Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: merge stable #785

Merged
merged 4 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 74 additions & 27 deletions l1-contracts/contracts/bridgehub/Bridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {BridgehubL2TransactionRequest, L2Message, L2Log, TxStatus} from "../comm
import {AddressAliasHelper} from "../vendor/AddressAliasHelper.sol";
import {IMessageRoot} from "./IMessageRoot.sol";
import {ICTMDeploymentTracker} from "./ICTMDeploymentTracker.sol";
import {AssetHandlerNotRegistered, ZKChainLimitReached, Unauthorized, CTMAlreadyRegistered, CTMNotRegistered, ZeroChainId, ChainIdTooBig, SharedBridgeNotSet, BridgeHubAlreadyRegistered, AddressTooLow, MsgValueMismatch, WrongMagicValue, ZeroAddress} from "../common/L1ContractErrors.sol";
import {AssetHandlerNotRegistered, ZKChainLimitReached, CTMAlreadyRegistered, CTMNotRegistered, ZeroChainId, ChainIdTooBig, BridgeHubAlreadyRegistered, AddressTooLow, MsgValueMismatch, ZeroAddress, Unauthorized, SharedBridgeNotSet, WrongMagicValue, ChainIdAlreadyExists, ChainIdMismatch, ChainIdCantBeCurrentChain, EmptyAssetId, AssetIdNotSupported, IncorrectBridgeHubAddress} from "../common/L1ContractErrors.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
Expand Down Expand Up @@ -325,32 +325,7 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
bytes calldata _initData,
bytes[] calldata _factoryDeps
) external onlyOwnerOrAdmin nonReentrant whenNotPaused onlyL1 returns (uint256) {
if (_chainId == 0) {
revert ZeroChainId();
}
if (_chainId > type(uint48).max) {
revert ChainIdTooBig();
}
require(_chainId != block.chainid, "BH: chain id must not match current chainid");
if (_chainTypeManager == address(0)) {
revert ZeroAddress();
}
if (_baseTokenAssetId == bytes32(0)) {
revert ZeroAddress();
}

if (!chainTypeManagerIsRegistered[_chainTypeManager]) {
revert CTMNotRegistered();
}

require(assetIdIsRegistered[_baseTokenAssetId], "BH: asset id not registered");

if (assetRouter == address(0)) {
revert SharedBridgeNotSet();
}
if (chainTypeManager[_chainId] != address(0)) {
revert BridgeHubAlreadyRegistered();
}
_validateChainParams({_chainId: _chainId, _assetId: _baseTokenAssetId, _chainTypeManager: _chainTypeManager});

chainTypeManager[_chainId] = _chainTypeManager;

Expand Down Expand Up @@ -786,6 +761,78 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
});
}

/// @dev Registers an already deployed chain with the bridgehub
/// @param _chainId The chain Id of the chain
/// @param _zkChain Address of the zkChain
function registerAlreadyDeployedZKChain(uint256 _chainId, address _zkChain) external onlyOwner onlyL1 {
if (_zkChain == address(0)) {
revert ZeroAddress();
}
if (zkChainMap.contains(_chainId)) {
revert ChainIdAlreadyExists();
}
if (IZKChain(_zkChain).getChainId() != _chainId) {
revert ChainIdMismatch();
}

address ctm = IZKChain(_zkChain).getChainTypeManager();
address chainAdmin = IZKChain(_zkChain).getAdmin();
bytes32 chainBaseTokenAssetId = IZKChain(_zkChain).getBaseTokenAssetId();
address bridgeHub = IZKChain(_zkChain).getBridgehub();

if (bridgeHub != address(this)) {
revert IncorrectBridgeHubAddress(bridgeHub);
}

_validateChainParams({_chainId: _chainId, _assetId: chainBaseTokenAssetId, _chainTypeManager: ctm});

chainTypeManager[_chainId] = ctm;

baseTokenAssetId[_chainId] = chainBaseTokenAssetId;
settlementLayer[_chainId] = block.chainid;

_registerNewZKChain(_chainId, _zkChain);
messageRoot.addNewChain(_chainId);

emit NewChain(_chainId, ctm, chainAdmin);
}

function _validateChainParams(uint256 _chainId, bytes32 _assetId, address _chainTypeManager) internal view {
if (_chainId == 0) {
revert ZeroChainId();
}

if (_chainId > type(uint48).max) {
revert ChainIdTooBig();
}

if (_chainId == block.chainid) {
revert ChainIdCantBeCurrentChain();
}

if (_chainTypeManager == address(0)) {
revert ZeroAddress();
}
if (_assetId == bytes32(0)) {
revert EmptyAssetId();
}

if (!chainTypeManagerIsRegistered[_chainTypeManager]) {
revert CTMNotRegistered();
}

if (!assetIdIsRegistered[_assetId]) {
revert AssetIdNotSupported(_assetId);
}

if (assetRouter == address(0)) {
revert SharedBridgeNotSet();
}
if (chainTypeManager[_chainId] != address(0)) {
revert BridgeHubAlreadyRegistered();
}
}

/*//////////////////////////////////////////////////////////////
PAUSE
//////////////////////////////////////////////////////////////*/
Expand Down
4 changes: 4 additions & 0 deletions l1-contracts/contracts/bridgehub/IBridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ interface IBridgehub is IAssetHandler, IL1AssetHandler {

function migrationPaused() external view returns (bool);

function admin() external view returns (address);

/// Mailbox forwarder

function proveL2MessageInclusion(
Expand Down Expand Up @@ -224,4 +226,6 @@ interface IBridgehub is IAssetHandler, IL1AssetHandler {
function L1_CHAIN_ID() external view returns (uint256);

function setLegacyBaseTokenAssetId(uint256 _chainId) external;

function registerAlreadyDeployedZKChain(uint256 _chainId, address _hyperchain) external;
}
14 changes: 12 additions & 2 deletions l1-contracts/contracts/common/L1ContractErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ error AssetHandlerDoesNotExist(bytes32 assetId);
error AssetIdMismatch(bytes32 expected, bytes32 supplied);
// 0x0bfcef28
error AlreadyWhitelisted(address);
// 0x04a0b7e9
error AssetIdNotSupported(bytes32 assetId);
// 0x6afd6c20
error BadReturnData();
// 0x6ef9a972
Expand All @@ -65,6 +67,12 @@ error CanOnlyProcessOneBatch();
error CantExecuteUnprovenBatches();
// 0xe18cb383
error CantRevertExecutedBatch();
// 0x24591d89
error ChainIdAlreadyExists();
// 0x717a1656
error ChainIdCantBeCurrentChain();
// 0xa179f8c9
error ChainIdMismatch();
// 0x78d2ed02
error ChainAlreadyLive();
// 0x8f620a06
Expand All @@ -91,6 +99,8 @@ error DiamondFreezeIncorrectState();
error DiamondNotFrozen();
//
error EmptyAddress();
// 0x2d4d012f
error EmptyAssetId();
// 0xfc7ab1d3
error EmptyBlobVersionHash(uint256 index);
//
Expand Down Expand Up @@ -124,6 +134,8 @@ error HashMismatch(bytes32 expected, bytes32 actual);
error ZKChainLimitReached();
//
error InsufficientAllowance(uint256 providedAllowance, uint256 requiredAmount);
// 0xdd381a4c
error IncorrectBridgeHubAddress(address bridgehub);
// 0x826fb11e
error InsufficientChainBalance();
// 0x356680b7
Expand Down Expand Up @@ -385,8 +397,6 @@ error IncorrectBatchBounds(
uint256 processFromProvided,
uint256 processToProvided
);
// 0x04a0b7e9
error AssetIdNotSupported(bytes32 assetId);
// 0x64107968
error AssetHandlerNotRegistered(bytes32 assetId);

Expand Down
66 changes: 66 additions & 0 deletions l1-contracts/test/foundry/l1/integration/GatewayTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.so
import {AdminFacet} from "contracts/state-transition/chain-deps/facets/Admin.sol";
import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol";
import {TxStatus} from "contracts/common/Messaging.sol";
import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol";
import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol";

contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer {
uint256 constant TEST_USERS_COUNT = 10;
Expand Down Expand Up @@ -215,6 +217,70 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T
vm.stopBroadcast();
}

function test_registerAlreadyDeployedZKChain() public {
gatewayScript.registerGateway();
IChainTypeManager stm = IChainTypeManager(l1Script.getCTM());
IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress());
address owner = Ownable(address(bridgeHub)).owner();

{
uint256 chainId = currentZKChainId++;
bytes32 baseTokenAssetId = DataEncoding.encodeNTVAssetId(chainId, ETH_TOKEN_ADDRESS);

address chain = _deployZkChain(
chainId,
baseTokenAssetId,
address(bridgehub.sharedBridge()),
owner,
stm.protocolVersion(),
stm.storedBatchZero(),
address(bridgehub)
);

address stmAddr = IZKChain(chain).getChainTypeManager();

vm.startBroadcast(owner);
bridgeHub.addChainTypeManager(stmAddr);
bridgeHub.addTokenAssetId(baseTokenAssetId);
bridgeHub.registerAlreadyDeployedZKChain(chainId, chain);
vm.stopBroadcast();

address bridgeHubStmForChain = bridgeHub.chainTypeManager(chainId);
bytes32 bridgeHubBaseAssetIdForChain = bridgeHub.baseTokenAssetId(chainId);
address bridgeHubChainAddressdForChain = bridgeHub.getZKChain(chainId);
address bhAddr = IZKChain(chain).getBridgehub();

assertEq(bridgeHubStmForChain, stmAddr);
assertEq(bridgeHubBaseAssetIdForChain, baseTokenAssetId);
assertEq(bridgeHubChainAddressdForChain, chain);
assertEq(bhAddr, address(bridgeHub));
}

{
uint256 chainId = currentZKChainId++;
bytes32 baseTokenAssetId = DataEncoding.encodeNTVAssetId(chainId, ETH_TOKEN_ADDRESS);
address chain = _deployZkChain(
chainId,
baseTokenAssetId,
address(bridgehub.sharedBridge()),
owner,
stm.protocolVersion(),
stm.storedBatchZero(),
address(bridgehub.sharedBridge())
);

address stmAddr = IZKChain(chain).getChainTypeManager();

vm.startBroadcast(owner);
bridgeHub.addTokenAssetId(baseTokenAssetId);
vm.expectRevert(
abi.encodeWithSelector(IncorrectBridgeHubAddress.selector, address(bridgehub.sharedBridge()))
);
bridgeHub.registerAlreadyDeployedZKChain(chainId, chain);
vm.stopBroadcast();
}
}

function finishMoveChain() public {
IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress());
IChainTypeManager ctm = IChainTypeManager(l1Script.getCTM());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {StdStorage, stdStorage} from "forge-std/Test.sol";

import {L1ContractDeployer} from "./_SharedL1ContractDeployer.t.sol";
import {RegisterZKChainScript} from "deploy-scripts/RegisterZKChain.s.sol";
import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol";
import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol";
import "@openzeppelin/contracts-v4/utils/Strings.sol";
import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol";
import {Diamond} from "contracts/state-transition/libraries/Diamond.sol";
import {DiamondProxy} from "contracts/state-transition/chain-deps/DiamondProxy.sol";
import {IDiamondInit} from "contracts/state-transition/chain-interfaces/IDiamondInit.sol";

contract ZKChainDeployer is L1ContractDeployer {
using stdStorage for StdStorage;

RegisterZKChainScript deployScript;

struct ZKChainDescription {
Expand Down Expand Up @@ -133,4 +141,39 @@ contract ZKChainDeployer is L1ContractDeployer {

// add this to be excluded from coverage report
function testZKChainDeployer() internal {}

function _deployZkChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _sharedBridge,
address _admin,
uint256 _protocolVersion,
bytes32 _storedBatchZero,
address _bridgeHub
) internal returns (address) {
Diamond.DiamondCutData memory diamondCut = abi.decode(
l1Script.getInitialDiamondCutData(),
(Diamond.DiamondCutData)
);
bytes memory initData;

{
initData = bytes.concat(
IDiamondInit.initialize.selector,
bytes32(_chainId),
bytes32(uint256(uint160(address(_bridgeHub)))),
bytes32(uint256(uint160(address(this)))),
bytes32(_protocolVersion),
bytes32(uint256(uint160(_admin))),
bytes32(uint256(uint160(address(0x1337)))),
_baseTokenAssetId,
bytes32(uint256(uint160(_sharedBridge))),
_storedBatchZero,
diamondCut.initCalldata
);
}
diamondCut.initCalldata = initData;
DiamondProxy hyperchainContract = new DiamondProxy{salt: bytes32(0)}(block.chainid, diamondCut);
return address(hyperchainContract);
}
}
Loading