From e0a27a3e72a850879c1ffb3a7bfff16e97d452ff Mon Sep 17 00:00:00 2001 From: kelemeno Date: Tue, 17 Sep 2024 13:04:47 +0100 Subject: [PATCH 01/27] bridge fixes --- .../contracts/bridge/BridgedStandardERC20.sol | 11 ++++++++++- l1-contracts/contracts/bridge/L2WrappedBaseToken.sol | 8 ++++++++ .../contracts/bridge/asset-router/IL2AssetRouter.sol | 4 +++- .../contracts/bridge/asset-router/L2AssetRouter.sol | 8 ++++---- .../bridge/interfaces/IBridgedStandardToken.sol | 4 ++++ .../contracts/bridge/ntv/NativeTokenVault.sol | 9 +++++++-- l1-contracts/src.ts/deploy.ts | 4 +++- 7 files changed, 39 insertions(+), 9 deletions(-) diff --git a/l1-contracts/contracts/bridge/BridgedStandardERC20.sol b/l1-contracts/contracts/bridge/BridgedStandardERC20.sol index bd8d01110..b6dddb4d9 100644 --- a/l1-contracts/contracts/bridge/BridgedStandardERC20.sol +++ b/l1-contracts/contracts/bridge/BridgedStandardERC20.sol @@ -43,6 +43,9 @@ contract BridgedStandardERC20 is ERC20PermitUpgradeable, IBridgedStandardToken, /// @dev Address of the native token vault that is used as trustee who can mint/burn tokens address public nativeTokenVault; + /// @dev The assetId of the token. + bytes32 public assetId; + /// @dev This also sets the native token vault to the default value if it is not set. /// It is not set only on the L2s for legacy tokens. modifier onlyNTV() { @@ -74,14 +77,20 @@ contract BridgedStandardERC20 is ERC20PermitUpgradeable, IBridgedStandardToken, /// @notice Initializes a contract token for later use. Expected to be used in the proxy. /// @dev Stores the L1 address of the bridge and set `name`/`symbol`/`decimals` getters that L1 token has. + /// @param _assetId The assetId of the token. /// @param _originToken Address of the origin token that can be deposited to mint this bridged token /// @param _data The additional data that the L1 bridge provide for initialization. /// In this case, it is packed `name`/`symbol`/`decimals` of the L1 token. - function bridgeInitialize(address _originToken, bytes calldata _data) external initializer returns (uint256) { + function bridgeInitialize( + bytes32 _assetId, + address _originToken, + bytes calldata _data + ) external initializer returns (uint256) { if (_originToken == address(0)) { revert ZeroAddress(); } originToken = _originToken; + assetId = _assetId; nativeTokenVault = msg.sender; diff --git a/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol b/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol index 4319a8b7c..cc825cbee 100644 --- a/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol +++ b/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol @@ -6,6 +6,7 @@ import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/tok import {IL2WrappedBaseToken} from "./interfaces/IL2WrappedBaseToken.sol"; import {IBridgedStandardToken} from "./interfaces/IBridgedStandardToken.sol"; +import {L2_NATIVE_TOKEN_VAULT_ADDR} from "../common/L2ContractAddresses.sol"; import {ZeroAddress, Unauthorized, BridgeMintNotImplemented, WithdrawFailed} from "../common/L1ContractErrors.sol"; @@ -29,6 +30,12 @@ contract L2WrappedBaseToken is ERC20PermitUpgradeable, IL2WrappedBaseToken, IBri /// @dev Address of the L1 base token. It can be deposited to mint this L2 token. address public override l1Address; + /// @dev Address of the native token vault. + address public override nativeTokenVault; + + /// @dev The assetId of the token. + bytes32 public override assetId; + modifier onlyBridge() { if (msg.sender != l2Bridge) { revert Unauthorized(msg.sender); @@ -70,6 +77,7 @@ contract L2WrappedBaseToken is ERC20PermitUpgradeable, IL2WrappedBaseToken, IBri } l2Bridge = _l2Bridge; l1Address = _l1Address; + nativeTokenVault = L2_NATIVE_TOKEN_VAULT_ADDR; // Set decoded values for name and symbol. __ERC20_init_unchained(name_, symbol_); diff --git a/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol index 34ce2ecd1..7cb2bd1ce 100644 --- a/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol @@ -2,9 +2,11 @@ pragma solidity ^0.8.20; +import {IAssetRouterBase} from "./IAssetRouterBase.sol"; + /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev -interface IL2AssetRouter { +interface IL2AssetRouter is IAssetRouterBase { event WithdrawalInitiatedAssetRouter( uint256 chainId, address indexed l2Sender, diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index b75eb58e8..e50dd4da1 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -101,7 +101,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { function setAssetHandlerAddressThisChain( bytes32 _assetRegistrationData, address _assetHandlerAddress - ) external override(AssetRouterBase) { + ) external override(AssetRouterBase, IAssetRouterBase) { _setAssetHandlerAddressThisChain(L2_NATIVE_TOKEN_VAULT_ADDR, _assetRegistrationData, _assetHandlerAddress); } @@ -117,7 +117,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { uint256, bytes32 _assetId, bytes calldata _transferData - ) public override onlyAssetRouterCounterpartOrSelf(L1_CHAIN_ID) { + ) public override(AssetRouterBase, IAssetRouterBase) onlyAssetRouterCounterpartOrSelf(L1_CHAIN_ID) { if (_assetId == BASE_TOKEN_ASSET_ID) { revert AssetIdNotSupported(BASE_TOKEN_ASSET_ID); } @@ -250,7 +250,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { } function _withdrawLegacy(address _l1Receiver, address _l2Token, uint256 _amount, address _sender) internal { - bytes32 assetId = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, getL1TokenAddress(_l2Token)); + bytes32 assetId = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, l1TokenAddress(_l2Token)); bytes memory data = abi.encode(_amount, _l1Receiver); _withdrawSender(assetId, data, _sender, false); } @@ -258,7 +258,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { /// @notice Legacy getL1TokenAddress. /// @param _l2Token The address of token on L2. /// @return The address of token on L1. - function getL1TokenAddress(address _l2Token) public view returns (address) { + function l1TokenAddress(address _l2Token) public view returns (address) { return IBridgedStandardToken(_l2Token).l1Address(); } diff --git a/l1-contracts/contracts/bridge/interfaces/IBridgedStandardToken.sol b/l1-contracts/contracts/bridge/interfaces/IBridgedStandardToken.sol index 952bc1871..2ba2a081b 100644 --- a/l1-contracts/contracts/bridge/interfaces/IBridgedStandardToken.sol +++ b/l1-contracts/contracts/bridge/interfaces/IBridgedStandardToken.sol @@ -18,4 +18,8 @@ interface IBridgedStandardToken { function originToken() external view returns (address); function l2Bridge() external view returns (address); + + function assetId() external view returns (bytes32); + + function nativeTokenVault() external view returns (address); } diff --git a/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol index 02e865d5d..749e4697b 100644 --- a/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol @@ -390,7 +390,7 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 bytes memory _erc20Data, address _expectedToken ) internal { - address deployedToken = _deployBridgedToken(_originChainId, _originToken, _erc20Data); + address deployedToken = _deployBridgedToken(_originChainId, _assetId, _originToken, _erc20Data); if (deployedToken != _expectedToken) { revert AddressMismatch(_expectedToken, deployedToken); } @@ -412,13 +412,18 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 /// @return The address of the beacon proxy (bridged token). function _deployBridgedToken( uint256 _originChainId, + bytes32 _assetId, address _originToken, bytes memory _erc20Data ) internal returns (address) { bytes32 salt = _getCreate2Salt(_originChainId, _originToken); BeaconProxy l2Token = _deployBeaconProxy(salt); - uint256 tokenOriginChainId = BridgedStandardERC20(address(l2Token)).bridgeInitialize(_originToken, _erc20Data); + uint256 tokenOriginChainId = BridgedStandardERC20(address(l2Token)).bridgeInitialize( + _assetId, + _originToken, + _erc20Data + ); tokenOriginChainId = tokenOriginChainId == 0 ? L1_CHAIN_ID : tokenOriginChainId; originChainId[DataEncoding.encodeNTVAssetId(tokenOriginChainId, _originToken)] = tokenOriginChainId; return address(l2Token); diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index cd3e03baf..adeb2d2b9 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -1351,7 +1351,9 @@ export class Deployer { const alreadyRegisteredInCTM = (await chainTypeManager.getZKChain(inputChainId)) != ethers.constants.AddressZero; if (l2LegacySharedBridge) { - console.log("Setting L2 legacy shared bridge in L1Nullifier"); + if (this.verbose) { + console.log("Setting L2 legacy shared bridge in L1Nullifier"); + } await this.setL2LegacySharedBridgeInL1Nullifier(inputChainId); nonce++; } From 18167a27f76ccc8c59697911c120a47ca97d75ce Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 18 Sep 2024 18:00:03 +0100 Subject: [PATCH 02/27] fixes --- l1-contracts/contracts/bridge/L1Nullifier.sol | 4 ++-- .../bridge/asset-router/AssetRouterBase.sol | 6 ++++++ .../bridge/asset-router/L1AssetRouter.sol | 6 +++--- .../bridge/asset-router/L2AssetRouter.sol | 20 +++++++++++++++++++ .../bridge/ntv/INativeTokenVault.sol | 7 +++++-- .../bridge/ntv/L2NativeTokenVault.sol | 8 +++++--- .../contracts/bridge/ntv/NativeTokenVault.sol | 15 +++++++++----- .../bridgehub/CTMDeploymentTracker.sol | 2 +- .../bridgehub/ICTMDeploymentTracker.sol | 2 +- .../_L1SharedBridge_Shared.t.sol | 2 +- 10 files changed, 54 insertions(+), 18 deletions(-) diff --git a/l1-contracts/contracts/bridge/L1Nullifier.sol b/l1-contracts/contracts/bridge/L1Nullifier.sol index 6dda093c9..100e0b04e 100644 --- a/l1-contracts/contracts/bridge/L1Nullifier.sol +++ b/l1-contracts/contracts/bridge/L1Nullifier.sol @@ -642,7 +642,7 @@ contract L1Nullifier is IL1Nullifier, ReentrancyGuard, Ownable2StepUpgradeable, uint16 _l2TxNumberInBatch, bytes32[] calldata _merkleProof ) external override { - bytes32 assetId = INativeTokenVault(address(l1NativeTokenVault)).getAssetId(block.chainid, _l1Token); + bytes32 assetId = INativeTokenVault(address(l1NativeTokenVault)).calculateAssetId(block.chainid, _l1Token); // For legacy deposits, the l2 receiver is not required to check tx data hash // bytes memory transferData = abi.encode(_amount, _depositSender); bytes memory assetData = abi.encode(_amount, address(0)); @@ -696,7 +696,7 @@ contract L1Nullifier is IL1Nullifier, ReentrancyGuard, Ownable2StepUpgradeable, ) external override onlyLegacyBridge { bytes memory assetData = abi.encode(_amount, _depositSender); /// the legacy bridge can only be used with L1 native tokens. - bytes32 assetId = INativeTokenVault(address(l1NativeTokenVault)).getAssetId(block.chainid, _l1Asset); + bytes32 assetId = INativeTokenVault(address(l1NativeTokenVault)).calculateAssetId(block.chainid, _l1Asset); _verifyAndClearFailedTransfer({ _checkedInLegacyBridge: true, diff --git a/l1-contracts/contracts/bridge/asset-router/AssetRouterBase.sol b/l1-contracts/contracts/bridge/asset-router/AssetRouterBase.sol index 1a27e825f..d6ca41bdf 100644 --- a/l1-contracts/contracts/bridge/asset-router/AssetRouterBase.sol +++ b/l1-contracts/contracts/bridge/asset-router/AssetRouterBase.sol @@ -149,6 +149,12 @@ abstract contract AssetRouterBase is IAssetRouterBase, Ownable2StepUpgradeable, }); } + /// @notice Ensures that token is registered with native token vault. + /// @dev Only used when deposit is made with legacy data encoding format. + /// @param _token The native token address which should be registered with native token vault. + /// @return assetId The asset ID of the token provided. + function _ensureTokenRegisteredWithNTV(address _token) internal virtual returns (bytes32 assetId); + /*////////////////////////////////////////////////////////////// PAUSE //////////////////////////////////////////////////////////////*/ diff --git a/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol index 6e44f4cae..20e423f47 100644 --- a/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol @@ -354,10 +354,10 @@ contract L1AssetRouter is AssetRouterBase, IL1AssetRouter, ReentrancyGuard { /// @notice Ensures that token is registered with native token vault. /// @dev Only used when deposit is made with legacy data encoding format. - /// @param _token The L1 token address which should be registered with native token vault. + /// @param _token The native token address which should be registered with native token vault. /// @return assetId The asset ID of the token provided. - function _ensureTokenRegisteredWithNTV(address _token) internal returns (bytes32 assetId) { - assetId = nativeTokenVault.getAssetId(block.chainid, _token); + function _ensureTokenRegisteredWithNTV(address _token) internal override returns (bytes32 assetId) { + assetId = nativeTokenVault.calculateAssetId(block.chainid, _token); if (nativeTokenVault.tokenAddress(assetId) == address(0)) { nativeTokenVault.registerToken(_token); } diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index e50dd4da1..2a8e1cff9 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -126,6 +126,22 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { emit DepositFinalizedAssetRouter(L1_CHAIN_ID, _assetId, _transferData); } + /*////////////////////////////////////////////////////////////// + Internal & Helpers + //////////////////////////////////////////////////////////////*/ + + // kl todo add handle Legaacy data here, which calls esureTokenRegisteredWithNTV + // have handleLegacyData called from somewhere. + + /// @inheritdoc AssetRouterBase + function _ensureTokenRegisteredWithNTV(address _token) internal override returns (bytes32 assetId) { + IL2NativeTokenVault nativeTokenVault = IL2NativeTokenVault(L2_NATIVE_TOKEN_VAULT_ADDR); + assetId = nativeTokenVault.calculateAssetId(block.chainid, _token); + if (nativeTokenVault.tokenAddress(assetId) == address(0)) { + nativeTokenVault.registerToken(_token); + } + } + /*////////////////////////////////////////////////////////////// LEGACY FUNCTIONS //////////////////////////////////////////////////////////////*/ @@ -139,6 +155,10 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { _withdrawSender(_assetId, _assetData, msg.sender, true); } + function withdrawToken(bytes32 _assetId, bytes memory _assetData) public override { + _withdrawSender(_assetId, _assetData, msg.sender, true); + } + /// @notice Initiates a withdrawal by burning funds on the contract and sending the message to L1 /// where tokens would be unlocked /// @param _assetId The asset id of the withdrawn asset diff --git a/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol index 0cd78cf54..f6887f6e6 100644 --- a/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol @@ -25,8 +25,8 @@ interface INativeTokenVault { /// @notice No access control is ok, since the bridging of tokens should be permissionless. This requires permissionless registration. function registerToken(address _l1Token) external; - /// @notice Used to get the assetId of a token - function getAssetId(uint256 _chainId, address _tokenAddress) external view returns (bytes32); + /// @notice Used to calculate the assetId of a token + function calculateAssetId(uint256 _chainId, address _tokenAddress) external view returns (bytes32); /// @notice Used to get the the ERC20 data for a token function getERC20Getters(address _token, uint256 _originChainId) external view returns (bytes memory); @@ -34,6 +34,9 @@ interface INativeTokenVault { /// @notice Used to get the token address of an assetId function tokenAddress(bytes32 assetId) external view returns (address); + /// @notice Used to get the assetId of a token + function assetId(address token) external view returns (bytes32); + /// @notice Used to get the expected bridged token address corresponding to its native counterpart function calculateCreate2TokenAddress(uint256 _originChainId, address _originToken) external view returns (address); } diff --git a/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol index e96a6d289..a6a0ff62d 100644 --- a/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol @@ -85,9 +85,10 @@ contract L2NativeTokenVault is IL2NativeTokenVault, NativeTokenVault { /// @notice Sets the legacy token asset ID for the given L2 token address. function setLegacyTokenAssetId(address _l2TokenAddress) public { address l1TokenAddress = L2_LEGACY_SHARED_BRIDGE.l1TokenAddress(_l2TokenAddress); - bytes32 assetId = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, l1TokenAddress); - tokenAddress[assetId] = _l2TokenAddress; - originChainId[assetId] = L1_CHAIN_ID; + bytes32 newAssetId = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, l1TokenAddress); + tokenAddress[newAssetId] = _l2TokenAddress; + assetId[_l2TokenAddress] = newAssetId; + originChainId[newAssetId] = L1_CHAIN_ID; } /// @notice Ensures that the token is deployed. @@ -114,6 +115,7 @@ contract L2NativeTokenVault is IL2NativeTokenVault, NativeTokenVault { revert AddressMismatch(_originToken, l1LegacyToken); } tokenAddress[_assetId] = expectedToken; + assetId[expectedToken] = _assetId; } else { super._ensureTokenDeployedInner({ _originChainId: _originChainId, diff --git a/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol index 749e4697b..5fb6394f5 100644 --- a/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/NativeTokenVault.sol @@ -52,12 +52,15 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 /// @dev A mapping assetId => tokenAddress mapping(bytes32 assetId => address tokenAddress) public tokenAddress; + /// @dev A mapping tokenAddress => assetId + mapping(address tokenAddress => bytes32 assetId) public assetId; + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[47] private __gap; + uint256[46] private __gap; /// @notice Checks that the message sender is the bridgehub. modifier onlyAssetRouter() { @@ -322,7 +325,7 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 /// @notice Returns the parsed assetId. /// @param _nativeToken The address of the token to be parsed. /// @dev Shows the assetId for a given chain and token address - function getAssetId(uint256 _chainId, address _nativeToken) external pure override returns (bytes32) { + function calculateAssetId(uint256 _chainId, address _nativeToken) external pure override returns (bytes32) { return DataEncoding.encodeNTVAssetId(_chainId, _nativeToken); } @@ -330,10 +333,11 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 /// @dev It does not perform any checks for the correctnesss of the token contract. /// @param _nativeToken The address of the token to be registered. function _unsafeRegisterNativeToken(address _nativeToken) internal { - bytes32 assetId = DataEncoding.encodeNTVAssetId(block.chainid, _nativeToken); + bytes32 newAssetId = DataEncoding.encodeNTVAssetId(block.chainid, _nativeToken); ASSET_ROUTER.setAssetHandlerAddressThisChain(bytes32(uint256(uint160(_nativeToken))), address(this)); - tokenAddress[assetId] = _nativeToken; - originChainId[assetId] = block.chainid; + tokenAddress[newAssetId] = _nativeToken; + assetId[_nativeToken] = newAssetId; + originChainId[newAssetId] = block.chainid; } function _handleChainBalanceIncrease( @@ -396,6 +400,7 @@ abstract contract NativeTokenVault is INativeTokenVault, IAssetHandler, Ownable2 } tokenAddress[_assetId] = _expectedToken; + assetId[_expectedToken] = _assetId; } /// @notice Calculates the bridged token address corresponding to native token counterpart. diff --git a/l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol b/l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol index 6ffee2482..781d12640 100644 --- a/l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol +++ b/l1-contracts/contracts/bridgehub/CTMDeploymentTracker.sol @@ -115,7 +115,7 @@ contract CTMDeploymentTracker is ICTMDeploymentTracker, ReentrancyGuard, Ownable require(_assetHandlerAddressOnCounterpart == L2_BRIDGEHUB_ADDR, "CTMDT: wrong counter part"); } - function getAssetId(address _l1CTM) public view override returns (bytes32) { + function calculateAssetId(address _l1CTM) public view override returns (bytes32) { return keccak256(abi.encode(block.chainid, address(this), bytes32(uint256(uint160(_l1CTM))))); } diff --git a/l1-contracts/contracts/bridgehub/ICTMDeploymentTracker.sol b/l1-contracts/contracts/bridgehub/ICTMDeploymentTracker.sol index 5f75aa990..1b7558f29 100644 --- a/l1-contracts/contracts/bridgehub/ICTMDeploymentTracker.sol +++ b/l1-contracts/contracts/bridgehub/ICTMDeploymentTracker.sol @@ -22,5 +22,5 @@ interface ICTMDeploymentTracker is IL1AssetDeploymentTracker { function registerCTMAssetOnL1(address _ctmAddress) external; - function getAssetId(address _l1CTM) external view returns (bytes32); + function calculateAssetId(address _l1CTM) external view returns (bytes32); } diff --git a/l1-contracts/test/foundry/l1/unit/concrete/Bridges/L1SharedBridge/_L1SharedBridge_Shared.t.sol b/l1-contracts/test/foundry/l1/unit/concrete/Bridges/L1SharedBridge/_L1SharedBridge_Shared.t.sol index c67fa6a36..abbf05a8c 100644 --- a/l1-contracts/test/foundry/l1/unit/concrete/Bridges/L1SharedBridge/_L1SharedBridge_Shared.t.sol +++ b/l1-contracts/test/foundry/l1/unit/concrete/Bridges/L1SharedBridge/_L1SharedBridge_Shared.t.sol @@ -211,7 +211,7 @@ contract L1AssetRouterTest is Test { // vm.mockCall( // address(bridgehubAddress), // abi.encodeWithSelector(IBridgehub.baseTokenAssetId.selector, address(token)), - // abi.encode(nativeTokenVault.getAssetId(address(token))) + // abi.encode(nativeTokenVault.calculateAssetId(address(token))) // ); token.mint(address(nativeTokenVault), amount); From 56b4e1faeba194b82ab0784b000ed5acaf5380b5 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Thu, 19 Sep 2024 09:15:26 +0100 Subject: [PATCH 03/27] register Token new function new msg format --- l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index 2a8e1cff9..36a9ec5a1 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -155,8 +155,9 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { _withdrawSender(_assetId, _assetData, msg.sender, true); } - function withdrawToken(bytes32 _assetId, bytes memory _assetData) public override { - _withdrawSender(_assetId, _assetData, msg.sender, true); + function withdrawToken(address _l2NativeToken, bytes memory _assetData) public { + bytes32 assetId = _ensureTokenRegisteredWithNTV(_l2NativeToken); + _withdrawSender(assetId, _assetData, msg.sender, true); } /// @notice Initiates a withdrawal by burning funds on the contract and sending the message to L1 From 1e009c8a507aa84eff2cac84c4c88cdfd040f563 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Thu, 26 Sep 2024 21:59:25 +0100 Subject: [PATCH 04/27] copied some test mods from interop branch --- .../l2/unit/erc20/L2Erc20BridgeTest.t.sol | 30 +++-- .../test/foundry/l2/unit/utils/L2Utils.sol | 110 +++++++++++++----- 2 files changed, 99 insertions(+), 41 deletions(-) diff --git a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol index 5e195353e..62c74ad36 100644 --- a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol +++ b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol @@ -18,7 +18,7 @@ import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; -import {L2Utils} from "../utils/L2Utils.sol"; +import {L2Utils, SystemContractsArgs} from "../utils/L2Utils.sol"; contract L2Erc20BridgeTest is Test { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. @@ -59,16 +59,24 @@ contract L2Erc20BridgeTest is Test { beaconProxyBytecodeHash := extcodehash(beaconProxy) } - L2Utils.initSystemContracts(); - L2Utils.forceDeployAssetRouter(L1_CHAIN_ID, ERA_CHAIN_ID, ownerWallet, l1BridgeWallet, address(0)); - L2Utils.forceDeployNativeTokenVault({ - _l1ChainId: L1_CHAIN_ID, - _aliasedOwner: ownerWallet, - _l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, - _legacySharedBridge: address(0), - _l2TokenBeacon: address(beacon), - _contractsDeployedAlready: true - }); + address l2SharedBridge = L2Utils.deploySharedBridgeLegacy( + L1_CHAIN_ID, + ERA_CHAIN_ID, + ownerWallet, + l1BridgeWallet, + beaconProxyBytecodeHash + ); + L2Utils.initSystemContracts(SystemContractsArgs({ + l1ChainId: L1_CHAIN_ID, + eraChainId: ERA_CHAIN_ID, + l1AssetRouter: L2_ASSET_ROUTER_ADDR, + legacySharedBridge: l2SharedBridge, + l2TokenBeacon: address(beacon), + l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, + aliasedOwner: ownerWallet, + contractsDeployedAlready: true + })); + } function performDeposit(address depositor, address receiver, uint256 amount) internal { diff --git a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol index 9da81fe5d..3d41ddeaa 100644 --- a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol @@ -5,16 +5,32 @@ pragma solidity ^0.8.20; import {Vm} from "forge-std/Vm.sol"; import "forge-std/console.sol"; -import {DEPLOYER_SYSTEM_CONTRACT, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {DEPLOYER_SYSTEM_CONTRACT, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR, L2_MESSAGE_ROOT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {IContractDeployer, L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {L2NativeTokenVault} from "contracts/bridge/ntv/L2NativeTokenVault.sol"; +import {L2SharedBridgeLegacy} from "contracts/bridge/L2SharedBridgeLegacy.sol"; +import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; +import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; +struct SystemContractsArgs { + uint256 l1ChainId; + uint256 eraChainId; + address l1AssetRouter; + address legacySharedBridge; + address l2TokenBeacon; + bytes32 l2TokenProxyBytecodeHash; + address aliasedOwner; + bool contractsDeployedAlready; +} + library L2Utils { address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); Vm internal constant vm = Vm(VM_ADDRESS); @@ -23,6 +39,7 @@ library L2Utils { string internal constant L2_ASSET_ROUTER_PATH = "./zkout/L2AssetRouter.sol/L2AssetRouter.json"; string internal constant L2_NATIVE_TOKEN_VAULT_PATH = "./zkout/L2NativeTokenVault.sol/L2NativeTokenVault.json"; + string internal constant BRIDGEHUB_PATH = "./zkout/Bridgehub.sol/Bridgehub.json"; /// @notice Returns the bytecode of a given era contract from a `zkout` folder. function readEraBytecode(string memory _filename) internal returns (bytes memory bytecode) { @@ -54,9 +71,33 @@ library L2Utils { * @dev Initializes the system contracts. * @dev It is a hack needed to make the tests be able to call system contracts directly. */ - function initSystemContracts() internal { + function initSystemContracts(SystemContractsArgs memory _args) internal { bytes memory contractDeployerBytecode = readSystemContractsBytecode("ContractDeployer"); vm.etch(DEPLOYER_SYSTEM_CONTRACT, contractDeployerBytecode); + forceDeploySystemContracts(_args); + } + + function forceDeploySystemContracts( + SystemContractsArgs memory _args + ) internal { + forceDeployBridgehub(_args.l1ChainId, _args.eraChainId, _args.aliasedOwner, _args.l1AssetRouter, _args.legacySharedBridge); + forceDeployAssetRouter(_args.l1ChainId, _args.eraChainId, _args.aliasedOwner,_args.l1AssetRouter, _args.legacySharedBridge); + forceDeployNativeTokenVault(_args.l1ChainId, _args.aliasedOwner, _args.l2TokenProxyBytecodeHash, _args.legacySharedBridge, _args.l2TokenBeacon, _args.contractsDeployedAlready); + } + + function forceDeployBridgehub( + uint256 _l1ChainId, + uint256 _eraChainId, + address _aliasedOwner, + address _l1AssetRouter, + address _legacySharedBridge + ) internal { + new Bridgehub(_l1ChainId, _aliasedOwner, 100); + forceDeployWithConstructor("Bridgehub", L2_BRIDGEHUB_ADDR, abi.encode(_l1ChainId, _aliasedOwner, 100)); + Bridgehub bridgehub = Bridgehub(L2_BRIDGEHUB_ADDR); + address l1CTMDeployer = address(0x1); + vm.prank(_aliasedOwner); + bridgehub.setAddresses(L2_ASSET_ROUTER_ADDR, ICTMDeploymentTracker(l1CTMDeployer), IMessageRoot(L2_MESSAGE_ROOT_ADDR)); } /// @notice Deploys the L2AssetRouter contract. @@ -76,22 +117,8 @@ library L2Utils { { new L2AssetRouter(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner); } + forceDeployWithConstructor("L2AssetRouter", L2_ASSET_ROUTER_ADDR, abi.encode(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner)); - bytes memory bytecode = readEraBytecode("L2AssetRouter"); - - bytes32 bytecodehash = L2ContractHelper.hashL2Bytecode(bytecode); - - IContractDeployer.ForceDeployment[] memory deployments = new IContractDeployer.ForceDeployment[](1); - deployments[0] = IContractDeployer.ForceDeployment({ - bytecodeHash: bytecodehash, - newAddress: L2_ASSET_ROUTER_ADDR, - callConstructor: true, - value: 0, - input: abi.encode(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner) - }); - - vm.prank(L2_FORCE_DEPLOYER_ADDR); - IContractDeployer(DEPLOYER_SYSTEM_CONTRACT).forceDeployOnAddresses(deployments); } /// @notice Deploys the L2NativeTokenVault contract. @@ -123,34 +150,57 @@ library L2Utils { _baseTokenAssetId: ethAssetId }); } + forceDeployWithConstructor("L2NativeTokenVault", L2_NATIVE_TOKEN_VAULT_ADDR, abi.encode(_l1ChainId, _aliasedOwner, _l2TokenProxyBytecodeHash, _legacySharedBridge, _l2TokenBeacon, _contractsDeployedAlready, address(0), ethAssetId)); + } - bytes memory bytecode = readEraBytecode("L2NativeTokenVault"); + function forceDeployWithConstructor( + string memory _contractName, + address _address, + bytes memory _constuctorArgs + ) public { + bytes memory bytecode = readEraBytecode(_contractName); bytes32 bytecodehash = L2ContractHelper.hashL2Bytecode(bytecode); IContractDeployer.ForceDeployment[] memory deployments = new IContractDeployer.ForceDeployment[](1); deployments[0] = IContractDeployer.ForceDeployment({ bytecodeHash: bytecodehash, - newAddress: L2_NATIVE_TOKEN_VAULT_ADDR, + newAddress: _address, callConstructor: true, value: 0, - // solhint-disable-next-line func-named-parameters - input: abi.encode( - _l1ChainId, - _aliasedOwner, - _l2TokenProxyBytecodeHash, - _legacySharedBridge, - _l2TokenBeacon, - _contractsDeployedAlready, - address(0), - ethAssetId - ) + input: _constuctorArgs }); vm.prank(L2_FORCE_DEPLOYER_ADDR); IContractDeployer(DEPLOYER_SYSTEM_CONTRACT).forceDeployOnAddresses(deployments); } + function deploySharedBridgeLegacy( + uint256 _l1ChainId, + uint256 _eraChainId, + address _aliasedOwner, + address _l1SharedBridge, + bytes32 _l2TokenProxyBytecodeHash + ) internal returns (address) { + bytes32 ethAssetId = DataEncoding.encodeNTVAssetId(_l1ChainId, ETH_TOKEN_ADDRESS); + + L2SharedBridgeLegacy bridge = new L2SharedBridgeLegacy(); + console.log("bridge", address(bridge)); + address proxyAdmin = address(0x1); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(bridge), + proxyAdmin, + abi.encodeWithSelector( + L2SharedBridgeLegacy.initialize.selector, + _l1SharedBridge, + _l2TokenProxyBytecodeHash, + _aliasedOwner + ) + ); + console.log("proxy", address(proxy)); + return address(proxy); + } + /// @notice Encodes the token data. /// @param name The name of the token. /// @param symbol The symbol of the token. From acdf8e99caa64cf1fcadda158e1e510ad286e1ff Mon Sep 17 00:00:00 2001 From: kelemeno Date: Fri, 27 Sep 2024 13:08:26 +0100 Subject: [PATCH 05/27] some fixes --- l1-contracts/.env | 1 + .../chain-interfaces/IAdmin.sol | 3 + l1-contracts/deploy-scripts/DeployL1.s.sol | 231 +++++++++--------- .../integration/BridgeHubInvariantTests.t.sol | 6 +- .../l1/integration/BridgehubTests.t.sol | 6 +- .../l1/integration/DeploymentTest.t.sol | 90 +++++-- ...atewayTests.t.sol => L1GatewayTests.t.sol} | 159 ++++-------- .../_SharedL1ContractDeployer.t.sol | 47 ++-- .../integration/_SharedZKChainDeployer.t.sol | 2 +- 9 files changed, 282 insertions(+), 263 deletions(-) rename l1-contracts/test/foundry/l1/integration/{GatewayTests.t.sol => L1GatewayTests.t.sol} (65%) diff --git a/l1-contracts/.env b/l1-contracts/.env index 25ec2b87f..0cbe2dbd1 100644 --- a/l1-contracts/.env +++ b/l1-contracts/.env @@ -44,3 +44,4 @@ TOKENS_CONFIG=/script-config/config-deploy-erc20.toml ZK_CHAIN_CONFIG=/script-config/register-zk-chain.toml ZK_CHAIN_OUTPUT=/script-out/output-deploy-zk-chain-era.toml FORCE_DEPLOYMENTS_CONFIG=/script-config/generate-force-deployments-data.toml +GATEWAY_PREPARATION_L1_CONFIG=/script-config/gateway-preparation-l1.toml diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol index 4a2ad7170..daf155e3a 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol @@ -6,6 +6,7 @@ import {IZKChainBase} from "../chain-interfaces/IZKChainBase.sol"; import {Diamond} from "../libraries/Diamond.sol"; import {FeeParams, PubdataPricingMode} from "../chain-deps/ZKChainStorage.sol"; +import {ZKChainCommitment} from "../../common/Config.sol"; /// @title The interface of the Admin Contract that controls access rights for contract management. /// @author Matter Labs @@ -149,4 +150,6 @@ interface IAdmin is IZKChainBase { /// @dev Similar to IL1AssetHandler interface, used to receive chains. function forwardedBridgeMint(bytes calldata _data, bool _contractAlreadyDeployed) external payable; + + function prepareChainCommitment() external view returns (ZKChainCommitment memory commitment); } diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 1112d917e..f06ec50f0 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -69,110 +69,111 @@ struct FixedForceDeploymentsData { bytes32 messageRootBytecodeHash; } -contract DeployL1Script is Script { - using stdToml for string; +// solhint-disable-next-line gas-struct-packing +struct DeployedAddresses { + BridgehubDeployedAddresses bridgehub; + StateTransitionDeployedAddresses stateTransition; + BridgesDeployedAddresses bridges; + L1NativeTokenVaultAddresses vaults; + DataAvailabilityDeployedAddresses daAddresses; + address transparentProxyAdmin; + address governance; + address chainAdmin; + address accessControlRestrictionAddress; + address blobVersionedHashRetriever; + address validatorTimelock; + address create2Factory; +} - address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; - address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; +// solhint-disable-next-line gas-struct-packing +struct L1NativeTokenVaultAddresses { + address l1NativeTokenVaultImplementation; + address l1NativeTokenVaultProxy; +} - // solhint-disable-next-line gas-struct-packing - struct DeployedAddresses { - BridgehubDeployedAddresses bridgehub; - StateTransitionDeployedAddresses stateTransition; - BridgesDeployedAddresses bridges; - L1NativeTokenVaultAddresses vaults; - DataAvailabilityDeployedAddresses daAddresses; - address transparentProxyAdmin; - address governance; - address chainAdmin; - address accessControlRestrictionAddress; - address blobVersionedHashRetriever; - address validatorTimelock; - address create2Factory; - } +struct DataAvailabilityDeployedAddresses { + address l1RollupDAValidator; + address l1ValidiumDAValidator; +} - // solhint-disable-next-line gas-struct-packing - struct L1NativeTokenVaultAddresses { - address l1NativeTokenVaultImplementation; - address l1NativeTokenVaultProxy; - } +// solhint-disable-next-line gas-struct-packing +struct BridgehubDeployedAddresses { + address bridgehubImplementation; + address bridgehubProxy; + address ctmDeploymentTrackerImplementation; + address ctmDeploymentTrackerProxy; + address messageRootImplementation; + address messageRootProxy; +} - struct DataAvailabilityDeployedAddresses { - address l1RollupDAValidator; - address l1ValidiumDAValidator; - } +// solhint-disable-next-line gas-struct-packing +struct BridgesDeployedAddresses { + address erc20BridgeImplementation; + address erc20BridgeProxy; + address sharedBridgeImplementation; + address sharedBridgeProxy; + address l1NullifierImplementation; + address l1NullifierProxy; + address bridgedStandardERC20Implementation; + address bridgedTokenBeacon; +} - // solhint-disable-next-line gas-struct-packing - struct BridgehubDeployedAddresses { - address bridgehubImplementation; - address bridgehubProxy; - address ctmDeploymentTrackerImplementation; - address ctmDeploymentTrackerProxy; - address messageRootImplementation; - address messageRootProxy; - } +// solhint-disable-next-line gas-struct-packing +struct Config { + uint256 l1ChainId; + address deployerAddress; + uint256 eraChainId; + address ownerAddress; + bool testnetVerifier; + ContractsConfig contracts; + TokensConfig tokens; +} - // solhint-disable-next-line gas-struct-packing - struct BridgesDeployedAddresses { - address erc20BridgeImplementation; - address erc20BridgeProxy; - address sharedBridgeImplementation; - address sharedBridgeProxy; - address l1NullifierImplementation; - address l1NullifierProxy; - address bridgedStandardERC20Implementation; - address bridgedTokenBeacon; - } +// solhint-disable-next-line gas-struct-packing +struct ContractsConfig { + bytes32 create2FactorySalt; + address create2FactoryAddr; + address multicall3Addr; + uint256 validatorTimelockExecutionDelay; + bytes32 genesisRoot; + uint256 genesisRollupLeafIndex; + bytes32 genesisBatchCommitment; + uint256 latestProtocolVersion; + bytes32 recursionNodeLevelVkHash; + bytes32 recursionLeafLevelVkHash; + bytes32 recursionCircuitsSetVksHash; + uint256 priorityTxMaxGasLimit; + PubdataPricingMode diamondInitPubdataPricingMode; + uint256 diamondInitBatchOverheadL1Gas; + uint256 diamondInitMaxPubdataPerBatch; + uint256 diamondInitMaxL2GasPerBatch; + uint256 diamondInitPriorityTxMaxPubdata; + uint256 diamondInitMinimalL2GasPrice; + address governanceSecurityCouncilAddress; + uint256 governanceMinDelay; + uint256 maxNumberOfChains; + bytes diamondCutData; + bytes32 bootloaderHash; + bytes32 defaultAAHash; +} + +struct TokensConfig { + address tokenWethAddress; +} + +contract DeployL1Script is Script { + using stdToml for string; + + address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; + address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - // solhint-disable-next-line gas-struct-packing - struct Config { - uint256 l1ChainId; - address deployerAddress; - uint256 eraChainId; - address ownerAddress; - bool testnetVerifier; - ContractsConfig contracts; - TokensConfig tokens; - } // solhint-disable-next-line gas-struct-packing struct GeneratedData { bytes forceDeploymentsData; } - // solhint-disable-next-line gas-struct-packing - struct ContractsConfig { - bytes32 create2FactorySalt; - address create2FactoryAddr; - address multicall3Addr; - uint256 validatorTimelockExecutionDelay; - bytes32 genesisRoot; - uint256 genesisRollupLeafIndex; - bytes32 genesisBatchCommitment; - uint256 latestProtocolVersion; - bytes32 recursionNodeLevelVkHash; - bytes32 recursionLeafLevelVkHash; - bytes32 recursionCircuitsSetVksHash; - uint256 priorityTxMaxGasLimit; - PubdataPricingMode diamondInitPubdataPricingMode; - uint256 diamondInitBatchOverheadL1Gas; - uint256 diamondInitMaxPubdataPerBatch; - uint256 diamondInitMaxL2GasPerBatch; - uint256 diamondInitPriorityTxMaxPubdata; - uint256 diamondInitMinimalL2GasPrice; - address governanceSecurityCouncilAddress; - uint256 governanceMinDelay; - uint256 maxNumberOfChains; - bytes diamondCutData; - bytes32 bootloaderHash; - bytes32 defaultAAHash; - } - - struct TokensConfig { - address tokenWethAddress; - } - - Config internal config; + Config public config; GeneratedData internal generatedData; DeployedAddresses internal addresses; @@ -186,6 +187,18 @@ contract DeployL1Script is Script { runInner(vm.envString("L1_CONFIG"), vm.envString("L1_OUTPUT")); } + function runForL2Test() public { + runL2Inner(vm.envString("L2_CONFIG"), vm.envString("L2_OUTPUT")); + } + + function getAddresses() public view returns (DeployedAddresses memory) { + return addresses; + } + + function getConfig() public view returns (Config memory) { + return config; + } + function runInner(string memory inputPath, string memory outputPath) internal { string memory root = vm.projectRoot(); inputPath = string.concat(root, inputPath); @@ -232,36 +245,16 @@ contract DeployL1Script is Script { saveOutput(outputPath); } - function getBridgehubProxyAddress() public view returns (address) { - return addresses.bridgehub.bridgehubProxy; - } - - function getSharedBridgeProxyAddress() public view returns (address) { - return addresses.bridges.sharedBridgeProxy; - } - - function getNativeTokenVaultProxyAddress() public view returns (address) { - return addresses.vaults.l1NativeTokenVaultProxy; - } - - function getL1NullifierProxyAddress() public view returns (address) { - return addresses.bridges.l1NullifierProxy; - } - - function getOwnerAddress() public view returns (address) { - return config.ownerAddress; - } - - function getCTM() public view returns (address) { - return addresses.stateTransition.chainTypeManagerProxy; - } + function runL2Inner(string memory inputPath, string memory outputPath) internal { + string memory root = vm.projectRoot(); + inputPath = string.concat(root, inputPath); + outputPath = string.concat(root, outputPath); - function getInitialDiamondCutData() public view returns (bytes memory) { - return config.contracts.diamondCutData; - } + initializeConfig(inputPath); - function getCTMDeploymentTrackerAddress() public view returns (address) { - return addresses.bridgehub.ctmDeploymentTrackerProxy; + // instantiateCreate2Factory(); + // deployIfNeededMulticall3(); + deployChainTypeManagerContract(); } function initializeConfig(string memory configPath) internal { diff --git a/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol b/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol index 6eb78944d..5d23e1ad6 100644 --- a/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol @@ -509,7 +509,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgehubProxyAddress, + bridgeHubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -565,7 +565,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgehubProxyAddress, + bridgeHubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -643,7 +643,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe } function getAddressesToExclude() public returns (address[] memory) { - addressesToExclude.push(bridgehubProxyAddress); + addressesToExclude.push(bridgeHubProxyAddress); addressesToExclude.push(address(sharedBridge)); for (uint256 i = 0; i < users.length; i++) { diff --git a/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol b/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol index 09b07cca0..a9e54825a 100644 --- a/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol @@ -509,7 +509,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgehubProxyAddress, + bridgeHubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -565,7 +565,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgehubProxyAddress, + bridgeHubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -643,7 +643,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe } function getAddressesToExclude() public returns (address[] memory) { - addressesToExclude.push(bridgehubProxyAddress); + addressesToExclude.push(bridgeHubProxyAddress); addressesToExclude.push(address(sharedBridge)); for (uint256 i = 0; i < users.length; i++) { diff --git a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol index 9224eea05..5f85d7d66 100644 --- a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol @@ -4,6 +4,8 @@ pragma solidity 0.8.24; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; +import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; + import {L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "contracts/bridgehub/IBridgehub.sol"; import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol"; import {MailboxFacet} from "contracts/state-transition/chain-deps/facets/Mailbox.sol"; @@ -22,6 +24,8 @@ import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAdd import {IL1ERC20Bridge} from "contracts/bridge/interfaces/IL1ERC20Bridge.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; +import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol"; contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker { uint256 constant TEST_USERS_COUNT = 10; @@ -69,30 +73,27 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, // equals the balance of L1Shared bridge. function test_initialDeployment() public { uint256 chainId = zkChainIds[0]; - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); - address newChainAddress = bridgehub.getZKChain(chainId); - address admin = IZKChain(bridgehub.getZKChain(chainId)).getAdmin(); - IChainTypeManager ctm = IChainTypeManager(bridgehub.chainTypeManager(chainId)); + address newChainAddress = bridgeHub.getZKChain(chainId); + address admin = IZKChain(bridgeHub.getZKChain(chainId)).getAdmin(); assertNotEq(admin, address(0)); assertNotEq(newChainAddress, address(0)); - address[] memory chainAddresses = bridgehub.getAllZKChains(); + address[] memory chainAddresses = bridgeHub.getAllZKChains(); assertEq(chainAddresses.length, 1); assertEq(chainAddresses[0], newChainAddress); - uint256[] memory chainIds = bridgehub.getAllZKChainChainIDs(); + uint256[] memory chainIds = bridgeHub.getAllZKChainChainIDs(); assertEq(chainIds.length, 1); assertEq(chainIds[0], chainId); - uint256 protocolVersion = ctm.getProtocolVersion(chainId); + uint256 protocolVersion = chainTypeManager.getProtocolVersion(chainId); assertEq(protocolVersion, 0); } - function test_bridgehubSetter() public { - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); + function test_bridgeHubSetter() public { uint256 chainId = zkChainIds[0]; - IChainTypeManager chainTypeManager = IChainTypeManager(bridgehub.chainTypeManager(chainId)); + // IChainTypeManager chainTypeManager = IChainTypeManager(bridgeHub.chainTypeManager(chainId)); uint256 randomChainId = 123456; vm.mockCall( @@ -100,14 +101,75 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, abi.encodeWithSelector(IChainTypeManager.getZKChainLegacy.selector, randomChainId), abi.encode(address(0x01)) ); - vm.store(address(bridgehub), keccak256(abi.encode(randomChainId, 205)), bytes32(uint256(uint160(1)))); + vm.store(address(bridgeHub), keccak256(abi.encode(randomChainId, 205)), bytes32(uint256(uint160(1)))); vm.store( - address(bridgehub), + address(bridgeHub), keccak256(abi.encode(randomChainId, 204)), bytes32(uint256(uint160(address(chainTypeManager)))) ); - bridgehub.setLegacyBaseTokenAssetId(randomChainId); - bridgehub.setLegacyChainAddress(randomChainId); + bridgeHub.setLegacyBaseTokenAssetId(randomChainId); + bridgeHub.setLegacyChainAddress(randomChainId); + } + + function test_registerAlreadyDeployedZKChain() public { + 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, + chainTypeManager.protocolVersion(), + chainTypeManager.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, + chainTypeManager.protocolVersion(), + chainTypeManager.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(); + } } // add this to be excluded from coverage report diff --git a/l1-contracts/test/foundry/l1/integration/GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol similarity index 65% rename from l1-contracts/test/foundry/l1/integration/GatewayTests.t.sol rename to l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index 0cfcbf049..443d431bb 100644 --- a/l1-contracts/test/foundry/l1/integration/GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -5,6 +5,8 @@ import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import "forge-std/console.sol"; +import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; + import {L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter, BridgehubMintCTMAssetData, BridgehubBurnCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol"; import {MailboxFacet} from "contracts/state-transition/chain-deps/facets/Mailbox.sol"; @@ -21,11 +23,13 @@ import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY import {L2CanonicalTransaction} from "contracts/common/Messaging.sol"; import {L2Message} from "contracts/common/Messaging.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; -import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR, L2_ASSET_ROUTER_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {IL1ERC20Bridge} from "contracts/bridge/interfaces/IL1ERC20Bridge.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IAssetRouterBase} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; +import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {FinalizeL1DepositParams} from "contracts/bridge/L1Nullifier.sol"; -import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {AdminFacet} from "contracts/state-transition/chain-deps/facets/Admin.sol"; @@ -35,6 +39,8 @@ import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {DeployedAddresses} from "deploy-scripts/DeployL1.s.sol"; + contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer { uint256 constant TEST_USERS_COUNT = 10; address[] public users; @@ -85,15 +91,14 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T _initializeGatewayScript(); - vm.deal(Ownable(l1Script.getBridgehubProxyAddress()).owner(), 100000000000000000000000000000000000); - vm.deal(l1Script.getOwnerAddress(), 100000000000000000000000000000000000); - migratingChain = IZKChain(IBridgehub(l1Script.getBridgehubProxyAddress()).getZKChain(migratingChainId)); - gatewayChain = IZKChain(IBridgehub(l1Script.getBridgehubProxyAddress()).getZKChain(gatewayChainId)); + vm.deal(ecosystemConfig.ownerAddress, 100000000000000000000000000000000000); + migratingChain = IZKChain(IBridgehub(bridgeHub).getZKChain(migratingChainId)); + gatewayChain = IZKChain(IBridgehub(bridgeHub).getZKChain(gatewayChainId)); vm.deal(migratingChain.getAdmin(), 100000000000000000000000000000000000); vm.deal(gatewayChain.getAdmin(), 100000000000000000000000000000000000); // vm.deal(msg.sender, 100000000000000000000000000000000000); - // vm.deal(l1Script.getBridgehubProxyAddress(), 100000000000000000000000000000000000); + // vm.deal(bridgeHub, 100000000000000000000000000000000000); } // This is a method to simplify porting the tests for now. @@ -124,7 +129,7 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T _extractAccessControlRestriction(migratingChain.getAdmin()), migratingChainId ); - // require(bridgehub.settlementLayer()) + require(bridgeHub.settlementLayer(migratingChainId) == gatewayChainId, "Migration failed"); } function test_l2Registration() public { @@ -138,13 +143,14 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T gatewayScript.registerAssetIdInBridgehub(address(0x01), bytes32(0)); } - function test_finishMoveChain() public { - finishMoveChain(); - } - function test_startMessageToL3() public { - finishMoveChain(); - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); + _setUpGatewayWithFilterer(); + gatewayScript.migrateChainToGateway( + migratingChain.getAdmin(), + _extractAccessControlRestriction(migratingChain.getAdmin()), + migratingChainId + ); + IBridgehub bridgehub = IBridgehub(bridgeHub); uint256 expectedValue = 1000000000000000000000; L2TransactionRequestDirect memory request = _createL2TransactionRequestDirect( @@ -158,16 +164,6 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T bridgehub.requestL2TransactionDirect{value: expectedValue}(request); } - function test_forwardToL3OnGateway() public { - finishMoveChain(); - - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); - vm.chainId(12345); - vm.startBroadcast(SETTLEMENT_LAYER_RELAY_SENDER); - bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); - vm.stopBroadcast(); - } - function test_recoverFromFailedChainMigration() public { _setUpGatewayWithFilterer(); gatewayScript.migrateChainToGateway( @@ -177,16 +173,14 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T ); // Setup - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); - IChainTypeManager ctm = IChainTypeManager(l1Script.getCTM()); + IBridgehub bridgehub = IBridgehub(bridgeHub); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); bytes memory transferData; { IZKChain chain = IZKChain(bridgehub.getZKChain(migratingChainId)); - bytes memory initialDiamondCut = l1Script.getInitialDiamondCutData(); bytes memory chainData = abi.encode(chain.getProtocolVersion()); - bytes memory ctmData = abi.encode(address(1), msg.sender, ctm.protocolVersion(), initialDiamondCut); + bytes memory ctmData = abi.encode(address(1), msg.sender, chainTypeManager.protocolVersion(), ecosystemConfig.contracts.diamondCutData); BridgehubBurnCTMAssetData memory data = BridgehubBurnCTMAssetData({ chainId: migratingChainId, ctmData: ctmData, @@ -244,74 +238,12 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T vm.stopBroadcast(); } - function test_registerAlreadyDeployedZKChain() public { - gatewayScript.governanceRegisterGateway(); - - 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 test_migrateBackChain() public { + migrateBackChain(); } - function finishMoveChain() public { - IBridgehub bridgehub = IBridgehub(l1Script.getBridgehubProxyAddress()); - IChainTypeManager ctm = IChainTypeManager(l1Script.getCTM()); + function migrateBackChain() public { + IBridgehub bridgehub = IBridgehub(bridgeHub); IZKChain migratingChain = IZKChain(bridgehub.getZKChain(migratingChainId)); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); @@ -320,21 +252,34 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T vm.stopBroadcast(); bytes32 baseTokenAssetId = keccak256("baseTokenAssetId"); - bytes memory initialDiamondCut = l1Script.getInitialDiamondCutData(); - bytes memory chainData = abi.encode(AdminFacet(address(migratingChain)).prepareChainCommitment()); - bytes memory ctmData = abi.encode(baseTokenAssetId, msg.sender, ctm.protocolVersion(), initialDiamondCut); - BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ - chainId: mintChainId, - baseTokenAssetId: baseTokenAssetId, - ctmData: ctmData, - chainData: chainData - }); - bytes memory bridgehubMintData = abi.encode(data); - vm.startBroadcast(address(bridgehub.sharedBridge())); + uint256 currentChainId = block.chainid; + // we are already on L1, so we have to set another chain id, it cannot be GW or mintChainId. vm.chainId(migratingChainId); - bridgehub.bridgeMint(gatewayChainId, assetId, bridgehubMintData); - vm.stopBroadcast(); + vm.mockCall( + address(bridgeHub), + abi.encodeWithSelector(IBridgehub.proveL2MessageInclusion.selector), + abi.encode(true) + ); + vm.mockCall( + address(bridgehub), + abi.encodeWithSelector(IBridgehub.ctmAssetIdFromChainId.selector), + abi.encode(assetId) + ); + vm.mockCall( + address(chainTypeManager), + abi.encodeWithSelector(IChainTypeManager.protocolVersion.selector), + abi.encode(chainTypeManager.protocolVersion()) + ); + + // bytes memory initialDiamondCut = getInitialDiamondCutData(); + // gatewayScript. + gatewayScript.finishMigrateChainFromGateway( + migratingChain, + migratingChainId, + gatewayChainId + ); + vm.chainId(currentChainId); assertEq(bridgehub.baseTokenAssetId(mintChainId), baseTokenAssetId); diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol index b180f6090..5b98d4089 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol @@ -11,12 +11,19 @@ import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; import {L1NativeTokenVault} from "contracts/bridge/ntv/L1NativeTokenVault.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {DeployedAddresses, Config} from "deploy-scripts/DeployL1.s.sol"; + contract L1ContractDeployer is Test { using stdStorage for StdStorage; - address bridgehubProxyAddress; - address bridgehubOwnerAddress; + DeployL1Script l1Script; + DeployedAddresses public ecosystemAddresses; + Config public ecosystemConfig; + + address bridgeHubProxyAddress; + address bridgeHubOwnerAddress; Bridgehub bridgeHub; CTMDeploymentTracker ctmDeploymentTracker; @@ -25,7 +32,7 @@ contract L1ContractDeployer is Test { L1Nullifier public l1Nullifier; L1NativeTokenVault public l1NativeTokenVault; - DeployL1Script l1Script; + IChainTypeManager chainTypeManager; function _deployL1Contracts() internal { vm.setEnv("L1_CONFIG", "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml"); @@ -38,28 +45,36 @@ contract L1ContractDeployer is Test { "ZK_CHAIN_OUT", "/test/foundry/l1/integration/deploy-scripts/script-out/output-deploy-zk-chain-era.toml" ); + vm.setEnv("GATEWAY_PREPARATION_L1_CONFIG", "/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml"); l1Script = new DeployL1Script(); l1Script.runForTest(); - bridgehubProxyAddress = l1Script.getBridgehubProxyAddress(); - bridgeHub = Bridgehub(bridgehubProxyAddress); - - address sharedBridgeProxyAddress = l1Script.getSharedBridgeProxyAddress(); - sharedBridge = L1AssetRouter(sharedBridgeProxyAddress); - - address l1NullifierProxyAddress = l1Script.getL1NullifierProxyAddress(); - l1Nullifier = L1Nullifier(l1NullifierProxyAddress); + ecosystemAddresses = l1Script.getAddresses(); + ecosystemConfig = l1Script.getConfig(); - address l1NativeTokenVaultProxyAddress = l1Script.getNativeTokenVaultProxyAddress(); - l1NativeTokenVault = L1NativeTokenVault(payable(l1NativeTokenVaultProxyAddress)); + bridgeHub = Bridgehub(ecosystemAddresses.bridgehub.bridgehubProxy); + chainTypeManager = IChainTypeManager(ecosystemAddresses.stateTransition.chainTypeManagerProxy); + ctmDeploymentTracker = CTMDeploymentTracker(ecosystemAddresses.bridgehub.ctmDeploymentTrackerProxy); - ctmDeploymentTracker = CTMDeploymentTracker(l1Script.getCTMDeploymentTrackerAddress()); + sharedBridge = L1AssetRouter(ecosystemAddresses.bridges.sharedBridgeProxy); + l1Nullifier = L1Nullifier(ecosystemAddresses.bridges.l1NullifierProxy); + l1NativeTokenVault = L1NativeTokenVault(payable(ecosystemAddresses.vaults.l1NativeTokenVaultProxy)); _acceptOwnership(); _setEraBatch(); - bridgehubOwnerAddress = bridgeHub.owner(); + bridgeHubOwnerAddress = bridgeHub.owner(); + } + + function _deployL2Contracts() internal { + vm.setEnv("L2_CONFIG", "/test/foundry/l2/integration/script-config/config-deploy-l2.toml"); + vm.setEnv("L2_OUTPUT", "/test/foundry/l2/integration/script-out/output-deploy-l2.toml"); + + l1Script = new DeployL1Script(); + l1Script.runForL2Test(); + + chainTypeManager = IChainTypeManager(ecosystemAddresses.stateTransition.chainTypeManagerProxy); } function _acceptOwnership() private { @@ -80,7 +95,7 @@ contract L1ContractDeployer is Test { function _registerNewToken(address _tokenAddress) internal { bytes32 tokenAssetId = DataEncoding.encodeNTVAssetId(block.chainid, _tokenAddress); if (!bridgeHub.assetIdIsRegistered(tokenAssetId)) { - vm.prank(bridgehubOwnerAddress); + vm.prank(bridgeHubOwnerAddress); bridgeHub.addTokenAssetId(tokenAssetId); } } diff --git a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol index 6220818ef..108f9ce4e 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol @@ -163,7 +163,7 @@ contract ZKChainDeployer is L1ContractDeployer { address _bridgeHub ) internal returns (address) { Diamond.DiamondCutData memory diamondCut = abi.decode( - l1Script.getInitialDiamondCutData(), + ecosystemConfig.contracts.diamondCutData, (Diamond.DiamondCutData) ); bytes memory initData; From 9791cec335c074cf17865ca06bbef4c51b3d8884 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Fri, 27 Sep 2024 13:25:22 +0100 Subject: [PATCH 06/27] linting --- .../bridge/asset-router/L2AssetRouter.sol | 4 +- l1-contracts/deploy-scripts/DeployL1.s.sol | 1 - .../deploy-scripts/GatewayPreparation.s.sol | 106 +++++++++++++- .../l1/integration/DeploymentTest.t.sol | 3 +- .../GatewayPreparationForTests.sol | 4 +- .../l1/integration/L1GatewayTests.t.sol | 15 +- .../integration/_SharedGatewayDeployer.t.sol | 4 +- .../_SharedL1ContractDeployer.t.sol | 6 +- .../script-config/gateway-preparation-l1.toml | 11 ++ .../foundry/l2/integration/L2Gateway.t.sol | 133 ++++++++++++++++++ .../l2/unit/erc20/L2Erc20BridgeTest.t.sol | 23 +-- .../test/foundry/l2/unit/utils/L2Utils.sol | 57 ++++++-- 12 files changed, 325 insertions(+), 42 deletions(-) create mode 100644 l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml create mode 100644 l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index 36a9ec5a1..187039464 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -131,7 +131,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { //////////////////////////////////////////////////////////////*/ // kl todo add handle Legaacy data here, which calls esureTokenRegisteredWithNTV - // have handleLegacyData called from somewhere. + // have handleLegacyData called from somewhere. /// @inheritdoc AssetRouterBase function _ensureTokenRegisteredWithNTV(address _token) internal override returns (bytes32 assetId) { @@ -155,7 +155,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { _withdrawSender(_assetId, _assetData, msg.sender, true); } - function withdrawToken(address _l2NativeToken, bytes memory _assetData) public { + function withdrawToken(address _l2NativeToken, bytes memory _assetData) public { bytes32 assetId = _ensureTokenRegisteredWithNTV(_l2NativeToken); _withdrawSender(assetId, _assetData, msg.sender, true); } diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index f06ec50f0..b5a4a74a7 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -167,7 +167,6 @@ contract DeployL1Script is Script { address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - // solhint-disable-next-line gas-struct-packing struct GeneratedData { bytes forceDeploymentsData; diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index 91601d9bd..194f40ce9 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -22,6 +22,15 @@ import {GatewayTransactionFilterer} from "contracts/transactionFilterer/GatewayT import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {SET_ASSET_HANDLER_COUNTERPART_ENCODING_VERSION} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; import {CTM_DEPLOYMENT_TRACKER_ENCODING_VERSION} from "contracts/bridgehub/CTMDeploymentTracker.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAssetRouterBase} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; +import {L2_ASSET_ROUTER_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {FinalizeL1DepositParams} from "contracts/bridge/interfaces/IL1Nullifier.sol"; + +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; /// @notice Scripts that is responsible for preparing the chain to become a gateway contract GatewayPreparation is Script { @@ -44,6 +53,7 @@ contract GatewayPreparation is Script { address gatewayChainAdmin; address gatewayAccessControlRestriction; address gatewayChainProxyAdmin; + address l1NullifierProxy; bytes gatewayDiamondCutData; } @@ -70,7 +80,7 @@ contract GatewayPreparation is Script { l1ChainId = block.chainid; string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/script-config/gateway-preparation-l1.toml"); + string memory path = string.concat(root, vm.envString("GATEWAY_PREPARATION_L1_CONFIG")); string memory toml = vm.readFile(path); // Config file must be parsed key by key, otherwise values returned @@ -89,7 +99,8 @@ contract GatewayPreparation is Script { gatewayDiamondCutData: toml.readBytes("$.gateway_diamond_cut_data"), gatewayChainAdmin: toml.readAddress("$.chain_admin"), gatewayAccessControlRestriction: toml.readAddress("$.access_control_restriction"), - gatewayChainProxyAdmin: toml.readAddress("$.chain_proxy_admin") + gatewayChainProxyAdmin: toml.readAddress("$.chain_proxy_admin"), + l1NullifierProxy: toml.readAddress("$.l1_nullifier_proxy") }); } @@ -240,7 +251,7 @@ contract GatewayPreparation is Script { uint256 currentSettlementLayer = IBridgehub(config.bridgehub).settlementLayer(chainId); if (currentSettlementLayer == config.gatewayChainId) { - console.log("Chain already whitelisted as settlement layer"); + console.log("Chain already using gateway as its settlement layer"); saveOutput(bytes32(0)); return; } @@ -272,6 +283,95 @@ contract GatewayPreparation is Script { saveOutput(l2TxHash); } + /// @dev Calling this function requires private key to the admin of the chain + function startMigrateChainFromGateway( + address chainAdmin, + address accessControlRestriction, + uint256 chainId + ) public { + initializeConfig(); + + bytes32 chainAssetId = IBridgehub(config.bridgehub).ctmAssetIdFromChainId(chainId); + + uint256 currentSettlementLayer = IBridgehub(config.bridgehub).settlementLayer(chainId); + // if (currentSettlementLayer == config.l1ChainId) { + // console.log("Chain already using L1 as its settlement layer"); + // saveOutput(bytes32(0)); + // return; + // } + + // if (currentSettlementLayer == address(0)) { + // console.log("Chain has never used Gateway as its settlement layer"); + // saveOutput(bytes32(0)); + // return; + // } + + // bytes memory bridgehubData = abi.encode( + // BridgehubBurnCTMAssetData({ + // chainId: chainId, + // ctmData: abi.encode(chainAdmin, config.diamondCutData), + // chainData: abi.encode(IZKChain(IBridgehub(config.bridgehub).getZKChain(chainId)).getProtocolVersion()) + // }) + // ); + + // L2AssetRouter l2AssetRouter = L2AssetRouter(L2_ASSET_ROUTER_ADDR); + // l2AssetRouter.withdraw( + // ctmAssetId, + // bridgehubBurnData + // ); + + // saveOutput(l2TxHash); + } + + function finishMigrateChainFromGateway( + IZKChain migratingChain, + uint256 migratingChainId, + uint256 gatewayChainId + ) public { + initializeConfig(); + + // TODO(EVM-746): Use L2-based chain admin contract + // address l2ChainAdmin = AddressAliasHelper.applyL1ToL2Alias(chainAdmin); + IBridgehub bridgehub = IBridgehub(config.bridgehub); + bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); + bytes32 baseTokenAssetId = bridgehub.baseTokenAssetId(migratingChainId); + IChainTypeManager ctm = IChainTypeManager(bridgehub.chainTypeManager(migratingChainId)); + + bytes memory chainData = abi.encode(IAdmin(address(migratingChain)).prepareChainCommitment()); + bytes memory ctmData = abi.encode( + baseTokenAssetId, + msg.sender, + ctm.protocolVersion(), + config.gatewayDiamondCutData + ); + BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + chainId: migratingChainId, + baseTokenAssetId: baseTokenAssetId, + ctmData: ctmData, + chainData: chainData + }); + bytes memory bridgehubMintData = abi.encode(data); + + L1Nullifier l1Nullifier = L1Nullifier(config.l1NullifierProxy); + + l1Nullifier.finalizeDeposit( + FinalizeL1DepositParams({ + chainId: migratingChainId, + l2BatchNumber: 1, + l2MessageIndex: 1, + l2Sender: L2_ASSET_ROUTER_ADDR, + l2TxNumberInBatch: 1, + message: abi.encodePacked( + IAssetRouterBase.finalizeDeposit.selector, + gatewayChainId, + assetId, + bridgehubMintData + ), + merkleProof: new bytes32[](0) + }) + ); + } + /// @dev Calling this function requires private key to the admin of the chain function setDAValidatorPair( address chainAdmin, diff --git a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol index 5f85d7d66..499535b8d 100644 --- a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol @@ -93,7 +93,6 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, function test_bridgeHubSetter() public { uint256 chainId = zkChainIds[0]; - // IChainTypeManager chainTypeManager = IChainTypeManager(bridgeHub.chainTypeManager(chainId)); uint256 randomChainId = 123456; vm.mockCall( @@ -129,7 +128,7 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, ); address stmAddr = IZKChain(chain).getChainTypeManager(); - + vm.startBroadcast(owner); bridgeHub.addChainTypeManager(stmAddr); bridgeHub.addTokenAssetId(baseTokenAssetId); diff --git a/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol b/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol index 271dfdf0c..edd4dc781 100644 --- a/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol +++ b/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol @@ -22,12 +22,12 @@ contract GatewayPreparationForTests is GatewayPreparation { ); config.governance = toml.readAddress("$.deployed_addresses.governance_addr"); - path = string.concat(root, vm.envString("GATEWAY_CONFIG")); + path = string.concat(root, vm.envString("GATEWAY_AS_CHAIN_CONFIG")); toml = vm.readFile(path); config.gatewayChainId = toml.readUint("$.chain.chain_chain_id"); - path = string.concat(root, vm.envString("GATEWAY_OUTPUT")); + path = string.concat(root, vm.envString("GATEWAY_AS_CHAIN_OUTPUT")); toml = vm.readFile(path); config.gatewayChainAdmin = toml.readAddress("$.chain_admin_addr"); diff --git a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index 443d431bb..f035d22f9 100644 --- a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -180,7 +180,12 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T { IZKChain chain = IZKChain(bridgehub.getZKChain(migratingChainId)); bytes memory chainData = abi.encode(chain.getProtocolVersion()); - bytes memory ctmData = abi.encode(address(1), msg.sender, chainTypeManager.protocolVersion(), ecosystemConfig.contracts.diamondCutData); + bytes memory ctmData = abi.encode( + address(1), + msg.sender, + chainTypeManager.protocolVersion(), + ecosystemConfig.contracts.diamondCutData + ); BridgehubBurnCTMAssetData memory data = BridgehubBurnCTMAssetData({ chainId: migratingChainId, ctmData: ctmData, @@ -254,7 +259,7 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T bytes32 baseTokenAssetId = keccak256("baseTokenAssetId"); uint256 currentChainId = block.chainid; - // we are already on L1, so we have to set another chain id, it cannot be GW or mintChainId. + // we are already on L1, so we have to set another chain id, it cannot be GW or mintChainId. vm.chainId(migratingChainId); vm.mockCall( address(bridgeHub), @@ -274,11 +279,7 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T // bytes memory initialDiamondCut = getInitialDiamondCutData(); // gatewayScript. - gatewayScript.finishMigrateChainFromGateway( - migratingChain, - migratingChainId, - gatewayChainId - ); + gatewayScript.finishMigrateChainFromGateway(migratingChain, migratingChainId, gatewayChainId); vm.chainId(currentChainId); diff --git a/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol index 66e0aa628..864035e40 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol @@ -17,11 +17,11 @@ contract GatewayDeployer is L1ContractDeployer { "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-zk-chain-10.toml" ); vm.setEnv( - "GATEWAY_CONFIG", + "GATEWAY_AS_CHAIN_CONFIG", "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-zk-chain-11.toml" ); vm.setEnv( - "GATEWAY_OUTPUT", + "GATEWAY_AS_CHAIN_OUTPUT", "/test/foundry/l1/integration/deploy-scripts/script-out/output-deploy-zk-chain-11.toml" ); diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol index 5b98d4089..2cfd6e5b6 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol @@ -14,7 +14,6 @@ import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {DeployedAddresses, Config} from "deploy-scripts/DeployL1.s.sol"; - contract L1ContractDeployer is Test { using stdStorage for StdStorage; @@ -45,7 +44,10 @@ contract L1ContractDeployer is Test { "ZK_CHAIN_OUT", "/test/foundry/l1/integration/deploy-scripts/script-out/output-deploy-zk-chain-era.toml" ); - vm.setEnv("GATEWAY_PREPARATION_L1_CONFIG", "/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml"); + vm.setEnv( + "GATEWAY_PREPARATION_L1_CONFIG", + "/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml" + ); l1Script = new DeployL1Script(); l1Script.runForTest(); diff --git a/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml b/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml new file mode 100644 index 000000000..666f86482 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml @@ -0,0 +1,11 @@ +bridgehub_proxy_addr = "0xe7ed3a4b2f210cb71033cfaeb3d15aa1bd1f7719" +ctm_deployment_tracker_proxy_addr = "0x69aaa8f53f6bcc1c9574b25e44712e85b63b01f7" +chain_type_manager_proxy_addr = "0x3301550e72d3042e9a1ca3350a66bdfec5b16ef8" +shared_bridge_proxy_addr = "0x04f59969801829d13f574129e2e1323c36d3239c" +governance = "0xc8c1e39e9173f80ba4d70e1910aeead49e75c0c6" +chain_chain_id = 506 +gateway_diamond_cut_data = "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e024f9e4e8fa2f08f768c1cb56bc4a6e3cbd88340000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000005caf5f2b06ca757c7cebacdcd6f163af45a6bb8300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000130e18b681000000000000000000000000000000000000000000000000000000001733894500000000000000000000000000000000000000000000000000000000fc57565f000000000000000000000000000000000000000000000000000000001cc5d1030000000000000000000000000000000000000000000000000000000021f603d700000000000000000000000000000000000000000000000000000000235d9eb50000000000000000000000000000000000000000000000000000000027ae4c16000000000000000000000000000000000000000000000000000000002878fe74000000000000000000000000000000000000000000000000000000003f42d5dd0000000000000000000000000000000000000000000000000000000041cf49bb000000000000000000000000000000000000000000000000000000004623c91d000000000000000000000000000000000000000000000000000000004dd18bf5000000000000000000000000000000000000000000000000000000006223258e0000000000000000000000000000000000000000000000000000000064b554ad0000000000000000000000000000000000000000000000000000000064bf8d6600000000000000000000000000000000000000000000000000000000a9f6d94100000000000000000000000000000000000000000000000000000000b784610700000000000000000000000000000000000000000000000000000000be6f11cf00000000000000000000000000000000000000000000000000000000e76db86500000000000000000000000000000000000000000000000000000000000000000000000000000000a0dcb2c61862bd44785423d454e5174a04f7d56e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000002e06d49e5b00000000000000000000000000000000000000000000000000000000086a56f8000000000000000000000000000000000000000000000000000000000ec6b0b700000000000000000000000000000000000000000000000000000000fe26699e0000000000000000000000000000000000000000000000000000000018e3a941000000000000000000000000000000000000000000000000000000001de72e340000000000000000000000000000000000000000000000000000000022c5cf230000000000000000000000000000000000000000000000000000000029b98c670000000000000000000000000000000000000000000000000000000033ce93fe000000000000000000000000000000000000000000000000000000003408e470000000000000000000000000000000000000000000000000000000003591c1a000000000000000000000000000000000000000000000000000000000396073820000000000000000000000000000000000000000000000000000000039d7d4aa0000000000000000000000000000000000000000000000000000000046657fe90000000000000000000000000000000000000000000000000000000052ef6b2c000000000000000000000000000000000000000000000000000000005a59033500000000000000000000000000000000000000000000000000000000631f4bac000000000000000000000000000000000000000000000000000000006a27e8b5000000000000000000000000000000000000000000000000000000006e9960c30000000000000000000000000000000000000000000000000000000074f4d30d0000000000000000000000000000000000000000000000000000000079823c9a000000000000000000000000000000000000000000000000000000007a0ed627000000000000000000000000000000000000000000000000000000007b30c8da00000000000000000000000000000000000000000000000000000000946ebad100000000000000000000000000000000000000000000000000000000960dcf240000000000000000000000000000000000000000000000000000000098acd7a6000000000000000000000000000000000000000000000000000000009cd939e4000000000000000000000000000000000000000000000000000000009d1b5a8100000000000000000000000000000000000000000000000000000000a1954fc500000000000000000000000000000000000000000000000000000000adfca15e00000000000000000000000000000000000000000000000000000000af6a2dcd00000000000000000000000000000000000000000000000000000000b22dd78e00000000000000000000000000000000000000000000000000000000b8c2f66f00000000000000000000000000000000000000000000000000000000bd7c541200000000000000000000000000000000000000000000000000000000c3bbd2d700000000000000000000000000000000000000000000000000000000cdffacc600000000000000000000000000000000000000000000000000000000d046815600000000000000000000000000000000000000000000000000000000d86970d800000000000000000000000000000000000000000000000000000000db1f0bf900000000000000000000000000000000000000000000000000000000e5355c7500000000000000000000000000000000000000000000000000000000e81e0ba100000000000000000000000000000000000000000000000000000000ea6c029c00000000000000000000000000000000000000000000000000000000ef3f0bae00000000000000000000000000000000000000000000000000000000f5c1182c00000000000000000000000000000000000000000000000000000000facd743b00000000000000000000000000000000000000000000000000000000fd791f3c000000000000000000000000000000000000000000000000000000000000000000000000000000003275e4b7e3d062c0e5ff5c7c5ab873f4562627f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b042901c70000000000000000000000000000000000000000000000000000000012f43dab00000000000000000000000000000000000000000000000000000000eb67241900000000000000000000000000000000000000000000000000000000263b7f8e000000000000000000000000000000000000000000000000000000006c0960f9000000000000000000000000000000000000000000000000000000007efda2ae00000000000000000000000000000000000000000000000000000000b473318e00000000000000000000000000000000000000000000000000000000d077255100000000000000000000000000000000000000000000000000000000ddcc9eec00000000000000000000000000000000000000000000000000000000e4948f4300000000000000000000000000000000000000000000000000000000e717bab7000000000000000000000000000000000000000000000000000000000000000000000000000000007ed427e1c7de31d21a520eeceb835686927d199800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000040f23da4300000000000000000000000000000000000000000000000000000000e12a61370000000000000000000000000000000000000000000000000000000098f8196200000000000000000000000000000000000000000000000000000000cf02827d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000868a8819e738818dabe8bfb671ae8e027372dd7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf0100055d760f11a3d737e7fd1816e600a4cd874a9f17f7a225d1f1c537c51a1e00000000000000000000000000000000000000000000000000000000044aa200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000182b8000000000000000000000000000000000000000000000000000000000ee6b2800000000000000000000000000000000000000000000000000000000000000001" +chain_proxy_admin = "0xfd285e11becbd6d81d32944947be1f97e321784f" +chain_admin = "0xa6fba37e028416e514b769ad767d3264775e78a1" +access_control_restriction = "0x9be3e70228e06b02306a934cf17a8eb7c09b048b" +l1_nullifier_proxy = "0xcaf6EA7c7c4912616e8ba88FcfD3D6401867BB1D" diff --git a/l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol b/l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol new file mode 100644 index 000000000..cdc96762e --- /dev/null +++ b/l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; + +import {L2Utils} from "../unit/utils/L2Utils.sol"; +import {SystemContractsArgs} from "../unit/utils/L2Utils.sol"; + +import {L1ContractDeployer} from "../../l1/integration/_SharedL1ContractDeployer.t.sol"; +import {ZKChainDeployer} from "../../l1/integration/_SharedZKChainDeployer.t.sol"; +import {TokenDeployer} from "../../l1/integration/_SharedTokenDeployer.t.sol"; + +contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { + // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. + // It is a bit easier to use EOA and it is sufficient for the tests. + address internal l1BridgeWallet = address(1); + address internal aliasedL1BridgeWallet; + + // The owner of the beacon and the native token vault + address internal ownerWallet = address(2); + + BridgedStandardERC20 internal standardErc20Impl; + + UpgradeableBeacon internal beacon; + BeaconProxy internal proxy; + + IL2AssetRouter l2AssetRouter = IL2AssetRouter(L2_ASSET_ROUTER_ADDR); + IBridgehub l2Bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); + + uint256 internal constant L1_CHAIN_ID = 9; + uint256 internal ERA_CHAIN_ID = 270; + address internal l1AssetRouter; + + address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); + address internal l1CTM = makeAddr("l1CTM"); + bytes32 internal ctmAssetId = keccak256(abi.encode(L1_CHAIN_ID, l1CTMDeployer, abi.encode(l1CTM))); + + bytes32 internal baseTokenAssetId = + keccak256(abi.encode(L1_CHAIN_ID, L2_NATIVE_TOKEN_VAULT_ADDR, abi.encode(ETH_TOKEN_ADDRESS))); + + bytes internal exampleChainCommitment; + + function setUp() public { + aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); + + standardErc20Impl = new BridgedStandardERC20(); + beacon = new UpgradeableBeacon(address(standardErc20Impl)); + beacon.transferOwnership(ownerWallet); + + // One of the purposes of deploying it here is to publish its bytecode + BeaconProxy beaconProxy = new BeaconProxy(address(beacon), new bytes(0)); + proxy = beaconProxy; + bytes32 beaconProxyBytecodeHash; + assembly { + beaconProxyBytecodeHash := extcodehash(beaconProxy) + } + + address l2SharedBridge = makeAddr("l2SharedBridge"); + + L2Utils.initSystemContracts( + SystemContractsArgs({ + l1ChainId: L1_CHAIN_ID, + eraChainId: ERA_CHAIN_ID, + l1AssetRouter: l1AssetRouter, + legacySharedBridge: l2SharedBridge, + l2TokenBeacon: address(beacon), + l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, + aliasedOwner: ownerWallet, + contractsDeployedAlready: true + }) + ); + + _deployL2Contracts(); + + vm.prank(l1AssetRouter); + l2AssetRouter.setAssetHandlerAddress(L1_CHAIN_ID, ctmAssetId, L2_BRIDGEHUB_ADDR); + vm.prank(l1CTMDeployer); + l2Bridgehub.setAssetHandlerAddress(bytes32(uint256(uint160(l1CTM))), address(chainTypeManager)); + } + + function test_gatewayShouldFinalizeDeposit() public { + finalizeDeposit(); + } + + function test_forwardToL3OnGateway() public { + finalizeDeposit(); + + IBridgehub bridgehub = IBridgehub(bridgeHub); + // vm.chainId(12345); + vm.startBroadcast(SETTLEMENT_LAYER_RELAY_SENDER); + bridgehub.forwardTransactionOnGateway(ERA_CHAIN_ID, bytes32(0), 0); + vm.stopBroadcast(); + } + + function finalizeDeposit() public { + bytes memory chainData = abi.encode(exampleChainCommitment); + bytes memory ctmData = abi.encode( + baseTokenAssetId, + msg.sender, + chainTypeManager.protocolVersion(), + ecosystemConfig.contracts.diamondCutData + ); + + BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + chainId: ERA_CHAIN_ID, + baseTokenAssetId: baseTokenAssetId, + ctmData: ctmData, + chainData: chainData + }); + vm.prank(l1AssetRouter); + l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + } +} diff --git a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol index 62c74ad36..c9902366f 100644 --- a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol +++ b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol @@ -66,17 +66,18 @@ contract L2Erc20BridgeTest is Test { l1BridgeWallet, beaconProxyBytecodeHash ); - L2Utils.initSystemContracts(SystemContractsArgs({ - l1ChainId: L1_CHAIN_ID, - eraChainId: ERA_CHAIN_ID, - l1AssetRouter: L2_ASSET_ROUTER_ADDR, - legacySharedBridge: l2SharedBridge, - l2TokenBeacon: address(beacon), - l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, - aliasedOwner: ownerWallet, - contractsDeployedAlready: true - })); - + L2Utils.initSystemContracts( + SystemContractsArgs({ + l1ChainId: L1_CHAIN_ID, + eraChainId: ERA_CHAIN_ID, + l1AssetRouter: L2_ASSET_ROUTER_ADDR, + legacySharedBridge: l2SharedBridge, + l2TokenBeacon: address(beacon), + l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, + aliasedOwner: ownerWallet, + contractsDeployedAlready: true + }) + ); } function performDeposit(address depositor, address receiver, uint256 amount) internal { diff --git a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol index 3d41ddeaa..5b678fce6 100644 --- a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol @@ -77,12 +77,29 @@ library L2Utils { forceDeploySystemContracts(_args); } - function forceDeploySystemContracts( - SystemContractsArgs memory _args - ) internal { - forceDeployBridgehub(_args.l1ChainId, _args.eraChainId, _args.aliasedOwner, _args.l1AssetRouter, _args.legacySharedBridge); - forceDeployAssetRouter(_args.l1ChainId, _args.eraChainId, _args.aliasedOwner,_args.l1AssetRouter, _args.legacySharedBridge); - forceDeployNativeTokenVault(_args.l1ChainId, _args.aliasedOwner, _args.l2TokenProxyBytecodeHash, _args.legacySharedBridge, _args.l2TokenBeacon, _args.contractsDeployedAlready); + function forceDeploySystemContracts(SystemContractsArgs memory _args) internal { + forceDeployBridgehub( + _args.l1ChainId, + _args.eraChainId, + _args.aliasedOwner, + _args.l1AssetRouter, + _args.legacySharedBridge + ); + forceDeployAssetRouter( + _args.l1ChainId, + _args.eraChainId, + _args.aliasedOwner, + _args.l1AssetRouter, + _args.legacySharedBridge + ); + forceDeployNativeTokenVault( + _args.l1ChainId, + _args.aliasedOwner, + _args.l2TokenProxyBytecodeHash, + _args.legacySharedBridge, + _args.l2TokenBeacon, + _args.contractsDeployedAlready + ); } function forceDeployBridgehub( @@ -97,7 +114,11 @@ library L2Utils { Bridgehub bridgehub = Bridgehub(L2_BRIDGEHUB_ADDR); address l1CTMDeployer = address(0x1); vm.prank(_aliasedOwner); - bridgehub.setAddresses(L2_ASSET_ROUTER_ADDR, ICTMDeploymentTracker(l1CTMDeployer), IMessageRoot(L2_MESSAGE_ROOT_ADDR)); + bridgehub.setAddresses( + L2_ASSET_ROUTER_ADDR, + ICTMDeploymentTracker(l1CTMDeployer), + IMessageRoot(L2_MESSAGE_ROOT_ADDR) + ); } /// @notice Deploys the L2AssetRouter contract. @@ -117,8 +138,11 @@ library L2Utils { { new L2AssetRouter(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner); } - forceDeployWithConstructor("L2AssetRouter", L2_ASSET_ROUTER_ADDR, abi.encode(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner)); - + forceDeployWithConstructor( + "L2AssetRouter", + L2_ASSET_ROUTER_ADDR, + abi.encode(_l1ChainId, _eraChainId, _l1AssetRouter, _legacySharedBridge, ethAssetId, _aliasedOwner) + ); } /// @notice Deploys the L2NativeTokenVault contract. @@ -150,7 +174,20 @@ library L2Utils { _baseTokenAssetId: ethAssetId }); } - forceDeployWithConstructor("L2NativeTokenVault", L2_NATIVE_TOKEN_VAULT_ADDR, abi.encode(_l1ChainId, _aliasedOwner, _l2TokenProxyBytecodeHash, _legacySharedBridge, _l2TokenBeacon, _contractsDeployedAlready, address(0), ethAssetId)); + forceDeployWithConstructor( + "L2NativeTokenVault", + L2_NATIVE_TOKEN_VAULT_ADDR, + abi.encode( + _l1ChainId, + _aliasedOwner, + _l2TokenProxyBytecodeHash, + _legacySharedBridge, + _l2TokenBeacon, + _contractsDeployedAlready, + address(0), + ethAssetId + ) + ); } function forceDeployWithConstructor( From 0c7cc45afa1d0f61c8ed215cc85379aa7b82494e Mon Sep 17 00:00:00 2001 From: kelemeno Date: Fri, 27 Sep 2024 19:57:10 +0100 Subject: [PATCH 07/27] fixed test --- .../deploy-scripts/GatewayPreparation.s.sol | 32 +++++------ .../deploy-scripts/RegisterZKChain.s.sol | 56 ++++++++++--------- .../l1/integration/DeploymentTest.t.sol | 2 +- .../l1/integration/L1GatewayTests.t.sol | 18 +++--- ...ts.sol => _GatewayPreparationForTests.sol} | 1 + .../integration/_SharedGatewayDeployer.t.sol | 2 +- .../integration/_SharedZKChainDeployer.t.sol | 5 ++ .../script-config/config-deploy-l1.toml | 2 +- .../script-config/gateway-preparation-l1.toml | 11 ---- 9 files changed, 65 insertions(+), 64 deletions(-) rename l1-contracts/test/foundry/l1/integration/{GatewayPreparationForTests.sol => _GatewayPreparationForTests.sol} (94%) delete mode 100644 l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index 194f40ce9..a3568f10c 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -32,6 +32,21 @@ import {FinalizeL1DepositParams} from "contracts/bridge/interfaces/IL1Nullifier. import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +// solhint-disable-next-line gas-struct-packing +struct Config { + address bridgehub; + address ctmDeploymentTracker; + address chainTypeManagerProxy; + address sharedBridgeProxy; + address governance; + uint256 gatewayChainId; + address gatewayChainAdmin; + address gatewayAccessControlRestriction; + address gatewayChainProxyAdmin; + address l1NullifierProxy; + bytes gatewayDiamondCutData; +} + /// @notice Scripts that is responsible for preparing the chain to become a gateway contract GatewayPreparation is Script { using stdToml for string; @@ -42,21 +57,6 @@ contract GatewayPreparation is Script { address deployerAddress; uint256 l1ChainId; - // solhint-disable-next-line gas-struct-packing - struct Config { - address bridgehub; - address ctmDeploymentTracker; - address chainTypeManagerProxy; - address sharedBridgeProxy; - address governance; - uint256 gatewayChainId; - address gatewayChainAdmin; - address gatewayAccessControlRestriction; - address gatewayChainProxyAdmin; - address l1NullifierProxy; - bytes gatewayDiamondCutData; - } - struct Output { bytes32 governanceL2TxHash; address gatewayTransactionFiltererImplementation; @@ -335,7 +335,7 @@ contract GatewayPreparation is Script { IBridgehub bridgehub = IBridgehub(config.bridgehub); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); bytes32 baseTokenAssetId = bridgehub.baseTokenAssetId(migratingChainId); - IChainTypeManager ctm = IChainTypeManager(bridgehub.chainTypeManager(migratingChainId)); + IChainTypeManager ctm = IChainTypeManager(config.chainTypeManagerProxy); bytes memory chainData = abi.encode(IAdmin(address(migratingChain)).prepareChainCommitment()); bytes memory ctmData = abi.encode( diff --git a/l1-contracts/deploy-scripts/RegisterZKChain.s.sol b/l1-contracts/deploy-scripts/RegisterZKChain.s.sol index 3a374e674..b1c8ae292 100644 --- a/l1-contracts/deploy-scripts/RegisterZKChain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterZKChain.s.sol @@ -28,38 +28,38 @@ import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; +// solhint-disable-next-line gas-struct-packing +struct Config { + address deployerAddress; + address ownerAddress; + uint256 chainChainId; + bool validiumMode; + uint256 bridgehubCreateNewChainSalt; + address validatorSenderOperatorCommitEth; + address validatorSenderOperatorBlobsEth; + address baseToken; + bytes32 baseTokenAssetId; + uint128 baseTokenGasPriceMultiplierNominator; + uint128 baseTokenGasPriceMultiplierDenominator; + address bridgehub; + // TODO(EVM-744): maybe rename to asset router + address sharedBridgeProxy; + address nativeTokenVault; + address chainTypeManagerProxy; + address validatorTimelock; + bytes diamondCutData; + bytes forceDeployments; + address governanceSecurityCouncilAddress; + uint256 governanceMinDelay; + address l1Nullifier; +} + contract RegisterZKChainScript is Script { using stdToml for string; address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; bytes32 internal constant STATE_TRANSITION_NEW_CHAIN_HASH = keccak256("NewZKChain(uint256,address)"); - // solhint-disable-next-line gas-struct-packing - struct Config { - address deployerAddress; - address ownerAddress; - uint256 chainChainId; - bool validiumMode; - uint256 bridgehubCreateNewChainSalt; - address validatorSenderOperatorCommitEth; - address validatorSenderOperatorBlobsEth; - address baseToken; - bytes32 baseTokenAssetId; - uint128 baseTokenGasPriceMultiplierNominator; - uint128 baseTokenGasPriceMultiplierDenominator; - address bridgehub; - // TODO(EVM-744): maybe rename to asset router - address sharedBridgeProxy; - address nativeTokenVault; - address chainTypeManagerProxy; - address validatorTimelock; - bytes diamondCutData; - bytes forceDeployments; - address governanceSecurityCouncilAddress; - uint256 governanceMinDelay; - address l1Nullifier; - } - struct Output { address governance; address diamondProxy; @@ -167,6 +167,10 @@ contract RegisterZKChainScript is Script { config.validatorSenderOperatorBlobsEth = toml.readAddress("$.chain.validator_sender_operator_blobs_eth"); } + function getConfig() public view returns (Config memory) { + return config; + } + function initializeConfigTest() internal { // Grab config from output of l1 deployment string memory root = vm.projectRoot(); diff --git a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol index 499535b8d..d9abe13da 100644 --- a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol @@ -88,7 +88,7 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, assertEq(chainIds[0], chainId); uint256 protocolVersion = chainTypeManager.getProtocolVersion(chainId); - assertEq(protocolVersion, 0); + assertEq(protocolVersion, 25); } function test_bridgeHubSetter() public { diff --git a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index f035d22f9..271dcc73e 100644 --- a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -39,8 +39,6 @@ import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {DeployedAddresses} from "deploy-scripts/DeployL1.s.sol"; - contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer { uint256 constant TEST_USERS_COUNT = 10; address[] public users; @@ -244,6 +242,12 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T } function test_migrateBackChain() public { + _setUpGatewayWithFilterer(); + gatewayScript.migrateChainToGateway( + migratingChain.getAdmin(), + _extractAccessControlRestriction(migratingChain.getAdmin()), + migratingChainId + ); migrateBackChain(); } @@ -256,7 +260,7 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T bridgehub.registerSettlementLayer(gatewayChainId, true); vm.stopBroadcast(); - bytes32 baseTokenAssetId = keccak256("baseTokenAssetId"); + bytes32 baseTokenAssetId = eraConfig.baseTokenAssetId; uint256 currentChainId = block.chainid; // we are already on L1, so we have to set another chain id, it cannot be GW or mintChainId. @@ -277,15 +281,13 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T abi.encode(chainTypeManager.protocolVersion()) ); - // bytes memory initialDiamondCut = getInitialDiamondCutData(); - // gatewayScript. gatewayScript.finishMigrateChainFromGateway(migratingChain, migratingChainId, gatewayChainId); vm.chainId(currentChainId); - assertEq(bridgehub.baseTokenAssetId(mintChainId), baseTokenAssetId); - IZKChain mintedZKChain = IZKChain(bridgehub.getZKChain(mintChainId)); - assertEq(mintedZKChain.getBaseTokenAssetId(), baseTokenAssetId); + assertEq(bridgehub.baseTokenAssetId(migratingChainId), baseTokenAssetId); + IZKChain migratingChainContract = IZKChain(bridgehub.getZKChain(migratingChainId)); + assertEq(migratingChainContract.getBaseTokenAssetId(), baseTokenAssetId); } // add this to be excluded from coverage report diff --git a/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol b/l1-contracts/test/foundry/l1/integration/_GatewayPreparationForTests.sol similarity index 94% rename from l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol rename to l1-contracts/test/foundry/l1/integration/_GatewayPreparationForTests.sol index edd4dc781..26e754d9f 100644 --- a/l1-contracts/test/foundry/l1/integration/GatewayPreparationForTests.sol +++ b/l1-contracts/test/foundry/l1/integration/_GatewayPreparationForTests.sol @@ -35,6 +35,7 @@ contract GatewayPreparationForTests is GatewayPreparation { config.gatewayAccessControlRestriction = toml.readAddress( "$.deployed_addresses.access_control_restriction_addr" ); + config.l1NullifierProxy = toml.readAddress("$.deployed_addresses.bridges.l1_nullifier_proxy_addr"); console.log("chain chain id = ", config.gatewayChainId); diff --git a/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol index 864035e40..bd72835af 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedGatewayDeployer.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {L1ContractDeployer} from "./_SharedL1ContractDeployer.t.sol"; -import {GatewayPreparationForTests} from "./GatewayPreparationForTests.sol"; +import {GatewayPreparationForTests} from "./_GatewayPreparationForTests.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; import "@openzeppelin/contracts-v4/utils/Strings.sol"; diff --git a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol index 108f9ce4e..e5af52539 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol @@ -13,6 +13,8 @@ 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"; +import {Config as ChainConfig} from "deploy-scripts/RegisterZKChain.s.sol"; + contract ZKChainDeployer is L1ContractDeployer { using stdStorage for StdStorage; @@ -29,6 +31,8 @@ contract ZKChainDeployer is L1ContractDeployer { uint128 baseTokenGasPriceMultiplierDenominator; } + ChainConfig internal eraConfig; + uint256 currentZKChainId = 10; uint256 eraZKChainId = 9; uint256[] public zkChainIds; @@ -47,6 +51,7 @@ contract ZKChainDeployer is L1ContractDeployer { vm.warp(100); deployScript.runForTest(); zkChainIds.push(eraZKChainId); + eraConfig = deployScript.getConfig(); } function _deployZKChain(address _baseToken) internal { diff --git a/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml b/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml index 5683d081a..d52a6b704 100644 --- a/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml +++ b/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml @@ -12,7 +12,7 @@ validator_timelock_execution_delay = 0 genesis_root = "0x1000000000000000000000000000000000000000000000000000000000000000" genesis_rollup_leaf_index = 1 genesis_batch_commitment = "0x1000000000000000000000000000000000000000000000000000000000000000" -latest_protocol_version = 0 +latest_protocol_version = 25 recursion_node_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" recursion_leaf_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" recursion_circuits_set_vks_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" diff --git a/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml b/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml deleted file mode 100644 index 666f86482..000000000 --- a/l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/gateway-preparation-l1.toml +++ /dev/null @@ -1,11 +0,0 @@ -bridgehub_proxy_addr = "0xe7ed3a4b2f210cb71033cfaeb3d15aa1bd1f7719" -ctm_deployment_tracker_proxy_addr = "0x69aaa8f53f6bcc1c9574b25e44712e85b63b01f7" -chain_type_manager_proxy_addr = "0x3301550e72d3042e9a1ca3350a66bdfec5b16ef8" -shared_bridge_proxy_addr = "0x04f59969801829d13f574129e2e1323c36d3239c" -governance = "0xc8c1e39e9173f80ba4d70e1910aeead49e75c0c6" -chain_chain_id = 506 -gateway_diamond_cut_data = "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e024f9e4e8fa2f08f768c1cb56bc4a6e3cbd88340000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000005caf5f2b06ca757c7cebacdcd6f163af45a6bb8300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000130e18b681000000000000000000000000000000000000000000000000000000001733894500000000000000000000000000000000000000000000000000000000fc57565f000000000000000000000000000000000000000000000000000000001cc5d1030000000000000000000000000000000000000000000000000000000021f603d700000000000000000000000000000000000000000000000000000000235d9eb50000000000000000000000000000000000000000000000000000000027ae4c16000000000000000000000000000000000000000000000000000000002878fe74000000000000000000000000000000000000000000000000000000003f42d5dd0000000000000000000000000000000000000000000000000000000041cf49bb000000000000000000000000000000000000000000000000000000004623c91d000000000000000000000000000000000000000000000000000000004dd18bf5000000000000000000000000000000000000000000000000000000006223258e0000000000000000000000000000000000000000000000000000000064b554ad0000000000000000000000000000000000000000000000000000000064bf8d6600000000000000000000000000000000000000000000000000000000a9f6d94100000000000000000000000000000000000000000000000000000000b784610700000000000000000000000000000000000000000000000000000000be6f11cf00000000000000000000000000000000000000000000000000000000e76db86500000000000000000000000000000000000000000000000000000000000000000000000000000000a0dcb2c61862bd44785423d454e5174a04f7d56e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000002e06d49e5b00000000000000000000000000000000000000000000000000000000086a56f8000000000000000000000000000000000000000000000000000000000ec6b0b700000000000000000000000000000000000000000000000000000000fe26699e0000000000000000000000000000000000000000000000000000000018e3a941000000000000000000000000000000000000000000000000000000001de72e340000000000000000000000000000000000000000000000000000000022c5cf230000000000000000000000000000000000000000000000000000000029b98c670000000000000000000000000000000000000000000000000000000033ce93fe000000000000000000000000000000000000000000000000000000003408e470000000000000000000000000000000000000000000000000000000003591c1a000000000000000000000000000000000000000000000000000000000396073820000000000000000000000000000000000000000000000000000000039d7d4aa0000000000000000000000000000000000000000000000000000000046657fe90000000000000000000000000000000000000000000000000000000052ef6b2c000000000000000000000000000000000000000000000000000000005a59033500000000000000000000000000000000000000000000000000000000631f4bac000000000000000000000000000000000000000000000000000000006a27e8b5000000000000000000000000000000000000000000000000000000006e9960c30000000000000000000000000000000000000000000000000000000074f4d30d0000000000000000000000000000000000000000000000000000000079823c9a000000000000000000000000000000000000000000000000000000007a0ed627000000000000000000000000000000000000000000000000000000007b30c8da00000000000000000000000000000000000000000000000000000000946ebad100000000000000000000000000000000000000000000000000000000960dcf240000000000000000000000000000000000000000000000000000000098acd7a6000000000000000000000000000000000000000000000000000000009cd939e4000000000000000000000000000000000000000000000000000000009d1b5a8100000000000000000000000000000000000000000000000000000000a1954fc500000000000000000000000000000000000000000000000000000000adfca15e00000000000000000000000000000000000000000000000000000000af6a2dcd00000000000000000000000000000000000000000000000000000000b22dd78e00000000000000000000000000000000000000000000000000000000b8c2f66f00000000000000000000000000000000000000000000000000000000bd7c541200000000000000000000000000000000000000000000000000000000c3bbd2d700000000000000000000000000000000000000000000000000000000cdffacc600000000000000000000000000000000000000000000000000000000d046815600000000000000000000000000000000000000000000000000000000d86970d800000000000000000000000000000000000000000000000000000000db1f0bf900000000000000000000000000000000000000000000000000000000e5355c7500000000000000000000000000000000000000000000000000000000e81e0ba100000000000000000000000000000000000000000000000000000000ea6c029c00000000000000000000000000000000000000000000000000000000ef3f0bae00000000000000000000000000000000000000000000000000000000f5c1182c00000000000000000000000000000000000000000000000000000000facd743b00000000000000000000000000000000000000000000000000000000fd791f3c000000000000000000000000000000000000000000000000000000000000000000000000000000003275e4b7e3d062c0e5ff5c7c5ab873f4562627f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b042901c70000000000000000000000000000000000000000000000000000000012f43dab00000000000000000000000000000000000000000000000000000000eb67241900000000000000000000000000000000000000000000000000000000263b7f8e000000000000000000000000000000000000000000000000000000006c0960f9000000000000000000000000000000000000000000000000000000007efda2ae00000000000000000000000000000000000000000000000000000000b473318e00000000000000000000000000000000000000000000000000000000d077255100000000000000000000000000000000000000000000000000000000ddcc9eec00000000000000000000000000000000000000000000000000000000e4948f4300000000000000000000000000000000000000000000000000000000e717bab7000000000000000000000000000000000000000000000000000000000000000000000000000000007ed427e1c7de31d21a520eeceb835686927d199800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000040f23da4300000000000000000000000000000000000000000000000000000000e12a61370000000000000000000000000000000000000000000000000000000098f8196200000000000000000000000000000000000000000000000000000000cf02827d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000868a8819e738818dabe8bfb671ae8e027372dd7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf0100055d760f11a3d737e7fd1816e600a4cd874a9f17f7a225d1f1c537c51a1e00000000000000000000000000000000000000000000000000000000044aa200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000182b8000000000000000000000000000000000000000000000000000000000ee6b2800000000000000000000000000000000000000000000000000000000000000001" -chain_proxy_admin = "0xfd285e11becbd6d81d32944947be1f97e321784f" -chain_admin = "0xa6fba37e028416e514b769ad767d3264775e78a1" -access_control_restriction = "0x9be3e70228e06b02306a934cf17a8eb7c09b048b" -l1_nullifier_proxy = "0xcaf6EA7c7c4912616e8ba88FcfD3D6401867BB1D" From 18dc862bc0e5cf7f0d3d294a5bffea0bd36d93b6 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sat, 28 Sep 2024 21:57:21 +0100 Subject: [PATCH 08/27] some fixes, enabling l2 integrationt tests --- l1-contracts/deploy-scripts/DeployL1.s.sol | 492 ++---------------- l1-contracts/deploy-scripts/DeployUtils.s.sol | 454 ++++++++++++++++ l1-contracts/package.json | 4 +- .../_SharedL1ContractDeployer.t.sol | 11 +- .../{L2Gateway.t.sol => L2GatewayTests.t.sol} | 72 +-- .../_SharedL2ContractDeployer.t.sol | 41 ++ .../l2/unit/erc20/L2Erc20BridgeTest.t.sol | 6 +- .../test/foundry/l2/unit/utils/L2Utils.sol | 40 +- 8 files changed, 625 insertions(+), 495 deletions(-) create mode 100644 l1-contracts/deploy-scripts/DeployUtils.s.sol rename l1-contracts/test/foundry/l2/integration/{L2Gateway.t.sol => L2GatewayTests.t.sol} (66%) create mode 100644 l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index b5a4a74a7..5380b56ca 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -56,126 +56,14 @@ import {IAssetRouterBase} from "contracts/bridge/asset-router/IAssetRouterBase.s import {L2ContractsBytecodesLib} from "./L2ContractsBytecodesLib.sol"; import {ValidiumL1DAValidator} from "contracts/state-transition/data-availability/ValidiumL1DAValidator.sol"; -struct FixedForceDeploymentsData { - uint256 l1ChainId; - uint256 eraChainId; - address l1AssetRouter; - bytes32 l2TokenProxyBytecodeHash; - address aliasedL1Governance; - uint256 maxNumberOfZKChains; - bytes32 bridgehubBytecodeHash; - bytes32 l2AssetRouterBytecodeHash; - bytes32 l2NtvBytecodeHash; - bytes32 messageRootBytecodeHash; -} - -// solhint-disable-next-line gas-struct-packing -struct DeployedAddresses { - BridgehubDeployedAddresses bridgehub; - StateTransitionDeployedAddresses stateTransition; - BridgesDeployedAddresses bridges; - L1NativeTokenVaultAddresses vaults; - DataAvailabilityDeployedAddresses daAddresses; - address transparentProxyAdmin; - address governance; - address chainAdmin; - address accessControlRestrictionAddress; - address blobVersionedHashRetriever; - address validatorTimelock; - address create2Factory; -} - -// solhint-disable-next-line gas-struct-packing -struct L1NativeTokenVaultAddresses { - address l1NativeTokenVaultImplementation; - address l1NativeTokenVaultProxy; -} - -struct DataAvailabilityDeployedAddresses { - address l1RollupDAValidator; - address l1ValidiumDAValidator; -} - -// solhint-disable-next-line gas-struct-packing -struct BridgehubDeployedAddresses { - address bridgehubImplementation; - address bridgehubProxy; - address ctmDeploymentTrackerImplementation; - address ctmDeploymentTrackerProxy; - address messageRootImplementation; - address messageRootProxy; -} +import {DeployUtils, GeneratedData, Config, DeployedAddresses, FixedForceDeploymentsData} from "./DeployUtils.s.sol"; -// solhint-disable-next-line gas-struct-packing -struct BridgesDeployedAddresses { - address erc20BridgeImplementation; - address erc20BridgeProxy; - address sharedBridgeImplementation; - address sharedBridgeProxy; - address l1NullifierImplementation; - address l1NullifierProxy; - address bridgedStandardERC20Implementation; - address bridgedTokenBeacon; -} - -// solhint-disable-next-line gas-struct-packing -struct Config { - uint256 l1ChainId; - address deployerAddress; - uint256 eraChainId; - address ownerAddress; - bool testnetVerifier; - ContractsConfig contracts; - TokensConfig tokens; -} - -// solhint-disable-next-line gas-struct-packing -struct ContractsConfig { - bytes32 create2FactorySalt; - address create2FactoryAddr; - address multicall3Addr; - uint256 validatorTimelockExecutionDelay; - bytes32 genesisRoot; - uint256 genesisRollupLeafIndex; - bytes32 genesisBatchCommitment; - uint256 latestProtocolVersion; - bytes32 recursionNodeLevelVkHash; - bytes32 recursionLeafLevelVkHash; - bytes32 recursionCircuitsSetVksHash; - uint256 priorityTxMaxGasLimit; - PubdataPricingMode diamondInitPubdataPricingMode; - uint256 diamondInitBatchOverheadL1Gas; - uint256 diamondInitMaxPubdataPerBatch; - uint256 diamondInitMaxL2GasPerBatch; - uint256 diamondInitPriorityTxMaxPubdata; - uint256 diamondInitMinimalL2GasPrice; - address governanceSecurityCouncilAddress; - uint256 governanceMinDelay; - uint256 maxNumberOfChains; - bytes diamondCutData; - bytes32 bootloaderHash; - bytes32 defaultAAHash; -} - -struct TokensConfig { - address tokenWethAddress; -} - -contract DeployL1Script is Script { +contract DeployL1Script is Script, DeployUtils { using stdToml for string; address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - // solhint-disable-next-line gas-struct-packing - struct GeneratedData { - bytes forceDeploymentsData; - } - - Config public config; - GeneratedData internal generatedData; - DeployedAddresses internal addresses; - function run() public { console.log("Deploying L1 contracts"); @@ -186,10 +74,6 @@ contract DeployL1Script is Script { runInner(vm.envString("L1_CONFIG"), vm.envString("L1_OUTPUT")); } - function runForL2Test() public { - runL2Inner(vm.envString("L2_CONFIG"), vm.envString("L2_OUTPUT")); - } - function getAddresses() public view returns (DeployedAddresses memory) { return addresses; } @@ -237,6 +121,7 @@ contract DeployL1Script is Script { deployBlobVersionedHashRetriever(); deployChainTypeManagerContract(); + registerChainTypeManager(); setChainTypeManagerInValidatorTimelock(); updateOwners(); @@ -244,71 +129,6 @@ contract DeployL1Script is Script { saveOutput(outputPath); } - function runL2Inner(string memory inputPath, string memory outputPath) internal { - string memory root = vm.projectRoot(); - inputPath = string.concat(root, inputPath); - outputPath = string.concat(root, outputPath); - - initializeConfig(inputPath); - - // instantiateCreate2Factory(); - // deployIfNeededMulticall3(); - deployChainTypeManagerContract(); - } - - function initializeConfig(string memory configPath) internal { - string memory toml = vm.readFile(configPath); - - config.l1ChainId = block.chainid; - config.deployerAddress = msg.sender; - - // Config file must be parsed key by key, otherwise values returned - // are parsed alfabetically and not by key. - // https://book.getfoundry.sh/cheatcodes/parse-toml - config.eraChainId = toml.readUint("$.era_chain_id"); - config.ownerAddress = toml.readAddress("$.owner_address"); - config.testnetVerifier = toml.readBool("$.testnet_verifier"); - - config.contracts.governanceSecurityCouncilAddress = toml.readAddress( - "$.contracts.governance_security_council_address" - ); - config.contracts.governanceMinDelay = toml.readUint("$.contracts.governance_min_delay"); - config.contracts.maxNumberOfChains = toml.readUint("$.contracts.max_number_of_chains"); - config.contracts.create2FactorySalt = toml.readBytes32("$.contracts.create2_factory_salt"); - if (vm.keyExistsToml(toml, "$.contracts.create2_factory_addr")) { - config.contracts.create2FactoryAddr = toml.readAddress("$.contracts.create2_factory_addr"); - } - config.contracts.validatorTimelockExecutionDelay = toml.readUint( - "$.contracts.validator_timelock_execution_delay" - ); - config.contracts.genesisRoot = toml.readBytes32("$.contracts.genesis_root"); - config.contracts.genesisRollupLeafIndex = toml.readUint("$.contracts.genesis_rollup_leaf_index"); - config.contracts.genesisBatchCommitment = toml.readBytes32("$.contracts.genesis_batch_commitment"); - config.contracts.latestProtocolVersion = toml.readUint("$.contracts.latest_protocol_version"); - config.contracts.recursionNodeLevelVkHash = toml.readBytes32("$.contracts.recursion_node_level_vk_hash"); - config.contracts.recursionLeafLevelVkHash = toml.readBytes32("$.contracts.recursion_leaf_level_vk_hash"); - config.contracts.recursionCircuitsSetVksHash = toml.readBytes32("$.contracts.recursion_circuits_set_vks_hash"); - config.contracts.priorityTxMaxGasLimit = toml.readUint("$.contracts.priority_tx_max_gas_limit"); - config.contracts.diamondInitPubdataPricingMode = PubdataPricingMode( - toml.readUint("$.contracts.diamond_init_pubdata_pricing_mode") - ); - config.contracts.diamondInitBatchOverheadL1Gas = toml.readUint( - "$.contracts.diamond_init_batch_overhead_l1_gas" - ); - config.contracts.diamondInitMaxPubdataPerBatch = toml.readUint( - "$.contracts.diamond_init_max_pubdata_per_batch" - ); - config.contracts.diamondInitMaxL2GasPerBatch = toml.readUint("$.contracts.diamond_init_max_l2_gas_per_batch"); - config.contracts.diamondInitPriorityTxMaxPubdata = toml.readUint( - "$.contracts.diamond_init_priority_tx_max_pubdata" - ); - config.contracts.diamondInitMinimalL2GasPrice = toml.readUint("$.contracts.diamond_init_minimal_l2_gas_price"); - config.contracts.defaultAAHash = toml.readBytes32("$.contracts.default_aa_hash"); - config.contracts.bootloaderHash = toml.readBytes32("$.contracts.bootloader_hash"); - - config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); - } - function initializeGeneratedData() internal { generatedData.forceDeploymentsData = prepareForceDeploymentsData(); } @@ -339,111 +159,31 @@ contract DeployL1Script is Script { function deployIfNeededMulticall3() internal { // Multicall3 is already deployed on public networks if (MULTICALL3_ADDRESS.code.length == 0) { - address contractAddress = deployViaCreate2(type(Multicall3).creationCode); + address contractAddress = deployViaCreate2(type(Multicall3).creationCode, ""); console.log("Multicall3 deployed at:", contractAddress); config.contracts.multicall3Addr = contractAddress; } else { config.contracts.multicall3Addr = MULTICALL3_ADDRESS; } } - - function deployVerifier() internal { - bytes memory code; - if (config.testnetVerifier) { - code = type(TestnetVerifier).creationCode; - } else { - code = type(Verifier).creationCode; - } - address contractAddress = deployViaCreate2(code); - console.log("Verifier deployed at:", contractAddress); - addresses.stateTransition.verifier = contractAddress; - } - - function deployDefaultUpgrade() internal { - address contractAddress = deployViaCreate2(type(DefaultUpgrade).creationCode); - console.log("DefaultUpgrade deployed at:", contractAddress); - addresses.stateTransition.defaultUpgrade = contractAddress; - } - - function deployGenesisUpgrade() internal { - bytes memory bytecode = abi.encodePacked(type(L1GenesisUpgrade).creationCode); - address contractAddress = deployViaCreate2(bytecode); - console.log("GenesisUpgrade deployed at:", contractAddress); - addresses.stateTransition.genesisUpgrade = contractAddress; - } - function deployDAValidators() internal { - address contractAddress = deployViaCreate2(Utils.readRollupDAValidatorBytecode()); + address contractAddress = deployViaCreate2(Utils.readRollupDAValidatorBytecode(), ""); console.log("L1RollupDAValidator deployed at:", contractAddress); addresses.daAddresses.l1RollupDAValidator = contractAddress; - contractAddress = deployViaCreate2(type(ValidiumL1DAValidator).creationCode); + contractAddress = deployViaCreate2(type(ValidiumL1DAValidator).creationCode, ""); console.log("L1ValidiumDAValidator deployed at:", contractAddress); addresses.daAddresses.l1ValidiumDAValidator = contractAddress; } - - function deployValidatorTimelock() internal { - uint32 executionDelay = uint32(config.contracts.validatorTimelockExecutionDelay); - bytes memory bytecode = abi.encodePacked( - type(ValidatorTimelock).creationCode, - abi.encode(config.deployerAddress, executionDelay, config.eraChainId) - ); - address contractAddress = deployViaCreate2(bytecode); - console.log("ValidatorTimelock deployed at:", contractAddress); - addresses.validatorTimelock = contractAddress; - } - - function deployGovernance() internal { - bytes memory bytecode = abi.encodePacked( - type(Governance).creationCode, - abi.encode( - config.ownerAddress, - config.contracts.governanceSecurityCouncilAddress, - config.contracts.governanceMinDelay - ) - ); - address contractAddress = deployViaCreate2(bytecode); - console.log("Governance deployed at:", contractAddress); - addresses.governance = contractAddress; - } - - function deployChainAdmin() internal { - bytes memory accessControlRestrictionBytecode = abi.encodePacked( - type(AccessControlRestriction).creationCode, - abi.encode(uint256(0), config.ownerAddress) - ); - - address accessControlRestriction = deployViaCreate2(accessControlRestrictionBytecode); - console.log("Access control restriction deployed at:", accessControlRestriction); - address[] memory restrictions = new address[](1); - restrictions[0] = accessControlRestriction; - addresses.accessControlRestrictionAddress = accessControlRestriction; - - bytes memory bytecode = abi.encodePacked(type(ChainAdmin).creationCode, abi.encode(restrictions)); - address contractAddress = deployViaCreate2(bytecode); - console.log("ChainAdmin deployed at:", contractAddress); - addresses.chainAdmin = contractAddress; - } - - function deployTransparentProxyAdmin() internal { - vm.startBroadcast(); - ProxyAdmin proxyAdmin = new ProxyAdmin(); - proxyAdmin.transferOwnership(addresses.governance); - vm.stopBroadcast(); - console.log("Transparent Proxy Admin deployed at:", address(proxyAdmin)); - addresses.transparentProxyAdmin = address(proxyAdmin); - } - function deployBridgehubContract() internal { - bytes memory bridgeHubBytecode = abi.encodePacked( + address bridgehubImplementation = deployViaCreate2( type(Bridgehub).creationCode, abi.encode(config.l1ChainId, config.ownerAddress, (config.contracts.maxNumberOfChains)) ); - address bridgehubImplementation = deployViaCreate2(bridgeHubBytecode); console.log("Bridgehub Implementation deployed at:", bridgehubImplementation); addresses.bridgehub.bridgehubImplementation = bridgehubImplementation; - bytes memory bytecode = abi.encodePacked( + address bridgehubProxy = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode( bridgehubImplementation, @@ -451,21 +191,19 @@ contract DeployL1Script is Script { abi.encodeCall(Bridgehub.initialize, (config.deployerAddress)) ) ); - address bridgehubProxy = deployViaCreate2(bytecode); console.log("Bridgehub Proxy deployed at:", bridgehubProxy); addresses.bridgehub.bridgehubProxy = bridgehubProxy; } function deployMessageRootContract() internal { - bytes memory messageRootBytecode = abi.encodePacked( + address messageRootImplementation = deployViaCreate2( type(MessageRoot).creationCode, abi.encode(addresses.bridgehub.bridgehubProxy) ); - address messageRootImplementation = deployViaCreate2(messageRootBytecode); console.log("MessageRoot Implementation deployed at:", messageRootImplementation); addresses.bridgehub.messageRootImplementation = messageRootImplementation; - bytes memory bytecode = abi.encodePacked( + address messageRootProxy = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode( messageRootImplementation, @@ -473,21 +211,19 @@ contract DeployL1Script is Script { abi.encodeCall(MessageRoot.initialize, ()) ) ); - address messageRootProxy = deployViaCreate2(bytecode); console.log("Message Root Proxy deployed at:", messageRootProxy); addresses.bridgehub.messageRootProxy = messageRootProxy; } function deployCTMDeploymentTracker() internal { - bytes memory ctmDTBytecode = abi.encodePacked( + address ctmDTImplementation = deployViaCreate2( type(CTMDeploymentTracker).creationCode, abi.encode(addresses.bridgehub.bridgehubProxy, addresses.bridges.sharedBridgeProxy) ); - address ctmDTImplementation = deployViaCreate2(ctmDTBytecode); console.log("CTM Deployment Tracker Implementation deployed at:", ctmDTImplementation); addresses.bridgehub.ctmDeploymentTrackerImplementation = ctmDTImplementation; - bytes memory bytecode = abi.encodePacked( + address ctmDTProxy = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode( ctmDTImplementation, @@ -495,7 +231,6 @@ contract DeployL1Script is Script { abi.encodeCall(CTMDeploymentTracker.initialize, (config.deployerAddress)) ) ); - address ctmDTProxy = deployViaCreate2(bytecode); console.log("CTM Deployment Tracker Proxy deployed at:", ctmDTProxy); addresses.bridgehub.ctmDeploymentTrackerProxy = ctmDTProxy; } @@ -503,144 +238,10 @@ contract DeployL1Script is Script { function deployBlobVersionedHashRetriever() internal { // solc contracts/state-transition/utils/blobVersionedHashRetriever.yul --strict-assembly --bin bytes memory bytecode = hex"600b600b5f39600b5ff3fe5f358049805f5260205ff3"; - address contractAddress = deployViaCreate2(bytecode); + address contractAddress = deployViaCreate2(bytecode, ""); console.log("BlobVersionedHashRetriever deployed at:", contractAddress); addresses.blobVersionedHashRetriever = contractAddress; } - - function deployChainTypeManagerContract() internal { - deployStateTransitionDiamondFacets(); - deployChainTypeManagerImplementation(); - deployChainTypeManagerProxy(); - registerChainTypeManager(); - } - - function deployStateTransitionDiamondFacets() internal { - address executorFacet = deployViaCreate2(type(ExecutorFacet).creationCode); - console.log("ExecutorFacet deployed at:", executorFacet); - addresses.stateTransition.executorFacet = executorFacet; - - address adminFacet = deployViaCreate2( - abi.encodePacked(type(AdminFacet).creationCode, abi.encode(config.l1ChainId)) - ); - console.log("AdminFacet deployed at:", adminFacet); - addresses.stateTransition.adminFacet = adminFacet; - - address mailboxFacet = deployViaCreate2( - abi.encodePacked(type(MailboxFacet).creationCode, abi.encode(config.eraChainId, config.l1ChainId)) - ); - console.log("MailboxFacet deployed at:", mailboxFacet); - addresses.stateTransition.mailboxFacet = mailboxFacet; - - address gettersFacet = deployViaCreate2(type(GettersFacet).creationCode); - console.log("GettersFacet deployed at:", gettersFacet); - addresses.stateTransition.gettersFacet = gettersFacet; - - address diamondInit = deployViaCreate2(type(DiamondInit).creationCode); - console.log("DiamondInit deployed at:", diamondInit); - addresses.stateTransition.diamondInit = diamondInit; - } - - function deployChainTypeManagerImplementation() internal { - bytes memory bytecode = abi.encodePacked( - type(ChainTypeManager).creationCode, - abi.encode(addresses.bridgehub.bridgehubProxy) - ); - address contractAddress = deployViaCreate2(bytecode); - console.log("ChainTypeManagerImplementation deployed at:", contractAddress); - addresses.stateTransition.chainTypeManagerImplementation = contractAddress; - } - - function deployChainTypeManagerProxy() internal { - Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](4); - facetCuts[0] = Diamond.FacetCut({ - facet: addresses.stateTransition.adminFacet, - action: Diamond.Action.Add, - isFreezable: false, - selectors: Utils.getAllSelectors(addresses.stateTransition.adminFacet.code) - }); - facetCuts[1] = Diamond.FacetCut({ - facet: addresses.stateTransition.gettersFacet, - action: Diamond.Action.Add, - isFreezable: false, - selectors: Utils.getAllSelectors(addresses.stateTransition.gettersFacet.code) - }); - facetCuts[2] = Diamond.FacetCut({ - facet: addresses.stateTransition.mailboxFacet, - action: Diamond.Action.Add, - isFreezable: true, - selectors: Utils.getAllSelectors(addresses.stateTransition.mailboxFacet.code) - }); - facetCuts[3] = Diamond.FacetCut({ - facet: addresses.stateTransition.executorFacet, - action: Diamond.Action.Add, - isFreezable: true, - selectors: Utils.getAllSelectors(addresses.stateTransition.executorFacet.code) - }); - - VerifierParams memory verifierParams = VerifierParams({ - recursionNodeLevelVkHash: config.contracts.recursionNodeLevelVkHash, - recursionLeafLevelVkHash: config.contracts.recursionLeafLevelVkHash, - recursionCircuitsSetVksHash: config.contracts.recursionCircuitsSetVksHash - }); - - FeeParams memory feeParams = FeeParams({ - pubdataPricingMode: config.contracts.diamondInitPubdataPricingMode, - batchOverheadL1Gas: uint32(config.contracts.diamondInitBatchOverheadL1Gas), - maxPubdataPerBatch: uint32(config.contracts.diamondInitMaxPubdataPerBatch), - maxL2GasPerBatch: uint32(config.contracts.diamondInitMaxL2GasPerBatch), - priorityTxMaxPubdata: uint32(config.contracts.diamondInitPriorityTxMaxPubdata), - minimalL2GasPrice: uint64(config.contracts.diamondInitMinimalL2GasPrice) - }); - - DiamondInitializeDataNewChain memory initializeData = DiamondInitializeDataNewChain({ - verifier: IVerifier(addresses.stateTransition.verifier), - verifierParams: verifierParams, - l2BootloaderBytecodeHash: config.contracts.bootloaderHash, - l2DefaultAccountBytecodeHash: config.contracts.defaultAAHash, - priorityTxMaxGasLimit: config.contracts.priorityTxMaxGasLimit, - feeParams: feeParams, - blobVersionedHashRetriever: addresses.blobVersionedHashRetriever - }); - - Diamond.DiamondCutData memory diamondCut = Diamond.DiamondCutData({ - facetCuts: facetCuts, - initAddress: addresses.stateTransition.diamondInit, - initCalldata: abi.encode(initializeData) - }); - - config.contracts.diamondCutData = abi.encode(diamondCut); - - ChainCreationParams memory chainCreationParams = ChainCreationParams({ - genesisUpgrade: addresses.stateTransition.genesisUpgrade, - genesisBatchHash: config.contracts.genesisRoot, - genesisIndexRepeatedStorageChanges: uint64(config.contracts.genesisRollupLeafIndex), - genesisBatchCommitment: config.contracts.genesisBatchCommitment, - diamondCut: diamondCut, - forceDeploymentsData: generatedData.forceDeploymentsData - }); - - ChainTypeManagerInitializeData memory diamondInitData = ChainTypeManagerInitializeData({ - owner: msg.sender, - validatorTimelock: addresses.validatorTimelock, - chainCreationParams: chainCreationParams, - protocolVersion: config.contracts.latestProtocolVersion - }); - - address contractAddress = deployViaCreate2( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - addresses.stateTransition.chainTypeManagerImplementation, - addresses.transparentProxyAdmin, - abi.encodeCall(ChainTypeManager.initialize, (diamondInitData)) - ) - ) - ); - console.log("ChainTypeManagerProxy deployed at:", contractAddress); - addresses.stateTransition.chainTypeManagerProxy = contractAddress; - } - function registerChainTypeManager() internal { Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy); vm.startBroadcast(msg.sender); @@ -689,11 +290,10 @@ contract DeployL1Script is Script { initAddress: address(0), initCalldata: "" }); - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(DiamondProxy).creationCode, abi.encode(config.l1ChainId, diamondCut) ); - address contractAddress = deployViaCreate2(bytecode); console.log("DiamondProxy deployed at:", contractAddress); addresses.stateTransition.diamondProxy = contractAddress; } @@ -710,29 +310,27 @@ contract DeployL1Script is Script { function deployL1NullifierImplementation() internal { // TODO(EVM-743): allow non-dev nullifier in the local deployment - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(L1NullifierDev).creationCode, // solhint-disable-next-line func-named-parameters abi.encode(addresses.bridgehub.bridgehubProxy, config.eraChainId, addresses.stateTransition.diamondProxy) ); - address contractAddress = deployViaCreate2(bytecode); console.log("L1NullifierImplementation deployed at:", contractAddress); addresses.bridges.l1NullifierImplementation = contractAddress; } function deployL1NullifierProxy() internal { bytes memory initCalldata = abi.encodeCall(L1Nullifier.initialize, (config.deployerAddress, 1, 1, 1, 0)); - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode(addresses.bridges.l1NullifierImplementation, addresses.transparentProxyAdmin, initCalldata) ); - address contractAddress = deployViaCreate2(bytecode); console.log("L1NullifierProxy deployed at:", contractAddress); addresses.bridges.l1NullifierProxy = contractAddress; } function deploySharedBridgeImplementation() internal { - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(L1AssetRouter).creationCode, // solhint-disable-next-line func-named-parameters abi.encode( @@ -743,18 +341,16 @@ contract DeployL1Script is Script { addresses.stateTransition.diamondProxy ) ); - address contractAddress = deployViaCreate2(bytecode); console.log("SharedBridgeImplementation deployed at:", contractAddress); addresses.bridges.sharedBridgeImplementation = contractAddress; } function deploySharedBridgeProxy() internal { bytes memory initCalldata = abi.encodeCall(L1AssetRouter.initialize, (config.deployerAddress)); - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode(addresses.bridges.sharedBridgeImplementation, addresses.transparentProxyAdmin, initCalldata) ); - address contractAddress = deployViaCreate2(bytecode); console.log("SharedBridgeProxy deployed at:", contractAddress); addresses.bridges.sharedBridgeProxy = contractAddress; } @@ -774,7 +370,7 @@ contract DeployL1Script is Script { } function deployErc20BridgeImplementation() internal { - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(L1ERC20Bridge).creationCode, abi.encode( addresses.bridges.l1NullifierProxy, @@ -783,18 +379,16 @@ contract DeployL1Script is Script { config.eraChainId ) ); - address contractAddress = deployViaCreate2(bytecode); console.log("Erc20BridgeImplementation deployed at:", contractAddress); addresses.bridges.erc20BridgeImplementation = contractAddress; } function deployErc20BridgeProxy() internal { bytes memory initCalldata = abi.encodeCall(L1ERC20Bridge.initialize, ()); - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode(addresses.bridges.erc20BridgeImplementation, addresses.transparentProxyAdmin, initCalldata) ); - address contractAddress = deployViaCreate2(bytecode); console.log("Erc20BridgeProxy deployed at:", contractAddress); addresses.bridges.erc20BridgeProxy = contractAddress; } @@ -807,22 +401,16 @@ contract DeployL1Script is Script { } function deployBridgedStandardERC20Implementation() internal { - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(BridgedStandardERC20).creationCode, // solhint-disable-next-line func-named-parameters abi.encode() ); - address contractAddress = deployViaCreate2(bytecode); console.log("BridgedStandardERC20Implementation deployed at:", contractAddress); addresses.bridges.bridgedStandardERC20Implementation = contractAddress; } function deployBridgedTokenBeacon() internal { - bytes memory bytecode = abi.encodePacked( - type(UpgradeableBeacon).creationCode, - // solhint-disable-next-line func-named-parameters - abi.encode(addresses.bridges.bridgedStandardERC20Implementation) - ); UpgradeableBeacon beacon = new UpgradeableBeacon(addresses.bridges.bridgedStandardERC20Implementation); address contractAddress = address(beacon); beacon.transferOwnership(config.ownerAddress); @@ -831,7 +419,7 @@ contract DeployL1Script is Script { } function deployL1NativeTokenVaultImplementation() internal { - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(L1NativeTokenVault).creationCode, // solhint-disable-next-line func-named-parameters abi.encode( @@ -841,7 +429,6 @@ contract DeployL1Script is Script { addresses.bridges.l1NullifierProxy ) ); - address contractAddress = deployViaCreate2(bytecode); console.log("L1NativeTokenVaultImplementation deployed at:", contractAddress); addresses.vaults.l1NativeTokenVaultImplementation = contractAddress; } @@ -851,11 +438,10 @@ contract DeployL1Script is Script { L1NativeTokenVault.initialize, (config.ownerAddress, addresses.bridges.bridgedTokenBeacon) ); - bytes memory bytecode = abi.encodePacked( + address contractAddress = deployViaCreate2( type(TransparentUpgradeableProxy).creationCode, abi.encode(addresses.vaults.l1NativeTokenVaultImplementation, addresses.transparentProxyAdmin, initCalldata) ); - address contractAddress = deployViaCreate2(bytecode); console.log("L1NativeTokenVaultProxy deployed at:", contractAddress); addresses.vaults.l1NativeTokenVaultProxy = contractAddress; @@ -908,6 +494,32 @@ contract DeployL1Script is Script { console.log("Owners updated"); } + function saveDiamondSelectors() public { + AdminFacet adminFacet = new AdminFacet(1); + GettersFacet gettersFacet = new GettersFacet(); + MailboxFacet mailboxFacet = new MailboxFacet(1, 1); + ExecutorFacet executorFacet = new ExecutorFacet(); + bytes4[] memory adminFacetSelectors = Utils.getAllSelectors(address(adminFacet).code); + bytes4[] memory gettersFacetSelectors = Utils.getAllSelectors(address(gettersFacet).code); + bytes4[] memory mailboxFacetSelectors = Utils.getAllSelectors(address(mailboxFacet).code); + bytes4[] memory executorFacetSelectors = Utils.getAllSelectors(address(executorFacet).code); + + string memory root = vm.projectRoot(); + string memory outputPath = string.concat(root, "/script-out/diamond-selectors.toml"); + + bytes memory adminFacetSelectorsBytes = abi.encode(adminFacetSelectors); + bytes memory gettersFacetSelectorsBytes = abi.encode(gettersFacetSelectors); + bytes memory mailboxFacetSelectorsBytes = abi.encode(mailboxFacetSelectors); + bytes memory executorFacetSelectorsBytes = abi.encode(executorFacetSelectors); + + vm.serializeBytes("diamond_selectors", "admin_facet_selectors", adminFacetSelectorsBytes); + vm.serializeBytes("diamond_selectors", "getters_facet_selectors", gettersFacetSelectorsBytes); + vm.serializeBytes("diamond_selectors", "mailbox_facet_selectors", mailboxFacetSelectorsBytes); + string memory toml = vm.serializeBytes("diamond_selectors", "executor_facet_selectors", executorFacetSelectorsBytes); + + vm.writeToml(toml, outputPath); + } + function saveOutput(string memory outputPath) internal { vm.serializeAddress("bridgehub", "bridgehub_proxy_addr", addresses.bridgehub.bridgehubProxy); vm.serializeAddress("bridgehub", "bridgehub_implementation_addr", addresses.bridgehub.bridgehubImplementation); @@ -1071,10 +683,6 @@ contract DeployL1Script is Script { vm.writeToml(toml, outputPath); } - function deployViaCreate2(bytes memory _bytecode) internal returns (address) { - return Utils.deployViaCreate2(_bytecode, config.contracts.create2FactorySalt, addresses.create2Factory); - } - function prepareForceDeploymentsData() internal view returns (bytes memory) { require(addresses.governance != address(0), "Governance address is not set"); @@ -1101,5 +709,5 @@ contract DeployL1Script is Script { } // add this to be excluded from coverage report - function test() internal {} + function test() internal virtual override {} } diff --git a/l1-contracts/deploy-scripts/DeployUtils.s.sol b/l1-contracts/deploy-scripts/DeployUtils.s.sol new file mode 100644 index 000000000..9ccee1373 --- /dev/null +++ b/l1-contracts/deploy-scripts/DeployUtils.s.sol @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +// solhint-disable no-console, gas-custom-errors + +import {Script, console2 as console} from "forge-std/Script.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {StateTransitionDeployedAddresses, Utils, L2_BRIDGEHUB_ADDRESS, L2_ASSET_ROUTER_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_MESSAGE_ROOT_ADDRESS} from "./Utils.sol"; +import {Multicall3} from "contracts/dev-contracts/Multicall3.sol"; +import {Verifier} from "contracts/state-transition/Verifier.sol"; +import {TestnetVerifier} from "contracts/state-transition/TestnetVerifier.sol"; +import {VerifierParams, IVerifier} from "contracts/state-transition/chain-interfaces/IVerifier.sol"; +import {DefaultUpgrade} from "contracts/upgrades/DefaultUpgrade.sol"; +import {Governance} from "contracts/governance/Governance.sol"; +import {L1GenesisUpgrade} from "contracts/upgrades/L1GenesisUpgrade.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {MessageRoot} from "contracts/bridgehub/MessageRoot.sol"; +import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol"; +import {L1NativeTokenVault} from "contracts/bridge/ntv/L1NativeTokenVault.sol"; +import {ExecutorFacet} from "contracts/state-transition/chain-deps/facets/Executor.sol"; +import {AdminFacet} from "contracts/state-transition/chain-deps/facets/Admin.sol"; +import {MailboxFacet} from "contracts/state-transition/chain-deps/facets/Mailbox.sol"; +import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol"; +import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol"; +import {ChainTypeManager} from "contracts/state-transition/ChainTypeManager.sol"; +import {ChainTypeManagerInitializeData, ChainCreationParams} from "contracts/state-transition/IChainTypeManager.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; +import {InitializeDataNewChain as DiamondInitializeDataNewChain} from "contracts/state-transition/chain-interfaces/IDiamondInit.sol"; +import {FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-deps/ZKChainStorage.sol"; +import {L1AssetRouter} from "contracts/bridge/asset-router/L1AssetRouter.sol"; +import {L1ERC20Bridge} from "contracts/bridge/L1ERC20Bridge.sol"; +import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {DiamondProxy} from "contracts/state-transition/chain-deps/DiamondProxy.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {INativeTokenVault} from "contracts/bridge/ntv/INativeTokenVault.sol"; +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {AddressHasNoCode} from "./ZkSyncScriptErrors.sol"; +import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; +import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; +import {IL2ContractDeployer} from "contracts/common/interfaces/IL2ContractDeployer.sol"; +import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {IL1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {IL1NativeTokenVault} from "contracts/bridge/ntv/IL1NativeTokenVault.sol"; +import {L1NullifierDev} from "contracts/dev-contracts/L1NullifierDev.sol"; +import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; +import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; +import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; +import {IAssetRouterBase} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; +import {L2ContractsBytecodesLib} from "./L2ContractsBytecodesLib.sol"; + +struct FixedForceDeploymentsData { + uint256 l1ChainId; + uint256 eraChainId; + address l1AssetRouter; + bytes32 l2TokenProxyBytecodeHash; + address aliasedL1Governance; + uint256 maxNumberOfZKChains; + bytes32 bridgehubBytecodeHash; + bytes32 l2AssetRouterBytecodeHash; + bytes32 l2NtvBytecodeHash; + bytes32 messageRootBytecodeHash; +} + +// solhint-disable-next-line gas-struct-packing +struct DeployedAddresses { + BridgehubDeployedAddresses bridgehub; + StateTransitionDeployedAddresses stateTransition; + BridgesDeployedAddresses bridges; + L1NativeTokenVaultAddresses vaults; + DataAvailabilityDeployedAddresses daAddresses; + address transparentProxyAdmin; + address governance; + address chainAdmin; + address accessControlRestrictionAddress; + address blobVersionedHashRetriever; + address validatorTimelock; + address create2Factory; +} + +// solhint-disable-next-line gas-struct-packing +struct L1NativeTokenVaultAddresses { + address l1NativeTokenVaultImplementation; + address l1NativeTokenVaultProxy; +} + +struct DataAvailabilityDeployedAddresses { + address l1RollupDAValidator; + address l1ValidiumDAValidator; +} + +// solhint-disable-next-line gas-struct-packing +struct BridgehubDeployedAddresses { + address bridgehubImplementation; + address bridgehubProxy; + address ctmDeploymentTrackerImplementation; + address ctmDeploymentTrackerProxy; + address messageRootImplementation; + address messageRootProxy; +} + +// solhint-disable-next-line gas-struct-packing +struct BridgesDeployedAddresses { + address erc20BridgeImplementation; + address erc20BridgeProxy; + address sharedBridgeImplementation; + address sharedBridgeProxy; + address l1NullifierImplementation; + address l1NullifierProxy; + address bridgedStandardERC20Implementation; + address bridgedTokenBeacon; +} + +// solhint-disable-next-line gas-struct-packing +struct Config { + uint256 l1ChainId; + address deployerAddress; + uint256 eraChainId; + address ownerAddress; + bool testnetVerifier; + ContractsConfig contracts; + TokensConfig tokens; +} + +// solhint-disable-next-line gas-struct-packing +struct ContractsConfig { + bytes32 create2FactorySalt; + address create2FactoryAddr; + address multicall3Addr; + uint256 validatorTimelockExecutionDelay; + bytes32 genesisRoot; + uint256 genesisRollupLeafIndex; + bytes32 genesisBatchCommitment; + uint256 latestProtocolVersion; + bytes32 recursionNodeLevelVkHash; + bytes32 recursionLeafLevelVkHash; + bytes32 recursionCircuitsSetVksHash; + uint256 priorityTxMaxGasLimit; + PubdataPricingMode diamondInitPubdataPricingMode; + uint256 diamondInitBatchOverheadL1Gas; + uint256 diamondInitMaxPubdataPerBatch; + uint256 diamondInitMaxL2GasPerBatch; + uint256 diamondInitPriorityTxMaxPubdata; + uint256 diamondInitMinimalL2GasPrice; + address governanceSecurityCouncilAddress; + uint256 governanceMinDelay; + uint256 maxNumberOfChains; + bytes diamondCutData; + bytes32 bootloaderHash; + bytes32 defaultAAHash; +} + +struct TokensConfig { + address tokenWethAddress; +} + +// solhint-disable-next-line gas-struct-packing +struct GeneratedData { + bytes forceDeploymentsData; +} + +contract DeployUtils is Script { + using stdToml for string; + + Config public config; + GeneratedData internal generatedData; + DeployedAddresses internal addresses; + + function initializeConfig(string memory configPath) internal { + string memory toml = vm.readFile(configPath); + + config.l1ChainId = block.chainid; + config.deployerAddress = msg.sender; + + // Config file must be parsed key by key, otherwise values returned + // are parsed alfabetically and not by key. + // https://book.getfoundry.sh/cheatcodes/parse-toml + config.eraChainId = toml.readUint("$.era_chain_id"); + config.ownerAddress = toml.readAddress("$.owner_address"); + config.testnetVerifier = toml.readBool("$.testnet_verifier"); + + config.contracts.governanceSecurityCouncilAddress = toml.readAddress( + "$.contracts.governance_security_council_address" + ); + config.contracts.governanceMinDelay = toml.readUint("$.contracts.governance_min_delay"); + config.contracts.maxNumberOfChains = toml.readUint("$.contracts.max_number_of_chains"); + config.contracts.create2FactorySalt = toml.readBytes32("$.contracts.create2_factory_salt"); + if (vm.keyExistsToml(toml, "$.contracts.create2_factory_addr")) { + config.contracts.create2FactoryAddr = toml.readAddress("$.contracts.create2_factory_addr"); + } + config.contracts.validatorTimelockExecutionDelay = toml.readUint( + "$.contracts.validator_timelock_execution_delay" + ); + config.contracts.genesisRoot = toml.readBytes32("$.contracts.genesis_root"); + config.contracts.genesisRollupLeafIndex = toml.readUint("$.contracts.genesis_rollup_leaf_index"); + config.contracts.genesisBatchCommitment = toml.readBytes32("$.contracts.genesis_batch_commitment"); + config.contracts.latestProtocolVersion = toml.readUint("$.contracts.latest_protocol_version"); + config.contracts.recursionNodeLevelVkHash = toml.readBytes32("$.contracts.recursion_node_level_vk_hash"); + config.contracts.recursionLeafLevelVkHash = toml.readBytes32("$.contracts.recursion_leaf_level_vk_hash"); + config.contracts.recursionCircuitsSetVksHash = toml.readBytes32("$.contracts.recursion_circuits_set_vks_hash"); + config.contracts.priorityTxMaxGasLimit = toml.readUint("$.contracts.priority_tx_max_gas_limit"); + config.contracts.diamondInitPubdataPricingMode = PubdataPricingMode( + toml.readUint("$.contracts.diamond_init_pubdata_pricing_mode") + ); + config.contracts.diamondInitBatchOverheadL1Gas = toml.readUint( + "$.contracts.diamond_init_batch_overhead_l1_gas" + ); + config.contracts.diamondInitMaxPubdataPerBatch = toml.readUint( + "$.contracts.diamond_init_max_pubdata_per_batch" + ); + config.contracts.diamondInitMaxL2GasPerBatch = toml.readUint("$.contracts.diamond_init_max_l2_gas_per_batch"); + config.contracts.diamondInitPriorityTxMaxPubdata = toml.readUint( + "$.contracts.diamond_init_priority_tx_max_pubdata" + ); + config.contracts.diamondInitMinimalL2GasPrice = toml.readUint("$.contracts.diamond_init_minimal_l2_gas_price"); + config.contracts.defaultAAHash = toml.readBytes32("$.contracts.default_aa_hash"); + config.contracts.bootloaderHash = toml.readBytes32("$.contracts.bootloader_hash"); + + config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); + } + + function deployViaCreate2(bytes memory creationCode, bytes memory constructorArgs) internal virtual returns (address) { + return Utils.deployViaCreate2(abi.encodePacked(creationCode, constructorArgs), config.contracts.create2FactorySalt, addresses.create2Factory); + } + + function deployVerifier() internal { + bytes memory code; + if (config.testnetVerifier) { + code = type(TestnetVerifier).creationCode; + } else { + code = type(Verifier).creationCode; + } + address contractAddress = deployViaCreate2(code, ""); + console.log("Verifier deployed at:", contractAddress); + addresses.stateTransition.verifier = contractAddress; + } + + function deployDefaultUpgrade() internal { + address contractAddress = deployViaCreate2(type(DefaultUpgrade).creationCode, ""); + console.log("DefaultUpgrade deployed at:", contractAddress); + addresses.stateTransition.defaultUpgrade = contractAddress; + } + + function deployGenesisUpgrade() internal { + address contractAddress = deployViaCreate2(type(L1GenesisUpgrade).creationCode, ""); + console.log("GenesisUpgrade deployed at:", contractAddress); + addresses.stateTransition.genesisUpgrade = contractAddress; + } + + function deployValidatorTimelock() internal { + uint32 executionDelay = uint32(config.contracts.validatorTimelockExecutionDelay); + address contractAddress = deployViaCreate2( + type(ValidatorTimelock).creationCode, + abi.encode(config.deployerAddress, executionDelay, config.eraChainId) + ); + console.log("ValidatorTimelock deployed at:", contractAddress); + addresses.validatorTimelock = contractAddress; + } + + function deployGovernance() internal { + address contractAddress = deployViaCreate2( + type(Governance).creationCode, + abi.encode( + config.ownerAddress, + config.contracts.governanceSecurityCouncilAddress, + config.contracts.governanceMinDelay + ) + ); + console.log("Governance deployed at:", contractAddress); + addresses.governance = contractAddress; + } + + function deployChainAdmin() internal { + address accessControlRestriction = deployViaCreate2( + type(AccessControlRestriction).creationCode, + abi.encode(uint256(0), config.ownerAddress) + ); + + console.log("Access control restriction deployed at:", accessControlRestriction); + address[] memory restrictions = new address[](1); + restrictions[0] = accessControlRestriction; + addresses.accessControlRestrictionAddress = accessControlRestriction; + + address contractAddress = deployViaCreate2( + type(ChainAdmin).creationCode, + abi.encode(restrictions) + ); + console.log("ChainAdmin deployed at:", contractAddress); + addresses.chainAdmin = contractAddress; + } + + function deployTransparentProxyAdmin() internal { + vm.startBroadcast(); + ProxyAdmin proxyAdmin = new ProxyAdmin(); + proxyAdmin.transferOwnership(addresses.governance); + vm.stopBroadcast(); + console.log("Transparent Proxy Admin deployed at:", address(proxyAdmin)); + addresses.transparentProxyAdmin = address(proxyAdmin); + } + + function deployChainTypeManagerContract() internal { + deployStateTransitionDiamondFacets(); + deployChainTypeManagerImplementation(); + deployChainTypeManagerProxy(); + } + + function deployStateTransitionDiamondFacets() internal { + address executorFacet = deployViaCreate2(type(ExecutorFacet).creationCode, abi.encode()); + console.log("ExecutorFacet deployed at:", executorFacet); + addresses.stateTransition.executorFacet = executorFacet; + + address adminFacet = deployViaCreate2( + type(AdminFacet).creationCode, + abi.encode(config.l1ChainId) + ); + console.log("AdminFacet deployed at:", adminFacet); + addresses.stateTransition.adminFacet = adminFacet; + + address mailboxFacet = deployViaCreate2( + type(MailboxFacet).creationCode, + abi.encode(config.eraChainId, config.l1ChainId) + ); + console.log("MailboxFacet deployed at:", mailboxFacet); + addresses.stateTransition.mailboxFacet = mailboxFacet; + + address gettersFacet = deployViaCreate2(type(GettersFacet).creationCode, ""); + console.log("GettersFacet deployed at:", gettersFacet); + addresses.stateTransition.gettersFacet = gettersFacet; + + address diamondInit = deployViaCreate2(type(DiamondInit).creationCode, ""); + console.log("DiamondInit deployed at:", diamondInit); + addresses.stateTransition.diamondInit = diamondInit; + } + + function deployChainTypeManagerImplementation() internal { + bytes memory bytecode = type(ChainTypeManager).creationCode; + bytes memory constructorArgs = abi.encode(addresses.bridgehub.bridgehubProxy); + address contractAddress = deployViaCreate2(bytecode, constructorArgs); + console.log("ChainTypeManagerImplementation deployed at:", contractAddress); + addresses.stateTransition.chainTypeManagerImplementation = contractAddress; + } + + function deployChainTypeManagerProxy() internal { + string memory root = vm.projectRoot(); + string memory inputPath = string.concat(root, "/script-out/diamond-selectors.toml"); + string memory toml = vm.readFile(inputPath); + + bytes memory adminFacetSelectors = toml.readBytes("$.admin_facet_selectors"); + bytes memory gettersFacetSelectors = toml.readBytes("$.getters_facet_selectors"); + bytes memory mailboxFacetSelectors = toml.readBytes("$.mailbox_facet_selectors"); + bytes memory executorFacetSelectors = toml.readBytes("$.executor_facet_selectors"); + + bytes4[] memory adminFacetSelectorsArray = abi.decode(adminFacetSelectors, (bytes4[])); + bytes4[] memory gettersFacetSelectorsArray = abi.decode(gettersFacetSelectors, (bytes4[])); + bytes4[] memory mailboxFacetSelectorsArray = abi.decode(mailboxFacetSelectors, (bytes4[])); + bytes4[] memory executorFacetSelectorsArray = abi.decode(executorFacetSelectors, (bytes4[])); + + Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](4); + facetCuts[0] = Diamond.FacetCut({ + facet: addresses.stateTransition.adminFacet, + action: Diamond.Action.Add, + isFreezable: false, + selectors: adminFacetSelectorsArray + }); + facetCuts[1] = Diamond.FacetCut({ + facet: addresses.stateTransition.gettersFacet, + action: Diamond.Action.Add, + isFreezable: false, + selectors: gettersFacetSelectorsArray + }); + facetCuts[2] = Diamond.FacetCut({ + facet: addresses.stateTransition.mailboxFacet, + action: Diamond.Action.Add, + isFreezable: true, + selectors: mailboxFacetSelectorsArray + }); + facetCuts[3] = Diamond.FacetCut({ + facet: addresses.stateTransition.executorFacet, + action: Diamond.Action.Add, + isFreezable: true, + selectors: executorFacetSelectorsArray + }); + + VerifierParams memory verifierParams = VerifierParams({ + recursionNodeLevelVkHash: config.contracts.recursionNodeLevelVkHash, + recursionLeafLevelVkHash: config.contracts.recursionLeafLevelVkHash, + recursionCircuitsSetVksHash: config.contracts.recursionCircuitsSetVksHash + }); + + FeeParams memory feeParams = FeeParams({ + pubdataPricingMode: config.contracts.diamondInitPubdataPricingMode, + batchOverheadL1Gas: uint32(config.contracts.diamondInitBatchOverheadL1Gas), + maxPubdataPerBatch: uint32(config.contracts.diamondInitMaxPubdataPerBatch), + maxL2GasPerBatch: uint32(config.contracts.diamondInitMaxL2GasPerBatch), + priorityTxMaxPubdata: uint32(config.contracts.diamondInitPriorityTxMaxPubdata), + minimalL2GasPrice: uint64(config.contracts.diamondInitMinimalL2GasPrice) + }); + + DiamondInitializeDataNewChain memory initializeData = DiamondInitializeDataNewChain({ + verifier: IVerifier(addresses.stateTransition.verifier), + verifierParams: verifierParams, + l2BootloaderBytecodeHash: config.contracts.bootloaderHash, + l2DefaultAccountBytecodeHash: config.contracts.defaultAAHash, + priorityTxMaxGasLimit: config.contracts.priorityTxMaxGasLimit, + feeParams: feeParams, + blobVersionedHashRetriever: addresses.blobVersionedHashRetriever + }); + + Diamond.DiamondCutData memory diamondCut = Diamond.DiamondCutData({ + facetCuts: facetCuts, + initAddress: addresses.stateTransition.diamondInit, + initCalldata: abi.encode(initializeData) + }); + + config.contracts.diamondCutData = abi.encode(diamondCut); + + ChainCreationParams memory chainCreationParams = ChainCreationParams({ + genesisUpgrade: addresses.stateTransition.genesisUpgrade, + genesisBatchHash: config.contracts.genesisRoot, + genesisIndexRepeatedStorageChanges: uint64(config.contracts.genesisRollupLeafIndex), + genesisBatchCommitment: config.contracts.genesisBatchCommitment, + diamondCut: diamondCut, + forceDeploymentsData: generatedData.forceDeploymentsData + }); + + ChainTypeManagerInitializeData memory diamondInitData = ChainTypeManagerInitializeData({ + owner: msg.sender, + validatorTimelock: addresses.validatorTimelock, + chainCreationParams: chainCreationParams, + protocolVersion: config.contracts.latestProtocolVersion + }); + + address contractAddress = deployViaCreate2( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + addresses.stateTransition.chainTypeManagerImplementation, + addresses.transparentProxyAdmin, + abi.encodeCall(ChainTypeManager.initialize, (diamondInitData)) + ) + ); + console.log("ChainTypeManagerProxy deployed at:", contractAddress); + addresses.stateTransition.chainTypeManagerProxy = contractAddress; + } + + + + function test() internal virtual {} +} diff --git a/l1-contracts/package.json b/l1-contracts/package.json index 6d68729e2..e4537c08a 100644 --- a/l1-contracts/package.json +++ b/l1-contracts/package.json @@ -58,8 +58,8 @@ "clean": "hardhat clean && CONTRACTS_BASE_NETWORK_ZKSYNC=true hardhat clean", "clean:foundry": "forge clean", "test": "yarn workspace da-contracts build && hardhat test test/unit_tests/*.spec.ts --network hardhat", - "test:foundry": "forge test --ffi --match-path 'test/foundry/l1/*'", - "test:zkfoundry": "forge test --zksync --match-path 'test/foundry/l2/*'", + "test:foundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --ffi --match-path 'test/foundry/l1/*'", + "test:zkfoundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --zksync --match-path 'test/foundry/l2/*'", "test:fork": "TEST_CONTRACTS_FORK=1 yarn run hardhat test test/unit_tests/*.fork.ts --network hardhat", "coverage:foundry": "forge coverage --ffi --match-path 'test/foundry/l1/*' --no-match-coverage 'contracts/bridge/.*L2.*.sol'", "deploy-no-build": "ts-node scripts/deploy.ts", diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol index 2cfd6e5b6..0b8efde4c 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol @@ -12,7 +12,7 @@ import {L1NativeTokenVault} from "contracts/bridge/ntv/L1NativeTokenVault.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; -import {DeployedAddresses, Config} from "deploy-scripts/DeployL1.s.sol"; +import {DeployedAddresses, Config} from "deploy-scripts/DeployUtils.s.sol"; contract L1ContractDeployer is Test { using stdStorage for StdStorage; @@ -69,15 +69,6 @@ contract L1ContractDeployer is Test { bridgeHubOwnerAddress = bridgeHub.owner(); } - function _deployL2Contracts() internal { - vm.setEnv("L2_CONFIG", "/test/foundry/l2/integration/script-config/config-deploy-l2.toml"); - vm.setEnv("L2_OUTPUT", "/test/foundry/l2/integration/script-out/output-deploy-l2.toml"); - - l1Script = new DeployL1Script(); - l1Script.runForL2Test(); - - chainTypeManager = IChainTypeManager(ecosystemAddresses.stateTransition.chainTypeManagerProxy); - } function _acceptOwnership() private { vm.startPrank(bridgeHub.pendingOwner()); diff --git a/l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol similarity index 66% rename from l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol rename to l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index cdc96762e..aa18507e1 100644 --- a/l1-contracts/test/foundry/l2/integration/L2Gateway.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -26,11 +26,10 @@ import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; import {L2Utils} from "../unit/utils/L2Utils.sol"; import {SystemContractsArgs} from "../unit/utils/L2Utils.sol"; -import {L1ContractDeployer} from "../../l1/integration/_SharedL1ContractDeployer.t.sol"; -import {ZKChainDeployer} from "../../l1/integration/_SharedZKChainDeployer.t.sol"; -import {TokenDeployer} from "../../l1/integration/_SharedTokenDeployer.t.sol"; +import {L2ContractDeployer} from "./_SharedL2ContractDeployer.t.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; -contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { +contract L2GatewayTests is Test, L2ContractDeployer { // is L1ContractDeployer, ZKChainDeployer, TokenDeployer { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. address internal l1BridgeWallet = address(1); @@ -49,7 +48,8 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { uint256 internal constant L1_CHAIN_ID = 9; uint256 internal ERA_CHAIN_ID = 270; - address internal l1AssetRouter; + address internal l1AssetRouter = makeAddr("l1AssetRouter"); + address internal aliasedL1AssetRouter = AddressAliasHelper.applyL1ToL2Alias(l1AssetRouter); address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); address internal l1CTM = makeAddr("l1CTM"); @@ -60,6 +60,10 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { bytes internal exampleChainCommitment; + IChainTypeManager internal chainTypeManager; + + // L2ContractDeployer internal deployScript; + function setUp() public { aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); @@ -86,16 +90,19 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { l2TokenBeacon: address(beacon), l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, aliasedOwner: ownerWallet, - contractsDeployedAlready: true + contractsDeployedAlready: false, + l1CtmDeployer: l1CTMDeployer }) ); + deployL2Contracts(); - _deployL2Contracts(); - - vm.prank(l1AssetRouter); + vm.prank(aliasedL1AssetRouter); l2AssetRouter.setAssetHandlerAddress(L1_CHAIN_ID, ctmAssetId, L2_BRIDGEHUB_ADDR); - vm.prank(l1CTMDeployer); - l2Bridgehub.setAssetHandlerAddress(bytes32(uint256(uint160(l1CTM))), address(chainTypeManager)); + vm.prank(ownerWallet); + l2Bridgehub.addChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1CTMDeployer)); + l2Bridgehub.setAssetHandlerAddress(bytes32(uint256(uint160(l1CTM))), address(addresses.stateTransition.chainTypeManagerProxy)); + chainTypeManager = IChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); } function test_gatewayShouldFinalizeDeposit() public { @@ -103,31 +110,30 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer { } function test_forwardToL3OnGateway() public { - finalizeDeposit(); + // todo fix this test + // finalizeDeposit(); - IBridgehub bridgehub = IBridgehub(bridgeHub); - // vm.chainId(12345); - vm.startBroadcast(SETTLEMENT_LAYER_RELAY_SENDER); - bridgehub.forwardTransactionOnGateway(ERA_CHAIN_ID, bytes32(0), 0); - vm.stopBroadcast(); + // IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); + // vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); + // bridgehub.forwardTransactionOnGateway(ERA_CHAIN_ID, bytes32(0), 0); } function finalizeDeposit() public { - bytes memory chainData = abi.encode(exampleChainCommitment); - bytes memory ctmData = abi.encode( - baseTokenAssetId, - msg.sender, - chainTypeManager.protocolVersion(), - ecosystemConfig.contracts.diamondCutData - ); - - BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ - chainId: ERA_CHAIN_ID, - baseTokenAssetId: baseTokenAssetId, - ctmData: ctmData, - chainData: chainData - }); - vm.prank(l1AssetRouter); - l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + // bytes memory chainData = abi.encode(exampleChainCommitment); + // bytes memory ctmData = abi.encode( + // baseTokenAssetId, + // msg.sender, + // chainTypeManager.protocolVersion(), + // config.contracts.diamondCutData + // ); + + // BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + // chainId: ERA_CHAIN_ID, + // baseTokenAssetId: baseTokenAssetId, + // ctmData: ctmData, + // chainData: chainData + // }); + // vm.prank(aliasedL1AssetRouter); + // l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); } } diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol new file mode 100644 index 000000000..00a28122b --- /dev/null +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {StdStorage, stdStorage, stdToml} from "forge-std/Test.sol"; +import {Script, console2 as console} from "forge-std/Script.sol"; + +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {L1AssetRouter} from "contracts/bridge/asset-router/L1AssetRouter.sol"; +import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {L1NativeTokenVault} from "contracts/bridge/ntv/L1NativeTokenVault.sol"; +import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; +import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {DeployedAddresses, Config} from "deploy-scripts/DeployUtils.s.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; + +import {L2Utils} from "../unit/utils/L2Utils.sol"; + + +contract L2ContractDeployer is DeployUtils { + using stdToml for string; + + function deployViaCreate2(bytes memory creationCode, bytes memory constructorArgs) internal override returns (address) { + console.log("Deploying via create2 L2"); + return L2Utils.deployViaCreat2L2(creationCode, constructorArgs, config.contracts.create2FactorySalt); + } + + function deployL2Contracts() public { + string memory root = vm.projectRoot(); + string memory inputPath = string.concat(root, "/script-config/config-deploy-l1.toml"); + initializeConfig(inputPath); + addresses.transparentProxyAdmin = address(0x1); + deployGenesisUpgrade(); + deployChainTypeManagerContract(); + } + + // add this to be excluded from coverage report + function test() internal virtual override {} +} diff --git a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol index c9902366f..d29d2b7ff 100644 --- a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol +++ b/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol @@ -43,6 +43,7 @@ contract L2Erc20BridgeTest is Test { string internal constant TOKEN_DEFAULT_NAME = "TestnetERC20Token"; string internal constant TOKEN_DEFAULT_SYMBOL = "TET"; uint8 internal constant TOKEN_DEFAULT_DECIMALS = 18; + address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); function setUp() public { aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); @@ -70,12 +71,13 @@ contract L2Erc20BridgeTest is Test { SystemContractsArgs({ l1ChainId: L1_CHAIN_ID, eraChainId: ERA_CHAIN_ID, - l1AssetRouter: L2_ASSET_ROUTER_ADDR, + l1AssetRouter: l1BridgeWallet, legacySharedBridge: l2SharedBridge, l2TokenBeacon: address(beacon), l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, aliasedOwner: ownerWallet, - contractsDeployedAlready: true + contractsDeployedAlready: false, + l1CtmDeployer: l1CTMDeployer }) ); } diff --git a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol index 5b678fce6..ee0daaef3 100644 --- a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol @@ -5,6 +5,8 @@ pragma solidity ^0.8.20; import {Vm} from "forge-std/Vm.sol"; import "forge-std/console.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; import {DEPLOYER_SYSTEM_CONTRACT, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR, L2_MESSAGE_ROOT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {IContractDeployer, L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; @@ -19,6 +21,10 @@ import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; + +import {SystemContractsCaller} from "contracts/common/libraries/SystemContractsCaller.sol"; +import {DeployFailed} from "contracts/common/L1ContractErrors.sol"; struct SystemContractsArgs { uint256 l1ChainId; @@ -29,6 +35,7 @@ struct SystemContractsArgs { bytes32 l2TokenProxyBytecodeHash; address aliasedOwner; bool contractsDeployedAlready; + address l1CtmDeployer; } library L2Utils { @@ -83,7 +90,8 @@ library L2Utils { _args.eraChainId, _args.aliasedOwner, _args.l1AssetRouter, - _args.legacySharedBridge + _args.legacySharedBridge, + _args.l1CtmDeployer ); forceDeployAssetRouter( _args.l1ChainId, @@ -107,16 +115,16 @@ library L2Utils { uint256 _eraChainId, address _aliasedOwner, address _l1AssetRouter, - address _legacySharedBridge + address _legacySharedBridge, + address _l1CtmDeployer ) internal { new Bridgehub(_l1ChainId, _aliasedOwner, 100); forceDeployWithConstructor("Bridgehub", L2_BRIDGEHUB_ADDR, abi.encode(_l1ChainId, _aliasedOwner, 100)); Bridgehub bridgehub = Bridgehub(L2_BRIDGEHUB_ADDR); - address l1CTMDeployer = address(0x1); vm.prank(_aliasedOwner); bridgehub.setAddresses( L2_ASSET_ROUTER_ADDR, - ICTMDeploymentTracker(l1CTMDeployer), + ICTMDeploymentTracker(_l1CtmDeployer), IMessageRoot(L2_MESSAGE_ROOT_ADDR) ); } @@ -193,7 +201,7 @@ library L2Utils { function forceDeployWithConstructor( string memory _contractName, address _address, - bytes memory _constuctorArgs + bytes memory _constructorArgs ) public { bytes memory bytecode = readEraBytecode(_contractName); @@ -205,7 +213,7 @@ library L2Utils { newAddress: _address, callConstructor: true, value: 0, - input: _constuctorArgs + input: _constructorArgs }); vm.prank(L2_FORCE_DEPLOYER_ADDR); @@ -253,4 +261,24 @@ library L2Utils { return abi.encode(encodedName, encodedSymbol, encodedDecimals); } + + function deployViaCreat2L2( + bytes memory creationCode, + bytes memory constructorargs, + bytes32 create2salt + ) internal returns (address) { + bytes memory bytecode = abi.encodePacked(creationCode, constructorargs); + address contractAddress; + assembly { + contractAddress := create2(0, add(bytecode, 0x20), mload(bytecode), create2salt) + } + uint32 size; + assembly { + size := extcodesize(contractAddress) + } + if (size == 0) { + revert DeployFailed(); + } + return contractAddress; + } } From 4c4e3f6cc448f524c5d0e79688c3be0e73958016 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sat, 28 Sep 2024 22:01:26 +0100 Subject: [PATCH 09/27] lint --- l1-contracts/deploy-scripts/DeployL1.s.sol | 8 +++++-- l1-contracts/deploy-scripts/DeployUtils.s.sol | 24 +++++++++---------- .../_SharedL1ContractDeployer.t.sol | 1 - .../l2/integration/L2GatewayTests.t.sol | 12 ++++++---- .../_SharedL2ContractDeployer.t.sol | 6 +++-- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 5380b56ca..34a160d11 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -503,7 +503,7 @@ contract DeployL1Script is Script, DeployUtils { bytes4[] memory gettersFacetSelectors = Utils.getAllSelectors(address(gettersFacet).code); bytes4[] memory mailboxFacetSelectors = Utils.getAllSelectors(address(mailboxFacet).code); bytes4[] memory executorFacetSelectors = Utils.getAllSelectors(address(executorFacet).code); - + string memory root = vm.projectRoot(); string memory outputPath = string.concat(root, "/script-out/diamond-selectors.toml"); @@ -515,7 +515,11 @@ contract DeployL1Script is Script, DeployUtils { vm.serializeBytes("diamond_selectors", "admin_facet_selectors", adminFacetSelectorsBytes); vm.serializeBytes("diamond_selectors", "getters_facet_selectors", gettersFacetSelectorsBytes); vm.serializeBytes("diamond_selectors", "mailbox_facet_selectors", mailboxFacetSelectorsBytes); - string memory toml = vm.serializeBytes("diamond_selectors", "executor_facet_selectors", executorFacetSelectorsBytes); + string memory toml = vm.serializeBytes( + "diamond_selectors", + "executor_facet_selectors", + executorFacetSelectorsBytes + ); vm.writeToml(toml, outputPath); } diff --git a/l1-contracts/deploy-scripts/DeployUtils.s.sol b/l1-contracts/deploy-scripts/DeployUtils.s.sol index 9ccee1373..5aebdccd1 100644 --- a/l1-contracts/deploy-scripts/DeployUtils.s.sol +++ b/l1-contracts/deploy-scripts/DeployUtils.s.sol @@ -225,8 +225,16 @@ contract DeployUtils is Script { config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); } - function deployViaCreate2(bytes memory creationCode, bytes memory constructorArgs) internal virtual returns (address) { - return Utils.deployViaCreate2(abi.encodePacked(creationCode, constructorArgs), config.contracts.create2FactorySalt, addresses.create2Factory); + function deployViaCreate2( + bytes memory creationCode, + bytes memory constructorArgs + ) internal virtual returns (address) { + return + Utils.deployViaCreate2( + abi.encodePacked(creationCode, constructorArgs), + config.contracts.create2FactorySalt, + addresses.create2Factory + ); } function deployVerifier() internal { @@ -287,10 +295,7 @@ contract DeployUtils is Script { restrictions[0] = accessControlRestriction; addresses.accessControlRestrictionAddress = accessControlRestriction; - address contractAddress = deployViaCreate2( - type(ChainAdmin).creationCode, - abi.encode(restrictions) - ); + address contractAddress = deployViaCreate2(type(ChainAdmin).creationCode, abi.encode(restrictions)); console.log("ChainAdmin deployed at:", contractAddress); addresses.chainAdmin = contractAddress; } @@ -315,10 +320,7 @@ contract DeployUtils is Script { console.log("ExecutorFacet deployed at:", executorFacet); addresses.stateTransition.executorFacet = executorFacet; - address adminFacet = deployViaCreate2( - type(AdminFacet).creationCode, - abi.encode(config.l1ChainId) - ); + address adminFacet = deployViaCreate2(type(AdminFacet).creationCode, abi.encode(config.l1ChainId)); console.log("AdminFacet deployed at:", adminFacet); addresses.stateTransition.adminFacet = adminFacet; @@ -448,7 +450,5 @@ contract DeployUtils is Script { addresses.stateTransition.chainTypeManagerProxy = contractAddress; } - - function test() internal virtual {} } diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol index 0b8efde4c..d7d7866d9 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol @@ -69,7 +69,6 @@ contract L1ContractDeployer is Test { bridgeHubOwnerAddress = bridgeHub.owner(); } - function _acceptOwnership() private { vm.startPrank(bridgeHub.pendingOwner()); bridgeHub.acceptOwnership(); diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index aa18507e1..595876a91 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -29,7 +29,10 @@ import {SystemContractsArgs} from "../unit/utils/L2Utils.sol"; import {L2ContractDeployer} from "./_SharedL2ContractDeployer.t.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; -contract L2GatewayTests is Test, L2ContractDeployer { // is L1ContractDeployer, ZKChainDeployer, TokenDeployer { +contract L2GatewayTests is + Test, + L2ContractDeployer // is L1ContractDeployer, ZKChainDeployer, TokenDeployer { +{ // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. address internal l1BridgeWallet = address(1); @@ -101,7 +104,10 @@ contract L2GatewayTests is Test, L2ContractDeployer { // is L1ContractDeployer, vm.prank(ownerWallet); l2Bridgehub.addChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1CTMDeployer)); - l2Bridgehub.setAssetHandlerAddress(bytes32(uint256(uint160(l1CTM))), address(addresses.stateTransition.chainTypeManagerProxy)); + l2Bridgehub.setAssetHandlerAddress( + bytes32(uint256(uint160(l1CTM))), + address(addresses.stateTransition.chainTypeManagerProxy) + ); chainTypeManager = IChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); } @@ -112,7 +118,6 @@ contract L2GatewayTests is Test, L2ContractDeployer { // is L1ContractDeployer, function test_forwardToL3OnGateway() public { // todo fix this test // finalizeDeposit(); - // IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); // vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); // bridgehub.forwardTransactionOnGateway(ERA_CHAIN_ID, bytes32(0), 0); @@ -126,7 +131,6 @@ contract L2GatewayTests is Test, L2ContractDeployer { // is L1ContractDeployer, // chainTypeManager.protocolVersion(), // config.contracts.diamondCutData // ); - // BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ // chainId: ERA_CHAIN_ID, // baseTokenAssetId: baseTokenAssetId, diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol index 00a28122b..549fbef8c 100644 --- a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol @@ -18,11 +18,13 @@ import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; import {L2Utils} from "../unit/utils/L2Utils.sol"; - contract L2ContractDeployer is DeployUtils { using stdToml for string; - function deployViaCreate2(bytes memory creationCode, bytes memory constructorArgs) internal override returns (address) { + function deployViaCreate2( + bytes memory creationCode, + bytes memory constructorArgs + ) internal override returns (address) { console.log("Deploying via create2 L2"); return L2Utils.deployViaCreat2L2(creationCode, constructorArgs, config.contracts.create2FactorySalt); } From e7cf415af8bc1b1629d90bf46ffe5fea58c04f2c Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sat, 28 Sep 2024 22:20:21 +0100 Subject: [PATCH 10/27] diamond selectors --- l1-contracts/deploy-scripts/DeployL1.s.sol | 1 + l1-contracts/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 34a160d11..76cb17b21 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -87,6 +87,7 @@ contract DeployL1Script is Script, DeployUtils { inputPath = string.concat(root, inputPath); outputPath = string.concat(root, outputPath); + saveDiamondSelectors(); initializeConfig(inputPath); instantiateCreate2Factory(); diff --git a/l1-contracts/package.json b/l1-contracts/package.json index e4537c08a..c7baa67ab 100644 --- a/l1-contracts/package.json +++ b/l1-contracts/package.json @@ -58,7 +58,7 @@ "clean": "hardhat clean && CONTRACTS_BASE_NETWORK_ZKSYNC=true hardhat clean", "clean:foundry": "forge clean", "test": "yarn workspace da-contracts build && hardhat test test/unit_tests/*.spec.ts --network hardhat", - "test:foundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --ffi --match-path 'test/foundry/l1/*'", + "test:foundry": "forge test --ffi --match-path 'test/foundry/l1/*'", "test:zkfoundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --zksync --match-path 'test/foundry/l2/*'", "test:fork": "TEST_CONTRACTS_FORK=1 yarn run hardhat test test/unit_tests/*.fork.ts --network hardhat", "coverage:foundry": "forge coverage --ffi --match-path 'test/foundry/l1/*' --no-match-coverage 'contracts/bridge/.*L2.*.sol'", From 5449b51b5ef18de26077636593bbbc82fd3c98e7 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sat, 28 Sep 2024 22:36:50 +0100 Subject: [PATCH 11/27] add back test for coverage --- .../test/foundry/l1/integration/L1GatewayTests.t.sol | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index 271dcc73e..0d558b8db 100644 --- a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -39,7 +39,7 @@ import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer { +contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer { uint256 constant TEST_USERS_COUNT = 10; address[] public users; address[] public l2ContractAddresses; @@ -290,6 +290,15 @@ contract GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2T assertEq(migratingChainContract.getBaseTokenAssetId(), baseTokenAssetId); } + /// to increase coverage, properly tested in L2GatewayTests + function test_forwardToL3OnGateway() public { + _setUpGatewayWithFilterer(); + vm.chainId(12345); + vm.startBroadcast(SETTLEMENT_LAYER_RELAY_SENDER); + bridgeHub.forwardTransactionOnGateway(migratingChainId, bytes32(0), 0); + vm.stopBroadcast(); + } + // add this to be excluded from coverage report function test() internal override {} } From ae57b24d0b4a5dd48de34aa988ffac17303597d9 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sat, 28 Sep 2024 22:38:48 +0100 Subject: [PATCH 12/27] trying to fix foundry deploy script tests --- .../foundry/l2/integration/_SharedL2ContractDeployer.t.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol index 549fbef8c..95411eba8 100644 --- a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol @@ -31,7 +31,10 @@ contract L2ContractDeployer is DeployUtils { function deployL2Contracts() public { string memory root = vm.projectRoot(); - string memory inputPath = string.concat(root, "/script-config/config-deploy-l1.toml"); + string memory inputPath = string.concat( + root, + "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml" + ); initializeConfig(inputPath); addresses.transparentProxyAdmin = address(0x1); deployGenesisUpgrade(); From da58aa0021f1fe1d0ba89d565580bd2fd64998e1 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 12:25:34 +0100 Subject: [PATCH 13/27] fixing l1 and l2 tests --- .../contracts/bridgehub/Bridgehub.sol | 7 +- l1-contracts/deploy-scripts/DeployL1.s.sol | 24 --- l1-contracts/deploy-scripts/DeployUtils.s.sol | 25 +++ .../l1/integration/L2GatewayDummyTests.t.sol | 50 +++++ .../L2GatewayDummyTestsAbstract.t.sol | 175 ++++++++++++++++++ .../_SharedL2ContractDummyDeployer.sol | 123 ++++++++++++ .../l2/integration/L2GatewayTests.t.sol | 127 +++---------- .../_SharedL2ContractDeployer.t.sol | 25 +-- .../test/foundry/l2/unit/utils/L2Utils.sol | 22 +-- 9 files changed, 419 insertions(+), 159 deletions(-) create mode 100644 l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol create mode 100644 l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol create mode 100644 l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol diff --git a/l1-contracts/contracts/bridgehub/Bridgehub.sol b/l1-contracts/contracts/bridgehub/Bridgehub.sol index 8e23a9f3d..e9bb2a305 100644 --- a/l1-contracts/contracts/bridgehub/Bridgehub.sol +++ b/l1-contracts/contracts/bridgehub/Bridgehub.sol @@ -153,14 +153,17 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus // This is indeed true, since the only methods where this immutable is used are the ones with `onlyL1` modifier. // We will change this with interop. ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, ETH_TOKEN_ADDRESS); - _transferOwnership(_owner); - whitelistedSettlementLayers[_l1ChainId] = true; + _initialize(_owner); } /// @notice used to initialize the contract /// @notice this contract is also deployed on L2 as a system contract there the owner and the related functions will not be used /// @param _owner the owner of the contract function initialize(address _owner) external reentrancyGuardInitializer { + _initialize(_owner); + } + + function _initialize(address _owner) internal { _transferOwnership(_owner); assetIdIsRegistered[ETH_TOKEN_ASSET_ID] = true; whitelistedSettlementLayers[L1_CHAIN_ID] = true; diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 76cb17b21..3f49947ff 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -62,7 +62,6 @@ contract DeployL1Script is Script, DeployUtils { using stdToml for string; address internal constant ADDRESS_ONE = 0x0000000000000000000000000000000000000001; - address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; function run() public { console.log("Deploying L1 contracts"); @@ -134,29 +133,6 @@ contract DeployL1Script is Script, DeployUtils { generatedData.forceDeploymentsData = prepareForceDeploymentsData(); } - function instantiateCreate2Factory() internal { - address contractAddress; - - bool isDeterministicDeployed = DETERMINISTIC_CREATE2_ADDRESS.code.length > 0; - bool isConfigured = config.contracts.create2FactoryAddr != address(0); - - if (isConfigured) { - if (config.contracts.create2FactoryAddr.code.length == 0) { - revert AddressHasNoCode(config.contracts.create2FactoryAddr); - } - contractAddress = config.contracts.create2FactoryAddr; - console.log("Using configured Create2Factory address:", contractAddress); - } else if (isDeterministicDeployed) { - contractAddress = DETERMINISTIC_CREATE2_ADDRESS; - console.log("Using deterministic Create2Factory address:", contractAddress); - } else { - contractAddress = Utils.deployCreate2Factory(); - console.log("Create2Factory deployed at:", contractAddress); - } - - addresses.create2Factory = contractAddress; - } - function deployIfNeededMulticall3() internal { // Multicall3 is already deployed on public networks if (MULTICALL3_ADDRESS.code.length == 0) { diff --git a/l1-contracts/deploy-scripts/DeployUtils.s.sol b/l1-contracts/deploy-scripts/DeployUtils.s.sol index 5aebdccd1..428024998 100644 --- a/l1-contracts/deploy-scripts/DeployUtils.s.sol +++ b/l1-contracts/deploy-scripts/DeployUtils.s.sol @@ -168,6 +168,8 @@ struct GeneratedData { contract DeployUtils is Script { using stdToml for string; + address internal constant DETERMINISTIC_CREATE2_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + Config public config; GeneratedData internal generatedData; DeployedAddresses internal addresses; @@ -225,6 +227,29 @@ contract DeployUtils is Script { config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); } + function instantiateCreate2Factory() internal { + address contractAddress; + + bool isDeterministicDeployed = DETERMINISTIC_CREATE2_ADDRESS.code.length > 0; + bool isConfigured = config.contracts.create2FactoryAddr != address(0); + + if (isConfigured) { + if (config.contracts.create2FactoryAddr.code.length == 0) { + revert AddressHasNoCode(config.contracts.create2FactoryAddr); + } + contractAddress = config.contracts.create2FactoryAddr; + console.log("Using configured Create2Factory address:", contractAddress); + } else if (isDeterministicDeployed) { + contractAddress = DETERMINISTIC_CREATE2_ADDRESS; + console.log("Using deterministic Create2Factory address:", contractAddress); + } else { + contractAddress = Utils.deployCreate2Factory(); + console.log("Create2Factory deployed at:", contractAddress); + } + + addresses.create2Factory = contractAddress; + } + function deployViaCreate2( bytes memory creationCode, bytes memory constructorArgs diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol new file mode 100644 index 000000000..a588bc841 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; + +import {L2ContractDummyDeployer} from "./_SharedL2ContractDummyDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {L2GatewayDummyTests} from "./L2GatewayDummyTests.t.sol"; + +contract L2GatewayDummyTests is Test, L2ContractDummyDeployer, L2GatewayDummyTests { + function test() internal virtual override(DeployUtils, L2ContractDummyDeployer) {} + + function initSystemContracts( + SystemContractsArgs memory _args + ) internal virtual override(L2GatewayDummyTests, L2ContractDummyDeployer) { + super.initSystemContracts(_args); + } + + function deployL2Contracts( + uint256 _l1ChainId + ) public virtual override(L2GatewayDummyTests, L2ContractDummyDeployer) { + super.deployL2Contracts(_l1ChainId); + } +} diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol new file mode 100644 index 000000000..404822868 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; + +import {L2ContractDummyDeployer} from "./_SharedL2ContractDummyDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; + +abstract contract L2GatewayDummyAbstract is + Test, + DeployUtils + // L2ContractDummyDeployer +{ + // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. + // It is a bit easier to use EOA and it is sufficient for the tests. + address internal l1BridgeWallet = address(1); + address internal aliasedL1BridgeWallet; + + // The owner of the beacon and the native token vault + address internal ownerWallet = address(2); + + BridgedStandardERC20 internal standardErc20Impl; + + UpgradeableBeacon internal beacon; + BeaconProxy internal proxy; + + IL2AssetRouter l2AssetRouter = IL2AssetRouter(L2_ASSET_ROUTER_ADDR); + IBridgehub l2Bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); + + uint256 internal constant L1_CHAIN_ID = 10; // it cannot be 9, the default block.chainid + uint256 internal ERA_CHAIN_ID = 270; + uint256 internal mintChainId = 300; + address internal l1AssetRouter = makeAddr("l1AssetRouter"); + address internal aliasedL1AssetRouter = AddressAliasHelper.applyL1ToL2Alias(l1AssetRouter); + + address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); + address internal l1CTM = makeAddr("l1CTM"); + bytes32 internal ctmAssetId = keccak256(abi.encode(L1_CHAIN_ID, l1CTMDeployer, bytes32(uint256(uint160(l1CTM))))); + + bytes32 internal baseTokenAssetId = + keccak256(abi.encode(L1_CHAIN_ID, L2_NATIVE_TOKEN_VAULT_ADDR, abi.encode(ETH_TOKEN_ADDRESS))); + + bytes internal exampleChainCommitment; + + IChainTypeManager internal chainTypeManager; + + // L2ContractDeployer internal deployScript; + + function setUp() public { + aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); + + standardErc20Impl = new BridgedStandardERC20(); + beacon = new UpgradeableBeacon(address(standardErc20Impl)); + beacon.transferOwnership(ownerWallet); + + // One of the purposes of deploying it here is to publish its bytecode + BeaconProxy beaconProxy = new BeaconProxy(address(beacon), new bytes(0)); + proxy = beaconProxy; + bytes32 beaconProxyBytecodeHash; + assembly { + beaconProxyBytecodeHash := extcodehash(beaconProxy) + } + + address l2SharedBridge = makeAddr("l2SharedBridge"); + + initSystemContracts( + SystemContractsArgs({ + l1ChainId: L1_CHAIN_ID, + eraChainId: ERA_CHAIN_ID, + l1AssetRouter: l1AssetRouter, + legacySharedBridge: l2SharedBridge, + l2TokenBeacon: address(beacon), + l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, + aliasedOwner: ownerWallet, + contractsDeployedAlready: false, + l1CtmDeployer: l1CTMDeployer + }) + ); + deployL2Contracts(L1_CHAIN_ID); + + vm.prank(aliasedL1AssetRouter); + l2AssetRouter.setAssetHandlerAddress(L1_CHAIN_ID, ctmAssetId, L2_BRIDGEHUB_ADDR); + vm.prank(ownerWallet); + l2Bridgehub.addChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1CTMDeployer)); + l2Bridgehub.setAssetHandlerAddress( + bytes32(uint256(uint160(l1CTM))), + address(addresses.stateTransition.chainTypeManagerProxy) + ); + chainTypeManager = IChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); + getExampleChainCommitment(); + } + + function test_gatewayShouldFinalizeDeposit() public { + finalizeDeposit(); + } + + function getExampleChainCommitment() internal returns (bytes memory) { + vm.mockCall( + L2_ASSET_ROUTER_ADDR, + abi.encodeWithSelector(IL1AssetRouter.L1_NULLIFIER.selector), + abi.encode(L2_ASSET_ROUTER_ADDR) + ); + vm.mockCall( + L2_ASSET_ROUTER_ADDR, + abi.encodeWithSelector(IL1Nullifier.l2BridgeAddress.selector), + abi.encode(address(0)) + ); + vm.prank(L2_BRIDGEHUB_ADDR); + address chainAddress = chainTypeManager.createNewChain( + ERA_CHAIN_ID + 1, + baseTokenAssetId, + L2_ASSET_ROUTER_ADDR, + address(0x1), + abi.encode(config.contracts.diamondCutData, generatedData.forceDeploymentsData), + new bytes[](0) + ); + exampleChainCommitment = abi.encode(IZKChain(chainAddress).prepareChainCommitment()); + } + + function test_forwardToL3OnGateway() public { + // todo fix this test + finalizeDeposit(); + IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); + vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); + bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); + } + + function finalizeDeposit() public { + bytes memory chainData = exampleChainCommitment; + bytes memory ctmData = abi.encode( + baseTokenAssetId, + msg.sender, + chainTypeManager.protocolVersion(), + config.contracts.diamondCutData + ); + BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + chainId: mintChainId, + baseTokenAssetId: baseTokenAssetId, + ctmData: ctmData, + chainData: chainData + }); + vm.prank(aliasedL1AssetRouter); + l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + } + + function initSystemContracts(SystemContractsArgs memory _args) internal virtual; + function deployL2Contracts(uint256 _l1ChainId) public virtual; +} diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol b/l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol new file mode 100644 index 000000000..edc483b70 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {StdStorage, stdStorage, stdToml} from "forge-std/Test.sol"; +import {Script, console2 as console} from "forge-std/Script.sol"; + +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {L1AssetRouter} from "contracts/bridge/asset-router/L1AssetRouter.sol"; +import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; +import {L1NativeTokenVault} from "contracts/bridge/ntv/L1NativeTokenVault.sol"; +import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; +import {CTMDeploymentTracker} from "contracts/bridgehub/CTMDeploymentTracker.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {DeployedAddresses, Config} from "deploy-scripts/DeployUtils.s.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; + +import {L2_MESSAGE_ROOT_ADDR, L2_BRIDGEHUB_ADDR, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; + +import {MessageRoot} from "contracts/bridgehub/MessageRoot.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {L2NativeTokenVault} from "contracts/bridge/ntv/L2NativeTokenVault.sol"; +import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; +import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; +import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; + +struct SystemContractsArgs { + uint256 l1ChainId; + uint256 eraChainId; + address l1AssetRouter; + address legacySharedBridge; + address l2TokenBeacon; + bytes32 l2TokenProxyBytecodeHash; + address aliasedOwner; + bool contractsDeployedAlready; + address l1CtmDeployer; +} + +contract L2ContractDummyDeployer is DeployUtils { + using stdToml for string; + using stdStorage for StdStorage; + + function initSystemContracts(SystemContractsArgs memory _args) internal virtual { + bytes32 baseTokenAssetId = DataEncoding.encodeNTVAssetId(_args.l1ChainId, ETH_TOKEN_ADDRESS); + address wethToken = address(0x1); + + address messageRoot = address(new MessageRoot(IBridgehub(L2_BRIDGEHUB_ADDR))); + address bridgehub = address(new Bridgehub(_args.l1ChainId, _args.aliasedOwner, 100)); + address assetRouter = address( + new L2AssetRouter( + _args.l1ChainId, + _args.eraChainId, + _args.l1AssetRouter, + _args.legacySharedBridge, + baseTokenAssetId, + _args.aliasedOwner + ) + ); + address ntv = address( + new L2NativeTokenVault( + _args.l1ChainId, + _args.aliasedOwner, + _args.l2TokenProxyBytecodeHash, + _args.legacySharedBridge, + _args.l2TokenBeacon, + _args.contractsDeployedAlready, + wethToken, + baseTokenAssetId + ) + ); + + vm.etch(L2_MESSAGE_ROOT_ADDR, messageRoot.code); + MessageRoot(L2_MESSAGE_ROOT_ADDR).initialize(); + + vm.etch(L2_BRIDGEHUB_ADDR, bridgehub.code); + Bridgehub(L2_BRIDGEHUB_ADDR).initialize(_args.aliasedOwner); + vm.prank(_args.aliasedOwner); + Bridgehub(L2_BRIDGEHUB_ADDR).setAddresses( + L2_ASSET_ROUTER_ADDR, + ICTMDeploymentTracker(_args.l1CtmDeployer), + IMessageRoot(L2_MESSAGE_ROOT_ADDR) + ); + + vm.etch(L2_ASSET_ROUTER_ADDR, assetRouter.code); + stdstore.target(address(L2_ASSET_ROUTER_ADDR)).sig("l1AssetRouter()").checked_write(_args.l1AssetRouter); + + stdstore + .target(L2_ASSET_ROUTER_ADDR) + .sig("assetHandlerAddress(bytes32)") + .with_key(baseTokenAssetId) + .checked_write(bytes32(uint256(uint160(L2_NATIVE_TOKEN_VAULT_ADDR)))); + + vm.etch(L2_NATIVE_TOKEN_VAULT_ADDR, ntv.code); + + vm.store(L2_NATIVE_TOKEN_VAULT_ADDR, bytes32(uint256(251)), bytes32(uint256(_args.l2TokenProxyBytecodeHash))); + } + + function deployL2Contracts(uint256 _l1ChainId) public virtual { + string memory root = vm.projectRoot(); + string memory inputPath = string.concat( + root, + "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml" + ); + initializeConfig(inputPath); + addresses.transparentProxyAdmin = address(0x1); + addresses.bridgehub.bridgehubProxy = L2_BRIDGEHUB_ADDR; + addresses.bridges.sharedBridgeProxy = L2_ASSET_ROUTER_ADDR; + addresses.vaults.l1NativeTokenVaultProxy = L2_NATIVE_TOKEN_VAULT_ADDR; + addresses.blobVersionedHashRetriever = address(0x1); + config.l1ChainId = _l1ChainId; + console.log("Deploying L2 contracts"); + instantiateCreate2Factory(); + deployGenesisUpgrade(); + deployVerifier(); + deployValidatorTimelock(); + deployChainTypeManagerContract(); + } + + // add this to be excluded from coverage report + function test() internal virtual override {} +} diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index 595876a91..0356a233b 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -7,12 +7,12 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import "forge-std/console.sol"; -import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +// import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; -import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; +// import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; @@ -21,6 +21,8 @@ import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; import {L2Utils} from "../unit/utils/L2Utils.sol"; @@ -28,116 +30,31 @@ import {SystemContractsArgs} from "../unit/utils/L2Utils.sol"; import {L2ContractDeployer} from "./_SharedL2ContractDeployer.t.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; -contract L2GatewayTests is - Test, - L2ContractDeployer // is L1ContractDeployer, ZKChainDeployer, TokenDeployer { -{ +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {L2GatewayDummyTestsAbstract} from "../../l1/integration/L2GatewayDummyTestsAbstract.t.sol"; +import {L2ContractDummyDeployer} from "../../l1/integration/_SharedL2ContractDummyDeployer.sol"; + +contract L2GatewayTests is Test, L2GatewayDummyTestsAbstract, L2ContractDeployer { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. - address internal l1BridgeWallet = address(1); - address internal aliasedL1BridgeWallet; - - // The owner of the beacon and the native token vault - address internal ownerWallet = address(2); - - BridgedStandardERC20 internal standardErc20Impl; - - UpgradeableBeacon internal beacon; - BeaconProxy internal proxy; - - IL2AssetRouter l2AssetRouter = IL2AssetRouter(L2_ASSET_ROUTER_ADDR); - IBridgehub l2Bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); - - uint256 internal constant L1_CHAIN_ID = 9; - uint256 internal ERA_CHAIN_ID = 270; - address internal l1AssetRouter = makeAddr("l1AssetRouter"); - address internal aliasedL1AssetRouter = AddressAliasHelper.applyL1ToL2Alias(l1AssetRouter); - - address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); - address internal l1CTM = makeAddr("l1CTM"); - bytes32 internal ctmAssetId = keccak256(abi.encode(L1_CHAIN_ID, l1CTMDeployer, abi.encode(l1CTM))); - - bytes32 internal baseTokenAssetId = - keccak256(abi.encode(L1_CHAIN_ID, L2_NATIVE_TOKEN_VAULT_ADDR, abi.encode(ETH_TOKEN_ADDRESS))); - - bytes internal exampleChainCommitment; - - IChainTypeManager internal chainTypeManager; - - // L2ContractDeployer internal deployScript; - - function setUp() public { - aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); - - standardErc20Impl = new BridgedStandardERC20(); - beacon = new UpgradeableBeacon(address(standardErc20Impl)); - beacon.transferOwnership(ownerWallet); - - // One of the purposes of deploying it here is to publish its bytecode - BeaconProxy beaconProxy = new BeaconProxy(address(beacon), new bytes(0)); - proxy = beaconProxy; - bytes32 beaconProxyBytecodeHash; - assembly { - beaconProxyBytecodeHash := extcodehash(beaconProxy) - } - - address l2SharedBridge = makeAddr("l2SharedBridge"); - - L2Utils.initSystemContracts( - SystemContractsArgs({ - l1ChainId: L1_CHAIN_ID, - eraChainId: ERA_CHAIN_ID, - l1AssetRouter: l1AssetRouter, - legacySharedBridge: l2SharedBridge, - l2TokenBeacon: address(beacon), - l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, - aliasedOwner: ownerWallet, - contractsDeployedAlready: false, - l1CtmDeployer: l1CTMDeployer - }) - ); - deployL2Contracts(); - - vm.prank(aliasedL1AssetRouter); - l2AssetRouter.setAssetHandlerAddress(L1_CHAIN_ID, ctmAssetId, L2_BRIDGEHUB_ADDR); - vm.prank(ownerWallet); - l2Bridgehub.addChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1CTMDeployer)); - l2Bridgehub.setAssetHandlerAddress( - bytes32(uint256(uint160(l1CTM))), - address(addresses.stateTransition.chainTypeManagerProxy) - ); - chainTypeManager = IChainTypeManager(address(addresses.stateTransition.chainTypeManagerProxy)); - } + function test() internal virtual override(DeployUtils, L2ContractDeployer) {} - function test_gatewayShouldFinalizeDeposit() public { - finalizeDeposit(); + function initSystemContracts( + SystemContractsArgs memory _args + ) internal override(L2GatewayDummyTests, L2ContractDeployer) { + super.initSystemContracts(_args); } - function test_forwardToL3OnGateway() public { - // todo fix this test - // finalizeDeposit(); - // IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); - // vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); - // bridgehub.forwardTransactionOnGateway(ERA_CHAIN_ID, bytes32(0), 0); + function deployViaCreate2( + bytes memory creationCode, + bytes memory constructorArgs + ) internal override(DeployUtils, L2ContractDeployer) returns (address) { + return super.deployViaCreate2(creationCode, constructorArgs); } - function finalizeDeposit() public { - // bytes memory chainData = abi.encode(exampleChainCommitment); - // bytes memory ctmData = abi.encode( - // baseTokenAssetId, - // msg.sender, - // chainTypeManager.protocolVersion(), - // config.contracts.diamondCutData - // ); - // BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ - // chainId: ERA_CHAIN_ID, - // baseTokenAssetId: baseTokenAssetId, - // ctmData: ctmData, - // chainData: chainData - // }); - // vm.prank(aliasedL1AssetRouter); - // l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + function deployL2Contracts(uint256 _l1ChainId) public override(L2GatewayDummyTests, L2ContractDummyDeployer) { + super.deployL2Contracts(_l1ChainId); } } diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol index 95411eba8..31d69a7d4 100644 --- a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol @@ -16,31 +16,26 @@ import {DeployedAddresses, Config} from "deploy-scripts/DeployUtils.s.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {L2_BRIDGEHUB_ADDR, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; + import {L2Utils} from "../unit/utils/L2Utils.sol"; +import {L2ContractDummyDeployer, SystemContractsArgs} from "../../l1/integration/_SharedL2ContractDummyDeployer.sol"; -contract L2ContractDeployer is DeployUtils { +contract L2ContractDeployer is DeployUtils, L2ContractDummyDeployer { using stdToml for string; + function initSystemContracts(SystemContractsArgs memory _args) internal virtual override { + L2Utils.initSystemContracts(_args); + } + function deployViaCreate2( bytes memory creationCode, bytes memory constructorArgs - ) internal override returns (address) { + ) internal virtual override returns (address) { console.log("Deploying via create2 L2"); return L2Utils.deployViaCreat2L2(creationCode, constructorArgs, config.contracts.create2FactorySalt); } - function deployL2Contracts() public { - string memory root = vm.projectRoot(); - string memory inputPath = string.concat( - root, - "/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-l1.toml" - ); - initializeConfig(inputPath); - addresses.transparentProxyAdmin = address(0x1); - deployGenesisUpgrade(); - deployChainTypeManagerContract(); - } - // add this to be excluded from coverage report - function test() internal virtual override {} + function test() internal virtual override(DeployUtils, L2ContractDummyDeployer) {} } diff --git a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol index ee0daaef3..2586fb836 100644 --- a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol @@ -16,7 +16,8 @@ import {L2NativeTokenVault} from "contracts/bridge/ntv/L2NativeTokenVault.sol"; import {L2SharedBridgeLegacy} from "contracts/bridge/L2SharedBridgeLegacy.sol"; import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; -import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {Bridgehub, IBridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {MessageRoot} from "contracts/bridgehub/MessageRoot.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; @@ -25,18 +26,7 @@ import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {SystemContractsCaller} from "contracts/common/libraries/SystemContractsCaller.sol"; import {DeployFailed} from "contracts/common/L1ContractErrors.sol"; - -struct SystemContractsArgs { - uint256 l1ChainId; - uint256 eraChainId; - address l1AssetRouter; - address legacySharedBridge; - address l2TokenBeacon; - bytes32 l2TokenProxyBytecodeHash; - address aliasedOwner; - bool contractsDeployedAlready; - address l1CtmDeployer; -} +import {SystemContractsArgs} from "../../../l1/integration/_SharedL2ContractDummyDeployer.sol"; library L2Utils { address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); @@ -85,6 +75,7 @@ library L2Utils { } function forceDeploySystemContracts(SystemContractsArgs memory _args) internal { + forceDeployMessageRoot(); forceDeployBridgehub( _args.l1ChainId, _args.eraChainId, @@ -110,6 +101,11 @@ library L2Utils { ); } + function forceDeployMessageRoot() internal { + new MessageRoot(IBridgehub(L2_BRIDGEHUB_ADDR)); + forceDeployWithConstructor("MessageRoot", L2_MESSAGE_ROOT_ADDR, abi.encode(L2_BRIDGEHUB_ADDR)); + } + function forceDeployBridgehub( uint256 _l1ChainId, uint256 _eraChainId, From acc2e773f23ecb1744c4027407a993dc0196cf4b Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 12:31:36 +0100 Subject: [PATCH 14/27] renaming --- .../test/foundry/l1/integration/L2GatewayDummyTests.t.sol | 8 ++++---- ...myTestsAbstract.t.sol => L2GatewayTestsAbstract.t.sol} | 3 +-- .../test/foundry/l2/integration/L2GatewayTests.t.sol | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) rename l1-contracts/test/foundry/l1/integration/{L2GatewayDummyTestsAbstract.t.sol => L2GatewayTestsAbstract.t.sol} (98%) diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol index a588bc841..198a28041 100644 --- a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol @@ -31,20 +31,20 @@ import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {L2GatewayDummyTests} from "./L2GatewayDummyTests.t.sol"; +import {L2GatewayTestsAbstract} from "./L2GatewayTestsAbstract.t.sol"; -contract L2GatewayDummyTests is Test, L2ContractDummyDeployer, L2GatewayDummyTests { +contract L2GatewayDummyTests is Test, L2ContractDummyDeployer, L2GatewayTestsAbstract { function test() internal virtual override(DeployUtils, L2ContractDummyDeployer) {} function initSystemContracts( SystemContractsArgs memory _args - ) internal virtual override(L2GatewayDummyTests, L2ContractDummyDeployer) { + ) internal virtual override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { super.initSystemContracts(_args); } function deployL2Contracts( uint256 _l1ChainId - ) public virtual override(L2GatewayDummyTests, L2ContractDummyDeployer) { + ) public virtual override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { super.deployL2Contracts(_l1ChainId); } } diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol similarity index 98% rename from l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol rename to l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol index 404822868..a7da4bae2 100644 --- a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTestsAbstract.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol @@ -32,10 +32,9 @@ import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -abstract contract L2GatewayDummyAbstract is +abstract contract L2GatewayTestsAbstract is Test, DeployUtils - // L2ContractDummyDeployer { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index 0356a233b..3111ca2da 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -33,17 +33,17 @@ import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.so import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {L2GatewayDummyTestsAbstract} from "../../l1/integration/L2GatewayDummyTestsAbstract.t.sol"; +import {L2GatewayTestsAbstract} from "../../l1/integration/L2GatewayTestsAbstract.t.sol"; import {L2ContractDummyDeployer} from "../../l1/integration/_SharedL2ContractDummyDeployer.sol"; -contract L2GatewayTests is Test, L2GatewayDummyTestsAbstract, L2ContractDeployer { +contract L2GatewayTests is Test, L2GatewayTestsAbstract, L2ContractDeployer { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. function test() internal virtual override(DeployUtils, L2ContractDeployer) {} function initSystemContracts( SystemContractsArgs memory _args - ) internal override(L2GatewayDummyTests, L2ContractDeployer) { + ) internal override(L2GatewayTestsAbstract, L2ContractDeployer) { super.initSystemContracts(_args); } @@ -54,7 +54,7 @@ contract L2GatewayTests is Test, L2GatewayDummyTestsAbstract, L2ContractDeployer return super.deployViaCreate2(creationCode, constructorArgs); } - function deployL2Contracts(uint256 _l1ChainId) public override(L2GatewayDummyTests, L2ContractDummyDeployer) { + function deployL2Contracts(uint256 _l1ChainId) public override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { super.deployL2Contracts(_l1ChainId); } } From 21d11f3f1eeb714d52a303724d4cca578d5ba594 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 12:34:46 +0100 Subject: [PATCH 15/27] undo bh initialize change --- l1-contracts/contracts/bridgehub/Bridgehub.sol | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/l1-contracts/contracts/bridgehub/Bridgehub.sol b/l1-contracts/contracts/bridgehub/Bridgehub.sol index e9bb2a305..cd22a9cc7 100644 --- a/l1-contracts/contracts/bridgehub/Bridgehub.sol +++ b/l1-contracts/contracts/bridgehub/Bridgehub.sol @@ -153,17 +153,14 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus // This is indeed true, since the only methods where this immutable is used are the ones with `onlyL1` modifier. // We will change this with interop. ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, ETH_TOKEN_ADDRESS); - _initialize(_owner); + _transferOwnership(_owner); + whitelistedSettlementLayers[L1_CHAIN_ID] = true; } /// @notice used to initialize the contract /// @notice this contract is also deployed on L2 as a system contract there the owner and the related functions will not be used /// @param _owner the owner of the contract function initialize(address _owner) external reentrancyGuardInitializer { - _initialize(_owner); - } - - function _initialize(address _owner) internal { _transferOwnership(_owner); assetIdIsRegistered[ETH_TOKEN_ASSET_ID] = true; whitelistedSettlementLayers[L1_CHAIN_ID] = true; From 3d8b20284e5d3654f56753e854418dc3bc1334f7 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 12:37:11 +0100 Subject: [PATCH 16/27] fmt --- .../test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol index a7da4bae2..a3b56dc15 100644 --- a/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol @@ -32,10 +32,7 @@ import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -abstract contract L2GatewayTestsAbstract is - Test, - DeployUtils -{ +abstract contract L2GatewayTestsAbstract is Test, DeployUtils { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. address internal l1BridgeWallet = address(1); From 72c83b0b3832e66333524898a7e9ad1d3eccf464 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 20:55:52 +0100 Subject: [PATCH 17/27] getting tests to work --- .../bridge/ntv/L2NativeTokenVault.sol | 4 +- .../test/L2NativeTokenVaultDev.sol | 76 +++++++++++++ .../L2Erc20L1Test.t.sol} | 15 +-- .../l2-dummy-tests/L2Erc20TestAbstract.t.sol} | 83 +++----------- .../l2-dummy-tests/L2GatewayL1Test.t.sol | 51 +++++++++ .../L2GatewayTestAbstract.t.sol | 65 +++++++++++ .../l2-dummy-tests/L2WethTestAbstract.t.sol} | 45 ++++---- .../_SharedL2ContractDeployer.sol} | 107 ++++++++++++------ .../_SharedL2ContractL1DeployerUtils.sol} | 6 +- .../l2/integration/L2ERC20BridgeTest.t.sol | 49 ++++++++ .../l2/integration/L2GatewayTests.t.sol | 22 ++-- .../{unit/utils => integration}/L2Utils.sol | 44 +------ .../test/foundry/l2/integration/WETH.t.sol | 36 ++++++ ...l => _SharedL2ContractL2DeployerUtils.sol} | 8 +- .../ValidiumL2DAValidator.t.sol | 2 +- 15 files changed, 421 insertions(+), 192 deletions(-) create mode 100644 l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol rename l1-contracts/test/foundry/l1/integration/{L2GatewayDummyTests.t.sol => l2-dummy-tests/L2Erc20L1Test.t.sol} (72%) rename l1-contracts/test/foundry/{l2/unit/erc20/L2Erc20BridgeTest.t.sol => l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol} (55%) create mode 100644 l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol create mode 100644 l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol rename l1-contracts/test/foundry/{l2/unit/weth/WETH.t.sol => l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol} (61%) rename l1-contracts/test/foundry/l1/integration/{L2GatewayTestsAbstract.t.sol => l2-dummy-tests/_SharedL2ContractDeployer.sol} (63%) rename l1-contracts/test/foundry/l1/integration/{_SharedL2ContractDummyDeployer.sol => l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol} (94%) create mode 100644 l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol rename l1-contracts/test/foundry/l2/{unit/utils => integration}/L2Utils.sol (85%) create mode 100644 l1-contracts/test/foundry/l2/integration/WETH.t.sol rename l1-contracts/test/foundry/l2/integration/{_SharedL2ContractDeployer.t.sol => _SharedL2ContractL2DeployerUtils.sol} (81%) diff --git a/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol index a6a0ff62d..4b83037a7 100644 --- a/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/L2NativeTokenVault.sol @@ -132,7 +132,7 @@ contract L2NativeTokenVault is IL2NativeTokenVault, NativeTokenVault { /// for the code of the proxy. /// @param _salt The salt used for beacon proxy deployment of L2 bridged token. /// @return proxy The beacon proxy, i.e. L2 bridged token. - function _deployBeaconProxy(bytes32 _salt) internal override returns (BeaconProxy proxy) { + function _deployBeaconProxy(bytes32 _salt) internal virtual override returns (BeaconProxy proxy) { if (address(L2_LEGACY_SHARED_BRIDGE) == address(0)) { // Deploy the beacon proxy for the L2 token @@ -177,7 +177,7 @@ contract L2NativeTokenVault is IL2NativeTokenVault, NativeTokenVault { function calculateCreate2TokenAddress( uint256 _originChainId, address _l1Token - ) public view override(INativeTokenVault, NativeTokenVault) returns (address) { + ) public view virtual override(INativeTokenVault, NativeTokenVault) returns (address) { bytes32 constructorInputHash = keccak256(abi.encode(address(bridgedTokenBeacon), "")); bytes32 salt = _getCreate2Salt(_originChainId, _l1Token); if (address(L2_LEGACY_SHARED_BRIDGE) != address(0)) { diff --git a/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol b/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol new file mode 100644 index 000000000..0c26d8d14 --- /dev/null +++ b/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; +import {Create2} from "@openzeppelin/contracts-v4/utils/Create2.sol"; +import {IBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/IBeacon.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; + +import {INativeTokenVault} from "contracts/bridge/ntv/INativeTokenVault.sol"; +import {NativeTokenVault} from "contracts/bridge/ntv/NativeTokenVault.sol"; +import {L2NativeTokenVault} from "contracts/bridge/ntv/L2NativeTokenVault.sol"; +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; + +contract L2NativeTokenVaultDev is L2NativeTokenVault { + constructor( + uint256 _l1ChainId, + address _aliasedOwner, + bytes32 _l2TokenProxyBytecodeHash, + address _legacySharedBridge, + address _bridgedTokenBeacon, + bool _contractsDeployedAlready, + address _wethToken, + bytes32 _baseTokenAssetId + ) + L2NativeTokenVault( + _l1ChainId, + _aliasedOwner, + _l2TokenProxyBytecodeHash, + _legacySharedBridge, + _bridgedTokenBeacon, + _contractsDeployedAlready, + _wethToken, + _baseTokenAssetId + ) + {} + + /// @notice copied from L1NTV for L1 compilation + function calculateCreate2TokenAddress( + uint256 _originChainId, + address _l1Token + ) public view override(L2NativeTokenVault) returns (address) { + bytes32 salt = _getCreate2Salt(_originChainId, _l1Token); + return + Create2.computeAddress( + salt, + keccak256(abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(bridgedTokenBeacon, ""))) + ); + } + + function deployBridgedStandardERC20(address _owner) external { + _transferOwnership(_owner); + + address l2StandardToken = address(new BridgedStandardERC20{salt: bytes32(0)}()); + + UpgradeableBeacon tokenBeacon = new UpgradeableBeacon{salt: bytes32(0)}(l2StandardToken); + + tokenBeacon.transferOwnership(owner()); + bridgedTokenBeacon = IBeacon(address(tokenBeacon)); + emit L2TokenBeaconUpdated(address(bridgedTokenBeacon), l2TokenProxyBytecodeHash); + } + + function test() external pure { + // test + } + + function _deployBeaconProxy(bytes32 _salt) internal virtual override returns (BeaconProxy proxy) { + // Use CREATE2 to deploy the BeaconProxy + address proxyAddress = Create2.deploy( + 0, + _salt, + abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(bridgedTokenBeacon, "")) + ); + return BeaconProxy(payable(proxyAddress)); + } +} diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20L1Test.t.sol similarity index 72% rename from l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20L1Test.t.sol index 198a28041..b6346a09d 100644 --- a/l1-contracts/test/foundry/l1/integration/L2GatewayDummyTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20L1Test.t.sol @@ -25,26 +25,27 @@ import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; -import {L2ContractDummyDeployer} from "./_SharedL2ContractDummyDeployer.sol"; +import {SharedL2ContractDeployer} from "./_SharedL2ContractDeployer.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; -import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {L2GatewayTestsAbstract} from "./L2GatewayTestsAbstract.t.sol"; +import {L2Erc20TestAbstract} from "./L2Erc20TestAbstract.t.sol"; +import {SharedL2ContractL1DeployerUtils} from "./_SharedL2ContractL1DeployerUtils.sol"; -contract L2GatewayDummyTests is Test, L2ContractDummyDeployer, L2GatewayTestsAbstract { - function test() internal virtual override(DeployUtils, L2ContractDummyDeployer) {} +contract L2Erc20L1Test is Test, SharedL2ContractL1DeployerUtils, SharedL2ContractDeployer, L2Erc20TestAbstract { + function test() internal virtual override(DeployUtils, SharedL2ContractL1DeployerUtils) {} function initSystemContracts( SystemContractsArgs memory _args - ) internal virtual override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { + ) internal virtual override(SharedL2ContractDeployer, SharedL2ContractL1DeployerUtils) { super.initSystemContracts(_args); } function deployL2Contracts( uint256 _l1ChainId - ) public virtual override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { + ) public virtual override(SharedL2ContractDeployer, SharedL2ContractL1DeployerUtils) { super.deployL2Contracts(_l1ChainId); } } diff --git a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol similarity index 55% rename from l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol index d29d2b7ff..fcabf0d01 100644 --- a/l1-contracts/test/foundry/l2/unit/erc20/L2Erc20BridgeTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol @@ -14,82 +14,33 @@ import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol" import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; -import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; -import {L2Utils, SystemContractsArgs} from "../utils/L2Utils.sol"; - -contract L2Erc20BridgeTest is Test { - // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. - // It is a bit easier to use EOA and it is sufficient for the tests. - address internal l1BridgeWallet = address(1); - address internal aliasedL1BridgeWallet; - - // The owner of the beacon and the native token vault - address internal ownerWallet = address(2); - - BridgedStandardERC20 internal standardErc20Impl; - - UpgradeableBeacon internal beacon; - BeaconProxy internal proxy; - - uint256 internal constant L1_CHAIN_ID = 9; - uint256 internal ERA_CHAIN_ID = 270; - - // We won't actually deploy an L1 token in these tests, but we need some address for it. - address internal L1_TOKEN_ADDRESS = 0x1111100000000000000000000000000000011111; - - string internal constant TOKEN_DEFAULT_NAME = "TestnetERC20Token"; - string internal constant TOKEN_DEFAULT_SYMBOL = "TET"; - uint8 internal constant TOKEN_DEFAULT_DECIMALS = 18; - address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); - - function setUp() public { - aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); - - standardErc20Impl = new BridgedStandardERC20(); - beacon = new UpgradeableBeacon(address(standardErc20Impl)); - beacon.transferOwnership(ownerWallet); - - // One of the purposes of deploying it here is to publish its bytecode - BeaconProxy beaconProxy = new BeaconProxy(address(beacon), new bytes(0)); - proxy = beaconProxy; - bytes32 beaconProxyBytecodeHash; - assembly { - beaconProxyBytecodeHash := extcodehash(beaconProxy) - } - - address l2SharedBridge = L2Utils.deploySharedBridgeLegacy( - L1_CHAIN_ID, - ERA_CHAIN_ID, - ownerWallet, - l1BridgeWallet, - beaconProxyBytecodeHash - ); - L2Utils.initSystemContracts( - SystemContractsArgs({ - l1ChainId: L1_CHAIN_ID, - eraChainId: ERA_CHAIN_ID, - l1AssetRouter: l1BridgeWallet, - legacySharedBridge: l2SharedBridge, - l2TokenBeacon: address(beacon), - l2TokenProxyBytecodeHash: beaconProxyBytecodeHash, - aliasedOwner: ownerWallet, - contractsDeployedAlready: false, - l1CtmDeployer: l1CTMDeployer - }) - ); - } +import {SharedL2ContractDeployer} from "./_SharedL2ContractDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +abstract contract L2Erc20TestAbstract is Test, SharedL2ContractDeployer { function performDeposit(address depositor, address receiver, uint256 amount) internal { - vm.prank(aliasedL1BridgeWallet); + vm.prank(aliasedL1AssetRouter); L2AssetRouter(L2_ASSET_ROUTER_ADDR).finalizeDeposit({ _l1Sender: depositor, _l2Receiver: receiver, _l1Token: L1_TOKEN_ADDRESS, _amount: amount, - _data: L2Utils.encodeTokenData(TOKEN_DEFAULT_NAME, TOKEN_DEFAULT_SYMBOL, TOKEN_DEFAULT_DECIMALS) + _data: encodeTokenData(TOKEN_DEFAULT_NAME, TOKEN_DEFAULT_SYMBOL, TOKEN_DEFAULT_DECIMALS) }); } diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol new file mode 100644 index 000000000..3e8b04e42 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; + +import {SharedL2ContractDeployer} from "./_SharedL2ContractDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {L2GatewayTestAbstract} from "./L2GatewayTestAbstract.t.sol"; +import {SharedL2ContractL1DeployerUtils} from "./_SharedL2ContractL1DeployerUtils.sol"; + +contract L2GatewayL1Test is Test, SharedL2ContractL1DeployerUtils, SharedL2ContractDeployer, L2GatewayTestAbstract { + function test() internal virtual override(DeployUtils, SharedL2ContractL1DeployerUtils) {} + + function initSystemContracts( + SystemContractsArgs memory _args + ) internal virtual override(SharedL2ContractDeployer, SharedL2ContractL1DeployerUtils) { + super.initSystemContracts(_args); + } + + function deployL2Contracts( + uint256 _l1ChainId + ) public virtual override(SharedL2ContractDeployer, SharedL2ContractL1DeployerUtils) { + super.deployL2Contracts(_l1ChainId); + } +} diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol new file mode 100644 index 000000000..e2bf33d84 --- /dev/null +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; + +import {SharedL2ContractDeployer} from "./_SharedL2ContractDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; + +abstract contract L2GatewayTestAbstract is Test, SharedL2ContractDeployer { + function test_gatewayShouldFinalizeDeposit() public { + finalizeDeposit(); + } + + function test_forwardToL3OnGateway() public { + // todo fix this test + finalizeDeposit(); + IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); + vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); + bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); + } + + function finalizeDeposit() public { + bytes memory chainData = exampleChainCommitment; + bytes memory ctmData = abi.encode( + baseTokenAssetId, + msg.sender, + chainTypeManager.protocolVersion(), + config.contracts.diamondCutData + ); + BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + chainId: mintChainId, + baseTokenAssetId: baseTokenAssetId, + ctmData: ctmData, + chainData: chainData + }); + vm.prank(aliasedL1AssetRouter); + l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + } +} diff --git a/l1-contracts/test/foundry/l2/unit/weth/WETH.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol similarity index 61% rename from l1-contracts/test/foundry/l2/unit/weth/WETH.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol index 6cbc44fa7..d2a43be2e 100644 --- a/l1-contracts/test/foundry/l2/unit/weth/WETH.t.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol @@ -2,33 +2,38 @@ pragma solidity ^0.8.20; -import {Test} from "forge-std/Test.sol"; - -import {L2WrappedBaseToken} from "contracts/bridge/L2WrappedBaseToken.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; - -import {Unauthorized, UnimplementedMessage, BridgeMintNotImplemented} from "contracts/common/L1ContractErrors.sol"; +// solhint-disable gas-custom-errors -contract WethTest is Test { - L2WrappedBaseToken internal weth; +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; - // The owner of the proxy - address internal ownerWallet = address(2); +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; - address internal l2BridgeAddress = address(3); - address internal l1Address = address(4); +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; - function setUp() public { - ownerWallet = makeAddr("owner"); - L2WrappedBaseToken impl = new L2WrappedBaseToken(); +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; - TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), ownerWallet, ""); +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; +import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; +import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; +import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; +import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; - weth = L2WrappedBaseToken(payable(proxy)); +import {SharedL2ContractDeployer} from "./_SharedL2ContractDeployer.sol"; +import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; +import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; - weth.initializeV2("Wrapped Ether", "WETH", l2BridgeAddress, l1Address); - } +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {Unauthorized, UnimplementedMessage, BridgeMintNotImplemented} from "contracts/common/L1ContractErrors.sol"; +abstract contract L2WethTestAbstract is Test, SharedL2ContractDeployer { function test_shouldDepositWethByCallingDeposit() public { uint256 amount = 100; weth.deposit{value: amount}(); @@ -102,7 +107,7 @@ contract WethTest is Test { function test_revertWhenCallingBridgeMint() public { vm.expectRevert(abi.encodeWithSelector(BridgeMintNotImplemented.selector)); - vm.prank(l2BridgeAddress); + vm.prank(L2_ASSET_ROUTER_ADDR); weth.bridgeMint(address(1), 1); } diff --git a/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol similarity index 63% rename from l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol index a3b56dc15..aa7e5676a 100644 --- a/l1-contracts/test/foundry/l1/integration/L2GatewayTestsAbstract.t.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol @@ -7,6 +7,8 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import "forge-std/console.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; + import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; @@ -24,19 +26,20 @@ import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; +import {L2WrappedBaseToken} from "contracts/bridge/L2WrappedBaseToken.sol"; +import {L2SharedBridgeLegacy} from "contracts/bridge/L2SharedBridgeLegacy.sol"; +import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; -import {L2ContractDummyDeployer} from "./_SharedL2ContractDummyDeployer.sol"; +// import {L2ContractL1Deployer} from "./_SharedL2ContractL1Deployer.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; -import {SystemContractsArgs} from "./_SharedL2ContractDummyDeployer.sol"; +import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -abstract contract L2GatewayTestsAbstract is Test, DeployUtils { - // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. - // It is a bit easier to use EOA and it is sufficient for the tests. - address internal l1BridgeWallet = address(1); - address internal aliasedL1BridgeWallet; +abstract contract SharedL2ContractDeployer is Test, DeployUtils { + L2WrappedBaseToken internal weth; + address internal l1WethAddress = address(4); // The owner of the beacon and the native token vault address internal ownerWallet = address(2); @@ -55,6 +58,12 @@ abstract contract L2GatewayTestsAbstract is Test, DeployUtils { address internal l1AssetRouter = makeAddr("l1AssetRouter"); address internal aliasedL1AssetRouter = AddressAliasHelper.applyL1ToL2Alias(l1AssetRouter); + // We won't actually deploy an L1 token in these tests, but we need some address for it. + address internal L1_TOKEN_ADDRESS = 0x1111100000000000000000000000000000011111; + + string internal constant TOKEN_DEFAULT_NAME = "TestnetERC20Token"; + string internal constant TOKEN_DEFAULT_SYMBOL = "TET"; + uint8 internal constant TOKEN_DEFAULT_DECIMALS = 18; address internal l1CTMDeployer = makeAddr("l1CTMDeployer"); address internal l1CTM = makeAddr("l1CTM"); bytes32 internal ctmAssetId = keccak256(abi.encode(L1_CHAIN_ID, l1CTMDeployer, bytes32(uint256(uint160(l1CTM))))); @@ -66,11 +75,7 @@ abstract contract L2GatewayTestsAbstract is Test, DeployUtils { IChainTypeManager internal chainTypeManager; - // L2ContractDeployer internal deployScript; - function setUp() public { - aliasedL1BridgeWallet = AddressAliasHelper.applyL1ToL2Alias(l1BridgeWallet); - standardErc20Impl = new BridgedStandardERC20(); beacon = new UpgradeableBeacon(address(standardErc20Impl)); beacon.transferOwnership(ownerWallet); @@ -83,7 +88,15 @@ abstract contract L2GatewayTestsAbstract is Test, DeployUtils { beaconProxyBytecodeHash := extcodehash(beaconProxy) } - address l2SharedBridge = makeAddr("l2SharedBridge"); + address l2SharedBridge = deployL2SharedBridgeLegacy( + L1_CHAIN_ID, + ERA_CHAIN_ID, + ownerWallet, + l1AssetRouter, + beaconProxyBytecodeHash + ); + + L2WrappedBaseToken weth = deployL2Weth(); initSystemContracts( SystemContractsArgs({ @@ -113,10 +126,6 @@ abstract contract L2GatewayTestsAbstract is Test, DeployUtils { getExampleChainCommitment(); } - function test_gatewayShouldFinalizeDeposit() public { - finalizeDeposit(); - } - function getExampleChainCommitment() internal returns (bytes memory) { vm.mockCall( L2_ASSET_ROUTER_ADDR, @@ -140,30 +149,54 @@ abstract contract L2GatewayTestsAbstract is Test, DeployUtils { exampleChainCommitment = abi.encode(IZKChain(chainAddress).prepareChainCommitment()); } - function test_forwardToL3OnGateway() public { - // todo fix this test - finalizeDeposit(); - IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); - vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); - bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); + /// @notice Encodes the token data. + /// @param name The name of the token. + /// @param symbol The symbol of the token. + /// @param decimals The decimals of the token. + function encodeTokenData( + string memory name, + string memory symbol, + uint8 decimals + ) internal pure returns (bytes memory) { + bytes memory encodedName = abi.encode(name); + bytes memory encodedSymbol = abi.encode(symbol); + bytes memory encodedDecimals = abi.encode(decimals); + + return abi.encode(encodedName, encodedSymbol, encodedDecimals); } - function finalizeDeposit() public { - bytes memory chainData = exampleChainCommitment; - bytes memory ctmData = abi.encode( - baseTokenAssetId, - msg.sender, - chainTypeManager.protocolVersion(), - config.contracts.diamondCutData + function deployL2SharedBridgeLegacy( + uint256 _l1ChainId, + uint256 _eraChainId, + address _aliasedOwner, + address _l1SharedBridge, + bytes32 _l2TokenProxyBytecodeHash + ) internal returns (address) { + bytes32 ethAssetId = DataEncoding.encodeNTVAssetId(_l1ChainId, ETH_TOKEN_ADDRESS); + + L2SharedBridgeLegacy bridge = new L2SharedBridgeLegacy(); + console.log("bridge", address(bridge)); + address proxyAdmin = address(0x1); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(bridge), + proxyAdmin, + abi.encodeWithSelector( + L2SharedBridgeLegacy.initialize.selector, + _l1SharedBridge, + _l2TokenProxyBytecodeHash, + _aliasedOwner + ) ); - BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ - chainId: mintChainId, - baseTokenAssetId: baseTokenAssetId, - ctmData: ctmData, - chainData: chainData - }); - vm.prank(aliasedL1AssetRouter); - l2AssetRouter.finalizeDeposit(L1_CHAIN_ID, ctmAssetId, abi.encode(data)); + console.log("proxy", address(proxy)); + return address(proxy); + } + + function deployL2Weth() internal returns (L2WrappedBaseToken) { + L2WrappedBaseToken wethImpl = new L2WrappedBaseToken(); + TransparentUpgradeableProxy wethProxy = new TransparentUpgradeableProxy(address(wethImpl), ownerWallet, ""); + weth = L2WrappedBaseToken(payable(wethProxy)); + weth.initializeV2("Wrapped Ether", "WETH", L2_ASSET_ROUTER_ADDR, l1WethAddress); + return weth; } function initSystemContracts(SystemContractsArgs memory _args) internal virtual; diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol similarity index 94% rename from l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol rename to l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol index edc483b70..b48b7f0bc 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL2ContractDummyDeployer.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol @@ -22,6 +22,7 @@ import {MessageRoot} from "contracts/bridgehub/MessageRoot.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {L2NativeTokenVault} from "contracts/bridge/ntv/L2NativeTokenVault.sol"; +import {L2NativeTokenVaultDev} from "contracts/dev-contracts/test/L2NativeTokenVaultDev.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; import {IMessageRoot} from "contracts/bridgehub/IMessageRoot.sol"; import {ICTMDeploymentTracker} from "contracts/bridgehub/ICTMDeploymentTracker.sol"; @@ -38,7 +39,7 @@ struct SystemContractsArgs { address l1CtmDeployer; } -contract L2ContractDummyDeployer is DeployUtils { +contract SharedL2ContractL1DeployerUtils is DeployUtils { using stdToml for string; using stdStorage for StdStorage; @@ -59,7 +60,7 @@ contract L2ContractDummyDeployer is DeployUtils { ) ); address ntv = address( - new L2NativeTokenVault( + new L2NativeTokenVaultDev( _args.l1ChainId, _args.aliasedOwner, _args.l2TokenProxyBytecodeHash, @@ -95,6 +96,7 @@ contract L2ContractDummyDeployer is DeployUtils { vm.etch(L2_NATIVE_TOKEN_VAULT_ADDR, ntv.code); vm.store(L2_NATIVE_TOKEN_VAULT_ADDR, bytes32(uint256(251)), bytes32(uint256(_args.l2TokenProxyBytecodeHash))); + L2NativeTokenVaultDev(L2_NATIVE_TOKEN_VAULT_ADDR).deployBridgedStandardERC20(_args.aliasedOwner); } function deployL2Contracts(uint256 _l1ChainId) public virtual { diff --git a/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol b/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol new file mode 100644 index 000000000..9b308fd9e --- /dev/null +++ b/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; +import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; + +import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; +import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; + +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; + +import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; +import {L2Utils, SystemContractsArgs} from "./L2Utils.sol"; +import {SharedL2ContractL2DeployerUtils} from "./_SharedL2ContractL2DeployerUtils.sol"; +import {L2Erc20TestAbstract} from "../../l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol"; +import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; + +contract L2Erc20Test is Test, L2Erc20TestAbstract, SharedL2ContractL2DeployerUtils { + function test() internal virtual override(DeployUtils, SharedL2ContractL2DeployerUtils) {} + + function initSystemContracts( + SystemContractsArgs memory _args + ) internal override(SharedL2ContractDeployer, SharedL2ContractL2DeployerUtils) { + super.initSystemContracts(_args); + } + + function deployViaCreate2( + bytes memory creationCode, + bytes memory constructorArgs + ) internal override(DeployUtils, SharedL2ContractL2DeployerUtils) returns (address) { + return super.deployViaCreate2(creationCode, constructorArgs); + } + + function deployL2Contracts( + uint256 _l1ChainId + ) public override(SharedL2ContractL1DeployerUtils, SharedL2ContractDeployer) { + super.deployL2Contracts(_l1ChainId); + } +} diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index 3111ca2da..f9518d213 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -25,36 +25,38 @@ import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; -import {L2Utils} from "../unit/utils/L2Utils.sol"; -import {SystemContractsArgs} from "../unit/utils/L2Utils.sol"; +import {L2Utils, SystemContractsArgs} from "./L2Utils.sol"; -import {L2ContractDeployer} from "./_SharedL2ContractDeployer.t.sol"; +import {SharedL2ContractL2DeployerUtils} from "./_SharedL2ContractL2DeployerUtils.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {L2GatewayTestsAbstract} from "../../l1/integration/L2GatewayTestsAbstract.t.sol"; -import {L2ContractDummyDeployer} from "../../l1/integration/_SharedL2ContractDummyDeployer.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; +import {L2GatewayTestAbstract} from "../../l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol"; +import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; -contract L2GatewayTests is Test, L2GatewayTestsAbstract, L2ContractDeployer { +contract L2GatewayTests is Test, L2GatewayTestAbstract, SharedL2ContractL2DeployerUtils { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. // It is a bit easier to use EOA and it is sufficient for the tests. - function test() internal virtual override(DeployUtils, L2ContractDeployer) {} + function test() internal virtual override(DeployUtils, SharedL2ContractL2DeployerUtils) {} function initSystemContracts( SystemContractsArgs memory _args - ) internal override(L2GatewayTestsAbstract, L2ContractDeployer) { + ) internal override(SharedL2ContractDeployer, SharedL2ContractL2DeployerUtils) { super.initSystemContracts(_args); } function deployViaCreate2( bytes memory creationCode, bytes memory constructorArgs - ) internal override(DeployUtils, L2ContractDeployer) returns (address) { + ) internal override(DeployUtils, SharedL2ContractL2DeployerUtils) returns (address) { return super.deployViaCreate2(creationCode, constructorArgs); } - function deployL2Contracts(uint256 _l1ChainId) public override(L2GatewayTestsAbstract, L2ContractDummyDeployer) { + function deployL2Contracts( + uint256 _l1ChainId + ) public override(SharedL2ContractL1DeployerUtils, SharedL2ContractDeployer) { super.deployL2Contracts(_l1ChainId); } } diff --git a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol b/l1-contracts/test/foundry/l2/integration/L2Utils.sol similarity index 85% rename from l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol rename to l1-contracts/test/foundry/l2/integration/L2Utils.sol index 2586fb836..9a0afb563 100644 --- a/l1-contracts/test/foundry/l2/unit/utils/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/integration/L2Utils.sol @@ -26,7 +26,7 @@ import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {SystemContractsCaller} from "contracts/common/libraries/SystemContractsCaller.sol"; import {DeployFailed} from "contracts/common/L1ContractErrors.sol"; -import {SystemContractsArgs} from "../../../l1/integration/_SharedL2ContractDummyDeployer.sol"; +import {SystemContractsArgs} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; library L2Utils { address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); @@ -216,48 +216,6 @@ library L2Utils { IContractDeployer(DEPLOYER_SYSTEM_CONTRACT).forceDeployOnAddresses(deployments); } - function deploySharedBridgeLegacy( - uint256 _l1ChainId, - uint256 _eraChainId, - address _aliasedOwner, - address _l1SharedBridge, - bytes32 _l2TokenProxyBytecodeHash - ) internal returns (address) { - bytes32 ethAssetId = DataEncoding.encodeNTVAssetId(_l1ChainId, ETH_TOKEN_ADDRESS); - - L2SharedBridgeLegacy bridge = new L2SharedBridgeLegacy(); - console.log("bridge", address(bridge)); - address proxyAdmin = address(0x1); - TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( - address(bridge), - proxyAdmin, - abi.encodeWithSelector( - L2SharedBridgeLegacy.initialize.selector, - _l1SharedBridge, - _l2TokenProxyBytecodeHash, - _aliasedOwner - ) - ); - console.log("proxy", address(proxy)); - return address(proxy); - } - - /// @notice Encodes the token data. - /// @param name The name of the token. - /// @param symbol The symbol of the token. - /// @param decimals The decimals of the token. - function encodeTokenData( - string memory name, - string memory symbol, - uint8 decimals - ) internal pure returns (bytes memory) { - bytes memory encodedName = abi.encode(name); - bytes memory encodedSymbol = abi.encode(symbol); - bytes memory encodedDecimals = abi.encode(decimals); - - return abi.encode(encodedName, encodedSymbol, encodedDecimals); - } - function deployViaCreat2L2( bytes memory creationCode, bytes memory constructorargs, diff --git a/l1-contracts/test/foundry/l2/integration/WETH.t.sol b/l1-contracts/test/foundry/l2/integration/WETH.t.sol new file mode 100644 index 000000000..5a0b8e246 --- /dev/null +++ b/l1-contracts/test/foundry/l2/integration/WETH.t.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; + +import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; + +import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; +import {L2WethTestAbstract} from "../../l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol"; + +import {SharedL2ContractL2DeployerUtils, SystemContractsArgs} from "./_SharedL2ContractL2DeployerUtils.sol"; + +contract WethTest is Test, L2WethTestAbstract, SharedL2ContractL2DeployerUtils { + function test() internal virtual override(DeployUtils, SharedL2ContractL2DeployerUtils) {} + + function initSystemContracts( + SystemContractsArgs memory _args + ) internal override(SharedL2ContractDeployer, SharedL2ContractL2DeployerUtils) { + super.initSystemContracts(_args); + } + + function deployViaCreate2( + bytes memory creationCode, + bytes memory constructorArgs + ) internal override(DeployUtils, SharedL2ContractL2DeployerUtils) returns (address) { + return super.deployViaCreate2(creationCode, constructorArgs); + } + + function deployL2Contracts( + uint256 _l1ChainId + ) public override(SharedL2ContractL1DeployerUtils, SharedL2ContractDeployer) { + super.deployL2Contracts(_l1ChainId); + } +} diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol similarity index 81% rename from l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol rename to l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol index 31d69a7d4..61f51d0cd 100644 --- a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol @@ -18,10 +18,10 @@ import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; import {L2_BRIDGEHUB_ADDR, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; -import {L2Utils} from "../unit/utils/L2Utils.sol"; -import {L2ContractDummyDeployer, SystemContractsArgs} from "../../l1/integration/_SharedL2ContractDummyDeployer.sol"; +import {L2Utils} from "./L2Utils.sol"; +import {SharedL2ContractL1DeployerUtils, SystemContractsArgs} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; -contract L2ContractDeployer is DeployUtils, L2ContractDummyDeployer { +contract SharedL2ContractL2DeployerUtils is DeployUtils, SharedL2ContractL1DeployerUtils { using stdToml for string; function initSystemContracts(SystemContractsArgs memory _args) internal virtual override { @@ -37,5 +37,5 @@ contract L2ContractDeployer is DeployUtils, L2ContractDummyDeployer { } // add this to be excluded from coverage report - function test() internal virtual override(DeployUtils, L2ContractDummyDeployer) {} + function test() internal virtual override(DeployUtils, SharedL2ContractL1DeployerUtils) {} } diff --git a/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol b/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol index c54367295..3374e1acc 100644 --- a/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol +++ b/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol @@ -8,7 +8,7 @@ import {Test} from "forge-std/Test.sol"; import {ValidiumL2DAValidator} from "contracts/data-availability/ValidiumL2DAValidator.sol"; -contract L2Erc20BridgeTest is Test { +contract L2ValidiumDAValidatorTest is Test { function test_callValidiumDAValidator(address depositor, address receiver, uint256 amount) internal { ValidiumL2DAValidator validator = new ValidiumL2DAValidator(); From 8af590e5d8916d01020ca2bc0edf72f987afdcb4 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 20:56:39 +0100 Subject: [PATCH 18/27] fmt --- .../contracts/dev-contracts/test/L2NativeTokenVaultDev.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol b/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol index 0c26d8d14..7d4c01577 100644 --- a/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol +++ b/l1-contracts/contracts/dev-contracts/test/L2NativeTokenVaultDev.sol @@ -34,7 +34,7 @@ contract L2NativeTokenVaultDev is L2NativeTokenVault { _baseTokenAssetId ) {} - + /// @notice copied from L1NTV for L1 compilation function calculateCreate2TokenAddress( uint256 _originChainId, From 4c40c898fc44bc2541499d71abcb9a3aa5f38ed8 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 21:44:51 +0100 Subject: [PATCH 19/27] chain withdrawal test --- .../contracts/bridgehub/Bridgehub.sol | 16 +++++++--- .../contracts/bridgehub/IBridgehub.sol | 2 +- l1-contracts/contracts/common/Config.sol | 5 ++++ l1-contracts/deploy-scripts/DeployL1.s.sol | 2 +- .../deploy-scripts/GatewayPreparation.s.sol | 2 +- .../L2GatewayTestAbstract.t.sol | 30 +++++++++++++++---- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/l1-contracts/contracts/bridgehub/Bridgehub.sol b/l1-contracts/contracts/bridgehub/Bridgehub.sol index cd22a9cc7..283de8998 100644 --- a/l1-contracts/contracts/bridgehub/Bridgehub.sol +++ b/l1-contracts/contracts/bridgehub/Bridgehub.sol @@ -4,6 +4,8 @@ pragma solidity 0.8.24; // solhint-disable reason-string, gas-custom-errors +import {console} from "forge-std/console.sol"; + import {EnumerableMap} from "@openzeppelin/contracts-v4/utils/structs/EnumerableMap.sol"; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol"; @@ -18,7 +20,7 @@ import {ReentrancyGuard} from "../common/ReentrancyGuard.sol"; import {DataEncoding} from "../common/libraries/DataEncoding.sol"; import {IZKChain} from "../state-transition/chain-interfaces/IZKChain.sol"; -import {ETH_TOKEN_ADDRESS, TWO_BRIDGES_MAGIC_VALUE, BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "../common/Config.sol"; +import {ETH_TOKEN_ADDRESS, TWO_BRIDGES_MAGIC_VALUE, BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER, L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS} from "../common/Config.sol"; import {BridgehubL2TransactionRequest, L2Message, L2Log, TxStatus} from "../common/Messaging.sol"; import {AddressAliasHelper} from "../vendor/AddressAliasHelper.sol"; import {IMessageRoot} from "./IMessageRoot.sol"; @@ -86,6 +88,9 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus /// @dev asset info used to identify chains in the Shared Bridge mapping(bytes32 ctmAssetId => address ctmAddress) public ctmAssetIdToAddress; + /// @dev ctmAddress to ctmAssetId + mapping(address ctmAddress => bytes32 ctmAssetId) public ctmAssetIdFromAddress; + /// @dev used to indicate the currently active settlement layer for a given chainId mapping(uint256 chainId => uint256 activeSettlementLayerChainId) public settlementLayer; @@ -320,6 +325,7 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus bytes32 assetInfo = keccak256(abi.encode(L1_CHAIN_ID, sender, _additionalData)); ctmAssetIdToAddress[assetInfo] = _assetAddress; + ctmAssetIdFromAddress[_assetAddress] = assetInfo; emit AssetRegistered(assetInfo, _assetAddress, _additionalData, msg.sender); } @@ -422,10 +428,10 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus if (ctmAddress == address(0)) { revert ChainIdNotRegistered(_chainId); } - return ctmAssetId(chainTypeManager[_chainId]); + return ctmAssetIdFromAddress[chainTypeManager[_chainId]]; } - function ctmAssetId(address _ctmAddress) public view override returns (bytes32) { + function calculateCtmAssetId(address _ctmAddress) internal view returns (bytes32) { return keccak256(abi.encode(L1_CHAIN_ID, address(l1CtmDeployer), bytes32(uint256(uint160(_ctmAddress))))); } @@ -700,7 +706,9 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus bridgehubData.ctmData ); bytes memory chainMintData = IZKChain(zkChain).forwardedBridgeBurn( - zkChainMap.get(_settlementChainId), + _settlementChainId == L1_CHAIN_ID + ? L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS + : zkChainMap.get(_settlementChainId), _originalCaller, bridgehubData.chainData ); diff --git a/l1-contracts/contracts/bridgehub/IBridgehub.sol b/l1-contracts/contracts/bridgehub/IBridgehub.sol index 5e2be03fc..1eb9723ae 100644 --- a/l1-contracts/contracts/bridgehub/IBridgehub.sol +++ b/l1-contracts/contracts/bridgehub/IBridgehub.sol @@ -217,7 +217,7 @@ interface IBridgehub is IAssetHandler, IL1AssetHandler { function ctmAssetIdFromChainId(uint256 _chainId) external view returns (bytes32); - function ctmAssetId(address _ctmAddress) external view returns (bytes32); + function ctmAssetIdFromAddress(address _ctmAddress) external view returns (bytes32); function l1CtmDeployer() external view returns (ICTMDeploymentTracker); diff --git a/l1-contracts/contracts/common/Config.sol b/l1-contracts/contracts/common/Config.sol index beebcd00c..a1e58f464 100644 --- a/l1-contracts/contracts/common/Config.sol +++ b/l1-contracts/contracts/common/Config.sol @@ -120,6 +120,11 @@ address constant SETTLEMENT_LAYER_RELAY_SENDER = address(uint160(0x1111111111111 /// @dev The metadata version that is supported by the ZK Chains to prove that an L2->L1 log was included in a batch. uint256 constant SUPPORTED_PROOF_METADATA_VERSION = 1; +/// @dev The virtual address of the L1 settlement layer. +address constant L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS = address( + uint160(uint256(keccak256("L1_SETTLEMENT_LAYER_VIRTUAL_ADDRESS")) - 1) +); + struct PriorityTreeCommitment { uint256 nextLeafIndex; uint256 startIndex; diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 3f49947ff..5d12ba4c4 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -237,7 +237,7 @@ contract DeployL1Script is Script, DeployUtils { vm.stopBroadcast(); console.log("CTM registered in CTMDeploymentTracker"); - bytes32 assetId = bridgehub.ctmAssetId(addresses.stateTransition.chainTypeManagerProxy); + bytes32 assetId = bridgehub.ctmAssetIdFromAddress(addresses.stateTransition.chainTypeManagerProxy); // console.log(address(bridgehub.ctmDeployer()), addresses.bridgehub.ctmDeploymentTrackerProxy); // console.log(address(bridgehub.ctmDeployer().BRIDGE_HUB()), addresses.bridgehub.bridgehubProxy); console.log( diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index a3568f10c..808db90a4 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -188,7 +188,7 @@ contract GatewayPreparation is Script { function governanceSetCTMAssetHandler(bytes32 governanoceOperationSalt) public { initializeConfig(); - bytes32 assetId = IBridgehub(config.bridgehub).ctmAssetId(config.chainTypeManagerProxy); + bytes32 assetId = IBridgehub(config.bridgehub).ctmAssetIdFromAddress(config.chainTypeManagerProxy); // This should be equivalent to `config.chainTypeManagerProxy`, but we just double checking to ensure that // bridgehub was initialized correctly diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol index e2bf33d84..e97c2017b 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol @@ -14,11 +14,11 @@ import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol" import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; -import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; +import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR, L2_MESSENGER} from "contracts/common/L2ContractAddresses.sol"; import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; -import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; +import {BridgehubMintCTMAssetData, BridgehubBurnCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; import {IL2AssetRouter} from "contracts/bridge/asset-router/IL2AssetRouter.sol"; import {IL1Nullifier} from "contracts/bridge/interfaces/IL1Nullifier.sol"; @@ -35,21 +35,41 @@ import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; abstract contract L2GatewayTestAbstract is Test, SharedL2ContractDeployer { function test_gatewayShouldFinalizeDeposit() public { finalizeDeposit(); + require(l2Bridgehub.ctmAssetIdFromAddress(address(chainTypeManager)) == ctmAssetId, "ctmAssetId mismatch"); + require(l2Bridgehub.ctmAssetIdFromChainId(mintChainId) == ctmAssetId, "ctmAssetIdFromChainId mismatch"); } function test_forwardToL3OnGateway() public { // todo fix this test finalizeDeposit(); - IBridgehub bridgehub = IBridgehub(L2_BRIDGEHUB_ADDR); vm.prank(SETTLEMENT_LAYER_RELAY_SENDER); - bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); + l2Bridgehub.forwardTransactionOnGateway(mintChainId, bytes32(0), 0); + } + + function test_withdrawFromGateway() public { + // todo fix this test + finalizeDeposit(); + address newAdmin = address(0x1); + bytes memory newDiamondCut = abi.encode(); + BridgehubBurnCTMAssetData memory data = BridgehubBurnCTMAssetData({ + chainId: mintChainId, + ctmData: abi.encode(newAdmin, config.contracts.diamondCutData), + chainData: abi.encode(chainTypeManager.protocolVersion()) + }); + vm.prank(ownerWallet); + vm.mockCall( + address(L2_MESSENGER), + abi.encodeWithSelector(L2_MESSENGER.sendToL1.selector), + abi.encode(bytes("")) + ); + l2AssetRouter.withdraw(ctmAssetId, abi.encode(data)); } function finalizeDeposit() public { bytes memory chainData = exampleChainCommitment; bytes memory ctmData = abi.encode( baseTokenAssetId, - msg.sender, + ownerWallet, chainTypeManager.protocolVersion(), config.contracts.diamondCutData ); From 8ce690545a7da2928c193b30340fea5d901db10a Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 22:13:47 +0100 Subject: [PATCH 20/27] some bridge fixes --- .../contracts/bridge/L2SharedBridgeLegacy.sol | 4 +- .../bridge/asset-router/IL2AssetRouter.sol | 2 +- .../bridge/asset-router/L2AssetRouter.sol | 10 ++-- .../interfaces/IL2SharedBridgeLegacy.sol | 2 +- .../contracts/bridgehub/Bridgehub.sol | 2 - .../deploy-scripts/GatewayPreparation.s.sol | 58 ++++++++++--------- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/l1-contracts/contracts/bridge/L2SharedBridgeLegacy.sol b/l1-contracts/contracts/bridge/L2SharedBridgeLegacy.sol index 9ea29cf07..db46fef12 100644 --- a/l1-contracts/contracts/bridge/L2SharedBridgeLegacy.sol +++ b/l1-contracts/contracts/bridge/L2SharedBridgeLegacy.sol @@ -148,8 +148,8 @@ contract L2SharedBridgeLegacy is IL2SharedBridgeLegacy, Initializable { proxy = abi.decode(returndata, (address)); } - function sendMessageToL1(bytes calldata _message) external override onlyAssetRouter { + function sendMessageToL1(bytes calldata _message) external override onlyAssetRouter returns (bytes32) { // slither-disable-next-line unused-return - L2ContractHelper.sendMessageToL1(_message); + return L2ContractHelper.sendMessageToL1(_message); } } diff --git a/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol index 7cb2bd1ce..e1b6c5959 100644 --- a/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol @@ -14,7 +14,7 @@ interface IL2AssetRouter is IAssetRouterBase { bytes assetData ); - function withdraw(bytes32 _assetId, bytes calldata _transferData) external; + function withdraw(bytes32 _assetId, bytes calldata _transferData) external returns (bytes32); function l1AssetRouter() external view returns (address); diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index 187039464..7a7b72651 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -151,11 +151,11 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { /// @dev do not rely on this function, it will be deprecated in the future /// @param _assetId The asset id of the withdrawn asset /// @param _assetData The data that is passed to the asset handler contract - function withdraw(bytes32 _assetId, bytes memory _assetData) public override { + function withdraw(bytes32 _assetId, bytes memory _assetData) public override returns (bytes32) { _withdrawSender(_assetId, _assetData, msg.sender, true); } - function withdrawToken(address _l2NativeToken, bytes memory _assetData) public { + function withdrawToken(address _l2NativeToken, bytes memory _assetData) public returns (bytes32) { bytes32 assetId = _ensureTokenRegisteredWithNTV(_l2NativeToken); _withdrawSender(assetId, _assetData, msg.sender, true); } @@ -171,7 +171,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { bytes memory _assetData, address _sender, bool _alwaysNewMessageFormat - ) internal { + ) internal returns (bytes32 txHash) { address assetHandler = assetHandlerAddress[_assetId]; bytes memory _l1bridgeMintData = IAssetHandler(assetHandler).bridgeBurn({ _chainId: L1_CHAIN_ID, @@ -185,7 +185,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { if (_alwaysNewMessageFormat || L2_LEGACY_SHARED_BRIDGE == address(0)) { message = _getAssetRouterWithdrawMessage(_assetId, _l1bridgeMintData); // slither-disable-next-line unused-return - L2ContractHelper.sendMessageToL1(message); + txHash = L2ContractHelper.sendMessageToL1(message); } else { address l1Token = IBridgedStandardToken( IL2NativeTokenVault(L2_NATIVE_TOKEN_VAULT_ADDR).tokenAddress(_assetId) @@ -195,7 +195,7 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { } (uint256 amount, address l1Receiver) = abi.decode(_assetData, (uint256, address)); message = _getSharedBridgeWithdrawMessage(l1Receiver, l1Token, amount); - IL2SharedBridgeLegacy(L2_LEGACY_SHARED_BRIDGE).sendMessageToL1(message); + txHash = IL2SharedBridgeLegacy(L2_LEGACY_SHARED_BRIDGE).sendMessageToL1(message); } emit WithdrawalInitiatedAssetRouter(L1_CHAIN_ID, _sender, _assetId, _assetData); diff --git a/l1-contracts/contracts/bridge/interfaces/IL2SharedBridgeLegacy.sol b/l1-contracts/contracts/bridge/interfaces/IL2SharedBridgeLegacy.sol index 00a762447..a3f903139 100644 --- a/l1-contracts/contracts/bridge/interfaces/IL2SharedBridgeLegacy.sol +++ b/l1-contracts/contracts/bridge/interfaces/IL2SharedBridgeLegacy.sol @@ -17,5 +17,5 @@ interface IL2SharedBridgeLegacy { function deployBeaconProxy(bytes32 _salt) external returns (address); - function sendMessageToL1(bytes calldata _message) external; + function sendMessageToL1(bytes calldata _message) external returns (bytes32); } diff --git a/l1-contracts/contracts/bridgehub/Bridgehub.sol b/l1-contracts/contracts/bridgehub/Bridgehub.sol index 283de8998..c753533ba 100644 --- a/l1-contracts/contracts/bridgehub/Bridgehub.sol +++ b/l1-contracts/contracts/bridgehub/Bridgehub.sol @@ -4,8 +4,6 @@ pragma solidity 0.8.24; // solhint-disable reason-string, gas-custom-errors -import {console} from "forge-std/console.sol"; - import {EnumerableMap} from "@openzeppelin/contracts-v4/utils/structs/EnumerableMap.sol"; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol"; diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index 808db90a4..d3e1827fd 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -45,6 +45,8 @@ struct Config { address gatewayChainProxyAdmin; address l1NullifierProxy; bytes gatewayDiamondCutData; + bytes l1DiamondCutData; + uint256 l1ChainId; } /// @notice Scripts that is responsible for preparing the chain to become a gateway @@ -97,10 +99,12 @@ contract GatewayPreparation is Script { gatewayChainId: toml.readUint("$.chain_chain_id"), governance: toml.readAddress("$.governance"), gatewayDiamondCutData: toml.readBytes("$.gateway_diamond_cut_data"), + l1DiamondCutData: toml.readBytes("$.l1_diamond_cut_data"), gatewayChainAdmin: toml.readAddress("$.chain_admin"), gatewayAccessControlRestriction: toml.readAddress("$.access_control_restriction"), gatewayChainProxyAdmin: toml.readAddress("$.chain_proxy_admin"), - l1NullifierProxy: toml.readAddress("$.l1_nullifier_proxy") + l1NullifierProxy: toml.readAddress("$.l1_nullifier_proxy"), + l1ChainId: toml.readUint("$.l1_chain_id") }); } @@ -294,33 +298,31 @@ contract GatewayPreparation is Script { bytes32 chainAssetId = IBridgehub(config.bridgehub).ctmAssetIdFromChainId(chainId); uint256 currentSettlementLayer = IBridgehub(config.bridgehub).settlementLayer(chainId); - // if (currentSettlementLayer == config.l1ChainId) { - // console.log("Chain already using L1 as its settlement layer"); - // saveOutput(bytes32(0)); - // return; - // } - - // if (currentSettlementLayer == address(0)) { - // console.log("Chain has never used Gateway as its settlement layer"); - // saveOutput(bytes32(0)); - // return; - // } - - // bytes memory bridgehubData = abi.encode( - // BridgehubBurnCTMAssetData({ - // chainId: chainId, - // ctmData: abi.encode(chainAdmin, config.diamondCutData), - // chainData: abi.encode(IZKChain(IBridgehub(config.bridgehub).getZKChain(chainId)).getProtocolVersion()) - // }) - // ); - - // L2AssetRouter l2AssetRouter = L2AssetRouter(L2_ASSET_ROUTER_ADDR); - // l2AssetRouter.withdraw( - // ctmAssetId, - // bridgehubBurnData - // ); - - // saveOutput(l2TxHash); + if (currentSettlementLayer == config.l1ChainId) { + console.log("Chain already using L1 as its settlement layer"); + saveOutput(bytes32(0)); + return; + } + + if (currentSettlementLayer == 0) { + console.log("Chain has never used Gateway as its settlement layer"); + saveOutput(bytes32(0)); + return; + } + + bytes memory bridgehubBurnData = abi.encode( + BridgehubBurnCTMAssetData({ + chainId: chainId, + ctmData: abi.encode(chainAdmin, config.l1DiamondCutData), + chainData: abi.encode(IChainTypeManager(config.chainTypeManagerProxy).getProtocolVersion(chainId)) + }) + ); + + L2AssetRouter l2AssetRouter = L2AssetRouter(L2_ASSET_ROUTER_ADDR); + bytes32 ctmAssetId = IBridgehub(config.bridgehub).ctmAssetIdFromAddress(config.chainTypeManagerProxy); + bytes32 l2TxHash = l2AssetRouter.withdraw(ctmAssetId, bridgehubBurnData); + + saveOutput(l2TxHash); } function finishMigrateChainFromGateway( From 183589c65ba66a7bd67d68c63d18cf82bbf85da0 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Sun, 29 Sep 2024 22:23:40 +0100 Subject: [PATCH 21/27] script --- .../deploy-scripts/GatewayPreparation.s.sol | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index d3e1827fd..72f130ef1 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -295,17 +295,11 @@ contract GatewayPreparation is Script { ) public { initializeConfig(); - bytes32 chainAssetId = IBridgehub(config.bridgehub).ctmAssetIdFromChainId(chainId); - - uint256 currentSettlementLayer = IBridgehub(config.bridgehub).settlementLayer(chainId); - if (currentSettlementLayer == config.l1ChainId) { - console.log("Chain already using L1 as its settlement layer"); - saveOutput(bytes32(0)); - return; - } + IBridgehub l2Bridgehub = IBridgehub(config.bridgehub); - if (currentSettlementLayer == 0) { - console.log("Chain has never used Gateway as its settlement layer"); + uint256 currentSettlementLayer = l2Bridgehub.settlementLayer(chainId); + if (currentSettlementLayer == config.l1ChainId || currentSettlementLayer == 0) { + console.log("Chain not using Gateway as settlement layer"); saveOutput(bytes32(0)); return; } @@ -318,8 +312,8 @@ contract GatewayPreparation is Script { }) ); + bytes32 ctmAssetId = l2Bridgehub.ctmAssetIdFromChainId(chainId); L2AssetRouter l2AssetRouter = L2AssetRouter(L2_ASSET_ROUTER_ADDR); - bytes32 ctmAssetId = IBridgehub(config.bridgehub).ctmAssetIdFromAddress(config.chainTypeManagerProxy); bytes32 l2TxHash = l2AssetRouter.withdraw(ctmAssetId, bridgehubBurnData); saveOutput(l2TxHash); From aa87952a6679472fd9ce7f0c41953d80b50502b7 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Mon, 30 Sep 2024 14:07:57 +0100 Subject: [PATCH 22/27] l1 test fixes --- l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol | 2 -- .../integration/l2-dummy-tests/_SharedL2ContractDeployer.sol | 1 - .../l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol | 3 +++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol index d9abe13da..77aad90a5 100644 --- a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol @@ -120,7 +120,6 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, address chain = _deployZkChain( chainId, baseTokenAssetId, - address(bridgeHub.sharedBridge()), owner, chainTypeManager.protocolVersion(), chainTypeManager.storedBatchZero(), @@ -152,7 +151,6 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, address chain = _deployZkChain( chainId, baseTokenAssetId, - address(bridgeHub.sharedBridge()), owner, chainTypeManager.protocolVersion(), chainTypeManager.storedBatchZero(), diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol index aa7e5676a..8892bd21f 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol @@ -141,7 +141,6 @@ abstract contract SharedL2ContractDeployer is Test, DeployUtils { address chainAddress = chainTypeManager.createNewChain( ERA_CHAIN_ID + 1, baseTokenAssetId, - L2_ASSET_ROUTER_ADDR, address(0x1), abi.encode(config.contracts.diamondCutData, generatedData.forceDeploymentsData), new bytes[](0) diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol index b48b7f0bc..8c0e7e099 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol @@ -76,7 +76,10 @@ contract SharedL2ContractL1DeployerUtils is DeployUtils { MessageRoot(L2_MESSAGE_ROOT_ADDR).initialize(); vm.etch(L2_BRIDGEHUB_ADDR, bridgehub.code); + uint256 prevChainId = block.chainid; + vm.chainId(_args.l1ChainId); Bridgehub(L2_BRIDGEHUB_ADDR).initialize(_args.aliasedOwner); + vm.chainId(prevChainId); vm.prank(_args.aliasedOwner); Bridgehub(L2_BRIDGEHUB_ADDR).setAddresses( L2_ASSET_ROUTER_ADDR, From f6e3538a21f67c61ab1aad3cac09e949636653ad Mon Sep 17 00:00:00 2001 From: kelemeno Date: Tue, 1 Oct 2024 18:28:35 +0100 Subject: [PATCH 23/27] gateway -> l1 migration fix --- .../bridge/asset-router/L2AssetRouter.sol | 4 +- .../deploy-scripts/GatewayPreparation.s.sol | 89 +++++++++---------- .../l1/integration/L1GatewayTests.t.sol | 33 ++++++- 3 files changed, 75 insertions(+), 51 deletions(-) diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index d9b414c55..0562a05b4 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -207,9 +207,9 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { function _getAssetRouterWithdrawMessage( bytes32 _assetId, bytes memory _l1bridgeMintData - ) internal pure returns (bytes memory) { + ) internal view returns (bytes memory) { // solhint-disable-next-line func-named-parameters - return abi.encodePacked(IAssetRouterBase.finalizeDeposit.selector, _assetId, _l1bridgeMintData); + return abi.encodePacked(IAssetRouterBase.finalizeDeposit.selector, block.chainid, _assetId, _l1bridgeMintData); } /// @notice Encodes the message for l2ToL1log sent during withdraw initialization. diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index 72f130ef1..cf6220d5b 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -22,7 +22,7 @@ import {GatewayTransactionFilterer} from "contracts/transactionFilterer/GatewayT import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {SET_ASSET_HANDLER_COUNTERPART_ENCODING_VERSION} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; import {CTM_DEPLOYMENT_TRACKER_ENCODING_VERSION} from "contracts/bridgehub/CTMDeploymentTracker.sol"; -import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; +import {L2AssetRouter, IL2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {L1Nullifier} from "contracts/bridge/L1Nullifier.sol"; import {BridgehubMintCTMAssetData} from "contracts/bridgehub/IBridgehub.sol"; import {IAssetRouterBase} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; @@ -46,7 +46,6 @@ struct Config { address l1NullifierProxy; bytes gatewayDiamondCutData; bytes l1DiamondCutData; - uint256 l1ChainId; } /// @notice Scripts that is responsible for preparing the chain to become a gateway @@ -103,8 +102,7 @@ contract GatewayPreparation is Script { gatewayChainAdmin: toml.readAddress("$.chain_admin"), gatewayAccessControlRestriction: toml.readAddress("$.access_control_restriction"), gatewayChainProxyAdmin: toml.readAddress("$.chain_proxy_admin"), - l1NullifierProxy: toml.readAddress("$.l1_nullifier_proxy"), - l1ChainId: toml.readUint("$.l1_chain_id") + l1NullifierProxy: toml.readAddress("$.l1_nullifier_proxy_addr") }); } @@ -294,11 +292,10 @@ contract GatewayPreparation is Script { uint256 chainId ) public { initializeConfig(); + IBridgehub bridgehub = IBridgehub(config.bridgehub); - IBridgehub l2Bridgehub = IBridgehub(config.bridgehub); - - uint256 currentSettlementLayer = l2Bridgehub.settlementLayer(chainId); - if (currentSettlementLayer == config.l1ChainId || currentSettlementLayer == 0) { + uint256 currentSettlementLayer = bridgehub.settlementLayer(chainId); + if (currentSettlementLayer != config.gatewayChainId) { console.log("Chain not using Gateway as settlement layer"); saveOutput(bytes32(0)); return; @@ -312,60 +309,56 @@ contract GatewayPreparation is Script { }) ); - bytes32 ctmAssetId = l2Bridgehub.ctmAssetIdFromChainId(chainId); + bytes32 ctmAssetId = bridgehub.ctmAssetIdFromChainId(chainId); L2AssetRouter l2AssetRouter = L2AssetRouter(L2_ASSET_ROUTER_ADDR); - bytes32 l2TxHash = l2AssetRouter.withdraw(ctmAssetId, bridgehubBurnData); + bytes memory l2Calldata = abi.encodeCall(IL2AssetRouter.withdraw, (ctmAssetId, bridgehubBurnData)); + // vm.startBroadcast(); + bytes32 l2TxHash = Utils.runAdminL1L2DirectTransaction( + _getL1GasPrice(), + chainAdmin, + accessControlRestriction, + l2Calldata, + Utils.MAX_PRIORITY_TX_GAS, + new bytes[](0), + L2_ASSET_ROUTER_ADDR, + config.gatewayChainId, + config.bridgehub, + config.sharedBridgeProxy + ); saveOutput(l2TxHash); } function finishMigrateChainFromGateway( - IZKChain migratingChain, uint256 migratingChainId, - uint256 gatewayChainId + uint256 gatewayChainId, + uint256 l2BatchNumber, + uint256 l2MessageIndex, + uint16 l2TxNumberInBatch, + bytes memory message, + bytes32[] memory merkleProof ) public { initializeConfig(); // TODO(EVM-746): Use L2-based chain admin contract // address l2ChainAdmin = AddressAliasHelper.applyL1ToL2Alias(chainAdmin); - IBridgehub bridgehub = IBridgehub(config.bridgehub); - bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); - bytes32 baseTokenAssetId = bridgehub.baseTokenAssetId(migratingChainId); - IChainTypeManager ctm = IChainTypeManager(config.chainTypeManagerProxy); - - bytes memory chainData = abi.encode(IAdmin(address(migratingChain)).prepareChainCommitment()); - bytes memory ctmData = abi.encode( - baseTokenAssetId, - msg.sender, - ctm.protocolVersion(), - config.gatewayDiamondCutData - ); - BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ - chainId: migratingChainId, - baseTokenAssetId: baseTokenAssetId, - ctmData: ctmData, - chainData: chainData - }); - bytes memory bridgehubMintData = abi.encode(data); L1Nullifier l1Nullifier = L1Nullifier(config.l1NullifierProxy); - - l1Nullifier.finalizeDeposit( - FinalizeL1DepositParams({ - chainId: migratingChainId, - l2BatchNumber: 1, - l2MessageIndex: 1, - l2Sender: L2_ASSET_ROUTER_ADDR, - l2TxNumberInBatch: 1, - message: abi.encodePacked( - IAssetRouterBase.finalizeDeposit.selector, - gatewayChainId, - assetId, - bridgehubMintData - ), - merkleProof: new bytes32[](0) - }) - ); + { + IBridgehub bridgehub = IBridgehub(config.bridgehub); + bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); + l1Nullifier.finalizeDeposit( + FinalizeL1DepositParams({ + chainId: gatewayChainId, + l2BatchNumber: l2BatchNumber, + l2MessageIndex: l2MessageIndex, + l2Sender: L2_ASSET_ROUTER_ADDR, + l2TxNumberInBatch: l2TxNumberInBatch, + message: message, + merkleProof: merkleProof + }) + ); + } } /// @dev Calling this function requires private key to the admin of the chain diff --git a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index 0d558b8db..5fd43c169 100644 --- a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -38,6 +38,7 @@ import {TxStatus} from "contracts/common/Messaging.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; import {IncorrectBridgeHubAddress} from "contracts/common/L1ContractErrors.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker, GatewayDeployer { uint256 constant TEST_USERS_COUNT = 10; @@ -281,7 +282,37 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L abi.encode(chainTypeManager.protocolVersion()) ); - gatewayScript.finishMigrateChainFromGateway(migratingChain, migratingChainId, gatewayChainId); + uint256 protocolVersion = chainTypeManager.getProtocolVersion(migratingChainId); + + bytes memory chainData = abi.encode(IAdmin(address(migratingChain)).prepareChainCommitment()); + bytes memory ctmData = abi.encode( + baseTokenAssetId, + msg.sender, + protocolVersion, + ecosystemConfig.contracts.diamondCutData + ); + BridgehubMintCTMAssetData memory data = BridgehubMintCTMAssetData({ + chainId: migratingChainId, + baseTokenAssetId: baseTokenAssetId, + ctmData: ctmData, + chainData: chainData + }); + bytes memory bridgehubMintData = abi.encode(data); + bytes memory message = abi.encodePacked( + IAssetRouterBase.finalizeDeposit.selector, + gatewayChainId, + assetId, + bridgehubMintData + ); + gatewayScript.finishMigrateChainFromGateway( + migratingChainId, + gatewayChainId, + 0, + 0, + 0, + message, + new bytes32[](0) + ); vm.chainId(currentChainId); From ffcc50fd05fb95a422270ca7bc92bcc4ce0cbcdc Mon Sep 17 00:00:00 2001 From: kelemeno Date: Tue, 1 Oct 2024 20:10:58 +0100 Subject: [PATCH 24/27] stas issue fixes --- .../contracts/bridge/BridgedStandardERC20.sol | 5 ++ l1-contracts/contracts/bridge/L1Nullifier.sol | 2 +- .../contracts/bridge/L2WrappedBaseToken.sol | 9 +++- .../bridge/asset-router/L1AssetRouter.sol | 2 +- .../bridge/asset-router/L2AssetRouter.sol | 4 +- .../bridge/ntv/INativeTokenVault.sol | 4 ++ .../l1/integration/AssetRouterTest.t.sol | 14 ++++-- .../integration/BridgeHubInvariantTests.t.sol | 16 +++--- .../l1/integration/BridgehubTests.t.sol | 16 +++--- .../l1/integration/DeploymentTest.t.sol | 50 +++++++++---------- .../l1/integration/L1GatewayTests.t.sol | 22 ++++---- .../_SharedL1ContractDeployer.t.sol | 20 ++++---- .../integration/_SharedZKChainDeployer.t.sol | 10 ++-- .../_SharedL2ContractDeployer.sol | 2 +- .../_SharedL2ContractL1DeployerUtils.sol | 3 +- .../l2/integration/L2GatewayTests.t.sol | 2 - 16 files changed, 101 insertions(+), 80 deletions(-) diff --git a/l1-contracts/contracts/bridge/BridgedStandardERC20.sol b/l1-contracts/contracts/bridge/BridgedStandardERC20.sol index b6dddb4d9..d848dcbac 100644 --- a/l1-contracts/contracts/bridge/BridgedStandardERC20.sol +++ b/l1-contracts/contracts/bridge/BridgedStandardERC20.sol @@ -10,6 +10,7 @@ import {IBridgedStandardToken} from "./interfaces/IBridgedStandardToken.sol"; import {Unauthorized, NonSequentialVersion, ZeroAddress} from "../common/L1ContractErrors.sol"; import {L2_NATIVE_TOKEN_VAULT_ADDR} from "../common/L2ContractAddresses.sol"; import {DataEncoding} from "../common/libraries/DataEncoding.sol"; +import {INativeTokenVault} from "../bridge/ntv/INativeTokenVault.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -53,6 +54,10 @@ contract BridgedStandardERC20 is ERC20PermitUpgradeable, IBridgedStandardToken, if (ntv == address(0)) { ntv = L2_NATIVE_TOKEN_VAULT_ADDR; nativeTokenVault = L2_NATIVE_TOKEN_VAULT_ADDR; + assetId = DataEncoding.encodeNTVAssetId( + INativeTokenVault(L2_NATIVE_TOKEN_VAULT_ADDR).L1_CHAIN_ID(), + originToken + ); } if (msg.sender != ntv) { revert Unauthorized(msg.sender); diff --git a/l1-contracts/contracts/bridge/L1Nullifier.sol b/l1-contracts/contracts/bridge/L1Nullifier.sol index 2684bde55..5601bf344 100644 --- a/l1-contracts/contracts/bridge/L1Nullifier.sol +++ b/l1-contracts/contracts/bridge/L1Nullifier.sol @@ -702,7 +702,7 @@ contract L1Nullifier is IL1Nullifier, ReentrancyGuard, Ownable2StepUpgradeable, ) external override onlyLegacyBridge { bytes memory assetData = abi.encode(_amount, _depositSender); /// the legacy bridge can only be used with L1 native tokens. - bytes32 assetId = INativeTokenVault(address(l1NativeTokenVault)).calculateAssetId(block.chainid, _l1Asset); + bytes32 assetId = DataEncoding.encodeNTVAssetId(block.chainid, _l1Asset); _verifyAndClearFailedTransfer({ _checkedInLegacyBridge: true, diff --git a/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol b/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol index cc825cbee..7af7b6cd3 100644 --- a/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol +++ b/l1-contracts/contracts/bridge/L2WrappedBaseToken.sol @@ -33,7 +33,7 @@ contract L2WrappedBaseToken is ERC20PermitUpgradeable, IL2WrappedBaseToken, IBri /// @dev Address of the native token vault. address public override nativeTokenVault; - /// @dev The assetId of the token. + /// @dev The assetId of the token. The wrapped token does not have its own assetId. bytes32 public override assetId; modifier onlyBridge() { @@ -66,7 +66,8 @@ contract L2WrappedBaseToken is ERC20PermitUpgradeable, IL2WrappedBaseToken, IBri string calldata name_, string calldata symbol_, address _l2Bridge, - address _l1Address + address _l1Address, + bytes32 _baseTokenAssetId ) external reinitializer(2) { if (_l2Bridge == address(0)) { revert ZeroAddress(); @@ -75,9 +76,13 @@ contract L2WrappedBaseToken is ERC20PermitUpgradeable, IL2WrappedBaseToken, IBri if (_l1Address == address(0)) { revert ZeroAddress(); } + if (_baseTokenAssetId == bytes32(0)) { + revert ZeroAddress(); + } l2Bridge = _l2Bridge; l1Address = _l1Address; nativeTokenVault = L2_NATIVE_TOKEN_VAULT_ADDR; + assetId = _baseTokenAssetId; // Set decoded values for name and symbol. __ERC20_init_unchained(name_, symbol_); diff --git a/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol index c61297a9a..1c5d18c8a 100644 --- a/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol @@ -357,7 +357,7 @@ contract L1AssetRouter is AssetRouterBase, IL1AssetRouter, ReentrancyGuard { /// @param _token The native token address which should be registered with native token vault. /// @return assetId The asset ID of the token provided. function _ensureTokenRegisteredWithNTV(address _token) internal override returns (bytes32 assetId) { - assetId = nativeTokenVault.calculateAssetId(block.chainid, _token); + assetId = DataEncoding.encodeNTVAssetId(block.chainid, _token); if (nativeTokenVault.tokenAddress(assetId) == address(0)) { nativeTokenVault.registerToken(_token); } diff --git a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol index 0562a05b4..b2919d5f8 100644 --- a/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol +++ b/l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol @@ -152,12 +152,12 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter { /// @param _assetId The asset id of the withdrawn asset /// @param _assetData The data that is passed to the asset handler contract function withdraw(bytes32 _assetId, bytes memory _assetData) public override returns (bytes32) { - _withdrawSender(_assetId, _assetData, msg.sender, true); + return _withdrawSender(_assetId, _assetData, msg.sender, true); } function withdrawToken(address _l2NativeToken, bytes memory _assetData) public returns (bytes32) { bytes32 assetId = _ensureTokenRegisteredWithNTV(_l2NativeToken); - _withdrawSender(assetId, _assetData, msg.sender, true); + return _withdrawSender(assetId, _assetData, msg.sender, true); } /// @notice Initiates a withdrawal by burning funds on the contract and sending the message to L1 diff --git a/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol b/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol index f6887f6e6..05b641c43 100644 --- a/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol +++ b/l1-contracts/contracts/bridge/ntv/INativeTokenVault.sol @@ -16,6 +16,10 @@ interface INativeTokenVault { /// @notice The AssetRouter contract function ASSET_ROUTER() external view returns (IAssetRouterBase); + + /// @notice The chain ID of the L1 chain + function L1_CHAIN_ID() external view returns (uint256); + /// @notice Returns the chain ID of the origin chain for a given asset ID function originChainId(bytes32 assetId) external view returns (uint256); diff --git a/l1-contracts/test/foundry/l1/integration/AssetRouterTest.t.sol b/l1-contracts/test/foundry/l1/integration/AssetRouterTest.t.sol index 83913d2a4..7d122638d 100644 --- a/l1-contracts/test/foundry/l1/integration/AssetRouterTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/AssetRouterTest.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; +import {console2 as console} from "forge-std/console2.sol"; import {L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "contracts/bridgehub/IBridgehub.sol"; import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol"; @@ -24,6 +25,7 @@ import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IL1NativeTokenVault} from "contracts/bridge/ntv/IL1NativeTokenVault.sol"; +import {INativeTokenVault} from "contracts/bridge/ntv/INativeTokenVault.sol"; import {IL1Nullifier, FinalizeL1DepositParams} from "contracts/bridge/interfaces/IL1Nullifier.sol"; import {IL1AssetRouter} from "contracts/bridge/asset-router/IL1AssetRouter.sol"; import {IAssetRouterBase, LEGACY_ENCODING_VERSION, NEW_ENCODING_VERSION} from "contracts/bridge/asset-router/IAssetRouterBase.sol"; @@ -79,12 +81,12 @@ contract AssetRouterTest is L1ContractDeployer, ZKChainDeployer, TokenDeployer, function depositToL1(address _tokenAddress) public { vm.mockCall( - address(bridgeHub), + address(bridgehub), abi.encodeWithSelector(IBridgehub.proveL2MessageInclusion.selector), abi.encode(true) ); uint256 chainId = eraZKChainId; - l2TokenAssetId = DataEncoding.encodeNTVAssetId(chainId, address(1)); + l2TokenAssetId = DataEncoding.encodeNTVAssetId(chainId, _tokenAddress); bytes memory transferData = DataEncoding.encodeBridgeMintData({ _originalCaller: ETH_TOKEN_ADDRESS, _l2Receiver: address(this), @@ -152,7 +154,13 @@ contract AssetRouterTest is L1ContractDeployer, ZKChainDeployer, TokenDeployer, function test_BridgeTokenBurn() public { depositToL1(ETH_TOKEN_ADDRESS); BridgedStandardERC20 bridgedToken = BridgedStandardERC20(l1NativeTokenVault.tokenAddress(l2TokenAssetId)); + // setting nativeTokenVault to zero address. vm.store(address(bridgedToken), bytes32(uint256(207)), bytes32(0)); + vm.mockCall( + address(L2_NATIVE_TOKEN_VAULT_ADDR), + abi.encodeWithSelector(INativeTokenVault.L1_CHAIN_ID.selector), + abi.encode(block.chainid) + ); vm.broadcast(L2_NATIVE_TOKEN_VAULT_ADDR); // kl todo call ntv, or even assetRouter/bridgehub bridgedToken.bridgeBurn(address(this), 100); } @@ -164,7 +172,7 @@ contract AssetRouterTest is L1ContractDeployer, ZKChainDeployer, TokenDeployer, abi.encode(l2TokenAssetId, abi.encode(uint256(100), address(this))) ); IERC20(tokenL1Address).approve(address(l1NativeTokenVault), 100); - bridgeHub.requestL2TransactionTwoBridges{value: 250000000000100}( + bridgehub.requestL2TransactionTwoBridges{value: 250000000000100}( L2TransactionRequestTwoBridgesOuter({ chainId: eraZKChainId, mintValue: 250000000000100, diff --git a/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol b/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol index 5d23e1ad6..b4fec78de 100644 --- a/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/BridgeHubInvariantTests.t.sol @@ -270,7 +270,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges{value: mintValue}(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges{value: mintValue}(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -320,7 +320,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges{value: l2Value}(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges{value: l2Value}(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -375,7 +375,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -420,7 +420,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionDirect{value: mintValue}(txRequest); + bytes32 resultantHash = bridgehub.requestL2TransactionDirect{value: mintValue}(txRequest); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -464,7 +464,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionDirect(txRequest); + bytes32 resultantHash = bridgehub.requestL2TransactionDirect(txRequest); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -509,7 +509,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgeHubProxyAddress, + bridgehubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -565,7 +565,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgeHubProxyAddress, + bridgehubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -643,7 +643,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe } function getAddressesToExclude() public returns (address[] memory) { - addressesToExclude.push(bridgeHubProxyAddress); + addressesToExclude.push(bridgehubProxyAddress); addressesToExclude.push(address(sharedBridge)); for (uint256 i = 0; i < users.length; i++) { diff --git a/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol b/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol index a9e54825a..a99790839 100644 --- a/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/BridgehubTests.t.sol @@ -270,7 +270,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges{value: mintValue}(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges{value: mintValue}(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -320,7 +320,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges{value: l2Value}(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges{value: l2Value}(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -375,7 +375,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionTwoBridges(requestTx); + bytes32 resultantHash = bridgehub.requestL2TransactionTwoBridges(requestTx); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -420,7 +420,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionDirect{value: mintValue}(txRequest); + bytes32 resultantHash = bridgehub.requestL2TransactionDirect{value: mintValue}(txRequest); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -464,7 +464,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.recordLogs(); - bytes32 resultantHash = bridgeHub.requestL2TransactionDirect(txRequest); + bytes32 resultantHash = bridgehub.requestL2TransactionDirect(txRequest); Vm.Log[] memory logs = vm.getRecordedLogs(); NewPriorityRequest memory request = _getNewPriorityQueueFromLogs(logs); @@ -509,7 +509,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgeHubProxyAddress, + bridgehubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -565,7 +565,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe }); vm.mockCall( - bridgeHubProxyAddress, + bridgehubProxyAddress, // solhint-disable-next-line func-named-parameters abi.encodeWithSelector( IBridgehub.proveL2MessageInclusion.selector, @@ -643,7 +643,7 @@ contract BridgeHubInvariantTests is L1ContractDeployer, ZKChainDeployer, TokenDe } function getAddressesToExclude() public returns (address[] memory) { - addressesToExclude.push(bridgeHubProxyAddress); + addressesToExclude.push(bridgehubProxyAddress); addressesToExclude.push(address(sharedBridge)); for (uint256 i = 0; i < users.length; i++) { diff --git a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol index 77aad90a5..b4cca3bb1 100644 --- a/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/DeploymentTest.t.sol @@ -73,17 +73,17 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, // equals the balance of L1Shared bridge. function test_initialDeployment() public { uint256 chainId = zkChainIds[0]; - address newChainAddress = bridgeHub.getZKChain(chainId); - address admin = IZKChain(bridgeHub.getZKChain(chainId)).getAdmin(); + address newChainAddress = bridgehub.getZKChain(chainId); + address admin = IZKChain(bridgehub.getZKChain(chainId)).getAdmin(); assertNotEq(admin, address(0)); assertNotEq(newChainAddress, address(0)); - address[] memory chainAddresses = bridgeHub.getAllZKChains(); + address[] memory chainAddresses = bridgehub.getAllZKChains(); assertEq(chainAddresses.length, 1); assertEq(chainAddresses[0], newChainAddress); - uint256[] memory chainIds = bridgeHub.getAllZKChainChainIDs(); + uint256[] memory chainIds = bridgehub.getAllZKChainChainIDs(); assertEq(chainIds.length, 1); assertEq(chainIds[0], chainId); @@ -91,7 +91,7 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, assertEq(protocolVersion, 25); } - function test_bridgeHubSetter() public { + function test_bridgehubSetter() public { uint256 chainId = zkChainIds[0]; uint256 randomChainId = 123456; @@ -100,18 +100,18 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, abi.encodeWithSelector(IChainTypeManager.getZKChainLegacy.selector, randomChainId), abi.encode(address(0x01)) ); - vm.store(address(bridgeHub), keccak256(abi.encode(randomChainId, 205)), bytes32(uint256(uint160(1)))); + vm.store(address(bridgehub), keccak256(abi.encode(randomChainId, 205)), bytes32(uint256(uint160(1)))); vm.store( - address(bridgeHub), + address(bridgehub), keccak256(abi.encode(randomChainId, 204)), bytes32(uint256(uint160(address(chainTypeManager)))) ); - bridgeHub.setLegacyBaseTokenAssetId(randomChainId); - bridgeHub.setLegacyChainAddress(randomChainId); + bridgehub.setLegacyBaseTokenAssetId(randomChainId); + bridgehub.setLegacyChainAddress(randomChainId); } function test_registerAlreadyDeployedZKChain() public { - address owner = Ownable(address(bridgeHub)).owner(); + address owner = Ownable(address(bridgehub)).owner(); { uint256 chainId = currentZKChainId++; @@ -123,26 +123,26 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, owner, chainTypeManager.protocolVersion(), chainTypeManager.storedBatchZero(), - address(bridgeHub) + address(bridgehub) ); address stmAddr = IZKChain(chain).getChainTypeManager(); vm.startBroadcast(owner); - bridgeHub.addChainTypeManager(stmAddr); - bridgeHub.addTokenAssetId(baseTokenAssetId); - bridgeHub.registerAlreadyDeployedZKChain(chainId, chain); + 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 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)); + assertEq(bridgehubStmForChain, stmAddr); + assertEq(bridgehubBaseAssetIdForChain, baseTokenAssetId); + assertEq(bridgehubChainAddressdForChain, chain); + assertEq(bhAddr, address(bridgehub)); } { @@ -154,17 +154,17 @@ contract DeploymentTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, owner, chainTypeManager.protocolVersion(), chainTypeManager.storedBatchZero(), - address(bridgeHub.sharedBridge()) + address(bridgehub.sharedBridge()) ); address stmAddr = IZKChain(chain).getChainTypeManager(); vm.startBroadcast(owner); - bridgeHub.addTokenAssetId(baseTokenAssetId); + bridgehub.addTokenAssetId(baseTokenAssetId); vm.expectRevert( - abi.encodeWithSelector(IncorrectBridgeHubAddress.selector, address(bridgeHub.sharedBridge())) + abi.encodeWithSelector(IncorrectBridgeHubAddress.selector, address(bridgehub.sharedBridge())) ); - bridgeHub.registerAlreadyDeployedZKChain(chainId, chain); + bridgehub.registerAlreadyDeployedZKChain(chainId, chain); vm.stopBroadcast(); } } diff --git a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol index 5fd43c169..9f67d7973 100644 --- a/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l1/integration/L1GatewayTests.t.sol @@ -91,13 +91,13 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L _initializeGatewayScript(); vm.deal(ecosystemConfig.ownerAddress, 100000000000000000000000000000000000); - migratingChain = IZKChain(IBridgehub(bridgeHub).getZKChain(migratingChainId)); - gatewayChain = IZKChain(IBridgehub(bridgeHub).getZKChain(gatewayChainId)); + migratingChain = IZKChain(IBridgehub(bridgehub).getZKChain(migratingChainId)); + gatewayChain = IZKChain(IBridgehub(bridgehub).getZKChain(gatewayChainId)); vm.deal(migratingChain.getAdmin(), 100000000000000000000000000000000000); vm.deal(gatewayChain.getAdmin(), 100000000000000000000000000000000000); // vm.deal(msg.sender, 100000000000000000000000000000000000); - // vm.deal(bridgeHub, 100000000000000000000000000000000000); + // vm.deal(bridgehub, 100000000000000000000000000000000000); } // This is a method to simplify porting the tests for now. @@ -128,7 +128,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L _extractAccessControlRestriction(migratingChain.getAdmin()), migratingChainId ); - require(bridgeHub.settlementLayer(migratingChainId) == gatewayChainId, "Migration failed"); + require(bridgehub.settlementLayer(migratingChainId) == gatewayChainId, "Migration failed"); } function test_l2Registration() public { @@ -149,7 +149,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L _extractAccessControlRestriction(migratingChain.getAdmin()), migratingChainId ); - IBridgehub bridgehub = IBridgehub(bridgeHub); + IBridgehub bridgehub = IBridgehub(bridgehub); uint256 expectedValue = 1000000000000000000000; L2TransactionRequestDirect memory request = _createL2TransactionRequestDirect( @@ -172,7 +172,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L ); // Setup - IBridgehub bridgehub = IBridgehub(bridgeHub); + IBridgehub bridgehub = IBridgehub(bridgehub); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); bytes memory transferData; @@ -219,7 +219,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L ); // Set Deposit Happened - vm.startBroadcast(address(bridgeHub)); + vm.startBroadcast(address(bridgehub)); assetRouter.bridgehubConfirmL2Transaction({ _chainId: migratingChainId, _txDataHash: txDataHash, @@ -242,7 +242,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L vm.stopBroadcast(); } - function test_migrateBackChain() public { + function test_finishMigrateBackChain() public { _setUpGatewayWithFilterer(); gatewayScript.migrateChainToGateway( migratingChain.getAdmin(), @@ -253,7 +253,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L } function migrateBackChain() public { - IBridgehub bridgehub = IBridgehub(bridgeHub); + IBridgehub bridgehub = IBridgehub(bridgehub); IZKChain migratingChain = IZKChain(bridgehub.getZKChain(migratingChainId)); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); @@ -267,7 +267,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L // we are already on L1, so we have to set another chain id, it cannot be GW or mintChainId. vm.chainId(migratingChainId); vm.mockCall( - address(bridgeHub), + address(bridgehub), abi.encodeWithSelector(IBridgehub.proveL2MessageInclusion.selector), abi.encode(true) ); @@ -326,7 +326,7 @@ contract L1GatewayTests is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L _setUpGatewayWithFilterer(); vm.chainId(12345); vm.startBroadcast(SETTLEMENT_LAYER_RELAY_SENDER); - bridgeHub.forwardTransactionOnGateway(migratingChainId, bytes32(0), 0); + bridgehub.forwardTransactionOnGateway(migratingChainId, bytes32(0), 0); vm.stopBroadcast(); } diff --git a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol index d7d7866d9..e4cb7e690 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedL1ContractDeployer.t.sol @@ -21,9 +21,9 @@ contract L1ContractDeployer is Test { DeployedAddresses public ecosystemAddresses; Config public ecosystemConfig; - address bridgeHubProxyAddress; - address bridgeHubOwnerAddress; - Bridgehub bridgeHub; + address bridgehubProxyAddress; + address bridgehubOwnerAddress; + Bridgehub bridgehub; CTMDeploymentTracker ctmDeploymentTracker; @@ -55,7 +55,7 @@ contract L1ContractDeployer is Test { ecosystemAddresses = l1Script.getAddresses(); ecosystemConfig = l1Script.getConfig(); - bridgeHub = Bridgehub(ecosystemAddresses.bridgehub.bridgehubProxy); + bridgehub = Bridgehub(ecosystemAddresses.bridgehub.bridgehubProxy); chainTypeManager = IChainTypeManager(ecosystemAddresses.stateTransition.chainTypeManagerProxy); ctmDeploymentTracker = CTMDeploymentTracker(ecosystemAddresses.bridgehub.ctmDeploymentTrackerProxy); @@ -66,12 +66,12 @@ contract L1ContractDeployer is Test { _acceptOwnership(); _setEraBatch(); - bridgeHubOwnerAddress = bridgeHub.owner(); + bridgehubOwnerAddress = bridgehub.owner(); } function _acceptOwnership() private { - vm.startPrank(bridgeHub.pendingOwner()); - bridgeHub.acceptOwnership(); + vm.startPrank(bridgehub.pendingOwner()); + bridgehub.acceptOwnership(); sharedBridge.acceptOwnership(); ctmDeploymentTracker.acceptOwnership(); vm.stopPrank(); @@ -86,9 +86,9 @@ contract L1ContractDeployer is Test { function _registerNewToken(address _tokenAddress) internal { bytes32 tokenAssetId = DataEncoding.encodeNTVAssetId(block.chainid, _tokenAddress); - if (!bridgeHub.assetIdIsRegistered(tokenAssetId)) { - vm.prank(bridgeHubOwnerAddress); - bridgeHub.addTokenAssetId(tokenAssetId); + if (!bridgehub.assetIdIsRegistered(tokenAssetId)) { + vm.prank(bridgehubOwnerAddress); + bridgehub.addTokenAssetId(tokenAssetId); } } diff --git a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol index d9b47ab06..8836fec99 100644 --- a/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol +++ b/l1-contracts/test/foundry/l1/integration/_SharedZKChainDeployer.t.sol @@ -139,15 +139,15 @@ contract ZKChainDeployer is L1ContractDeployer { } function getZKChainAddress(uint256 _chainId) public view returns (address) { - return bridgeHub.getZKChain(_chainId); + return bridgehub.getZKChain(_chainId); } function getZKChainBaseToken(uint256 _chainId) public view returns (address) { - return bridgeHub.baseToken(_chainId); + return bridgehub.baseToken(_chainId); } function acceptPendingAdmin() public { - IZKChain chain = IZKChain(bridgeHub.getZKChain(currentZKChainId - 1)); + IZKChain chain = IZKChain(bridgehub.getZKChain(currentZKChainId - 1)); address admin = chain.getPendingAdmin(); vm.startBroadcast(admin); chain.acceptAdmin(); @@ -164,7 +164,7 @@ contract ZKChainDeployer is L1ContractDeployer { address _admin, uint256 _protocolVersion, bytes32 _storedBatchZero, - address _bridgeHub + address _bridgehub ) internal returns (address) { Diamond.DiamondCutData memory diamondCut = abi.decode( ecosystemConfig.contracts.diamondCutData, @@ -176,7 +176,7 @@ contract ZKChainDeployer is L1ContractDeployer { initData = bytes.concat( IDiamondInit.initialize.selector, bytes32(_chainId), - bytes32(uint256(uint160(address(_bridgeHub)))), + bytes32(uint256(uint160(address(_bridgehub)))), bytes32(uint256(uint160(address(this)))), bytes32(_protocolVersion), bytes32(uint256(uint160(_admin))), diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol index 8892bd21f..3a7611c6e 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol @@ -194,7 +194,7 @@ abstract contract SharedL2ContractDeployer is Test, DeployUtils { L2WrappedBaseToken wethImpl = new L2WrappedBaseToken(); TransparentUpgradeableProxy wethProxy = new TransparentUpgradeableProxy(address(wethImpl), ownerWallet, ""); weth = L2WrappedBaseToken(payable(wethProxy)); - weth.initializeV2("Wrapped Ether", "WETH", L2_ASSET_ROUTER_ADDR, l1WethAddress); + weth.initializeV2("Wrapped Ether", "WETH", L2_ASSET_ROUTER_ADDR, l1WethAddress, baseTokenAssetId); return weth; } diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol index 8c0e7e099..c3ee33a06 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol @@ -43,10 +43,11 @@ contract SharedL2ContractL1DeployerUtils is DeployUtils { using stdToml for string; using stdStorage for StdStorage; + /// @dev We provide a fast form of debugging the L2 contracts using L1 foundry. We also test using zk foundry. function initSystemContracts(SystemContractsArgs memory _args) internal virtual { bytes32 baseTokenAssetId = DataEncoding.encodeNTVAssetId(_args.l1ChainId, ETH_TOKEN_ADDRESS); address wethToken = address(0x1); - + // we deploy the code to get the contract code with immutables which we then etch address messageRoot = address(new MessageRoot(IBridgehub(L2_BRIDGEHUB_ADDR))); address bridgehub = address(new Bridgehub(_args.l1ChainId, _args.aliasedOwner, 100)); address assetRouter = address( diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index f9518d213..9c4f5da05 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -7,12 +7,10 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import "forge-std/console.sol"; -// import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {L2AssetRouter} from "contracts/bridge/asset-router/L2AssetRouter.sol"; import {IL2NativeTokenVault} from "contracts/bridge/ntv/IL2NativeTokenVault.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol"; -// import {BeaconProxy} from "@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol"; import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR, L2_BRIDGEHUB_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {ETH_TOKEN_ADDRESS, SETTLEMENT_LAYER_RELAY_SENDER} from "contracts/common/Config.sol"; From 40a556a75f119f5ae19c4f78581a97a05612709e Mon Sep 17 00:00:00 2001 From: kelemeno Date: Tue, 1 Oct 2024 20:51:15 +0100 Subject: [PATCH 25/27] rename l2 dummy tests --- .../L2Erc20L1Test.t.sol | 0 .../L2Erc20TestAbstract.t.sol | 0 .../L2GatewayL1Test.t.sol | 0 .../L2GatewayTestAbstract.t.sol | 0 .../L2WethTestAbstract.t.sol | 0 .../_SharedL2ContractDeployer.sol | 1 - .../_SharedL2ContractL1DeployerUtils.sol | 2 +- 7 files changed, 1 insertion(+), 2 deletions(-) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/L2Erc20L1Test.t.sol (100%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/L2Erc20TestAbstract.t.sol (100%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/L2GatewayL1Test.t.sol (100%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/L2GatewayTestAbstract.t.sol (100%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/L2WethTestAbstract.t.sol (100%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/_SharedL2ContractDeployer.sol (99%) rename l1-contracts/test/foundry/l1/integration/{l2-dummy-tests => l2-tests-in-l1-context}/_SharedL2ContractL1DeployerUtils.sol (99%) diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20L1Test.t.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2Erc20L1Test.t.sol similarity index 100% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20L1Test.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2Erc20L1Test.t.sol diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2Erc20TestAbstract.t.sol similarity index 100% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2Erc20TestAbstract.t.sol diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2GatewayL1Test.t.sol similarity index 100% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayL1Test.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2GatewayL1Test.t.sol diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2GatewayTestAbstract.t.sol similarity index 100% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2GatewayTestAbstract.t.sol diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2WethTestAbstract.t.sol similarity index 100% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/L2WethTestAbstract.t.sol diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol similarity index 99% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol index 3a7611c6e..83d8def98 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol @@ -30,7 +30,6 @@ import {L2WrappedBaseToken} from "contracts/bridge/L2WrappedBaseToken.sol"; import {L2SharedBridgeLegacy} from "contracts/bridge/L2SharedBridgeLegacy.sol"; import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol"; -// import {L2ContractL1Deployer} from "./_SharedL2ContractL1Deployer.sol"; import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.sol"; import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {SystemContractsArgs} from "./_SharedL2ContractL1DeployerUtils.sol"; diff --git a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol similarity index 99% rename from l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol rename to l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol index c3ee33a06..9dd125055 100644 --- a/l1-contracts/test/foundry/l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol +++ b/l1-contracts/test/foundry/l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol @@ -47,7 +47,7 @@ contract SharedL2ContractL1DeployerUtils is DeployUtils { function initSystemContracts(SystemContractsArgs memory _args) internal virtual { bytes32 baseTokenAssetId = DataEncoding.encodeNTVAssetId(_args.l1ChainId, ETH_TOKEN_ADDRESS); address wethToken = address(0x1); - // we deploy the code to get the contract code with immutables which we then etch + // we deploy the code to get the contract code with immutables which we then vm.etch address messageRoot = address(new MessageRoot(IBridgehub(L2_BRIDGEHUB_ADDR))); address bridgehub = address(new Bridgehub(_args.l1ChainId, _args.aliasedOwner, 100)); address assetRouter = address( From b88b1b6ddb3b99334904f14e7c3be0f9cc84bab1 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Tue, 1 Oct 2024 21:05:22 +0100 Subject: [PATCH 26/27] renamed the dummy-tests folder --- .../test/foundry/l2/integration/L2ERC20BridgeTest.t.sol | 6 +++--- .../test/foundry/l2/integration/L2GatewayTests.t.sol | 6 +++--- l1-contracts/test/foundry/l2/integration/L2Utils.sol | 2 +- l1-contracts/test/foundry/l2/integration/WETH.t.sol | 6 +++--- .../l2/integration/_SharedL2ContractL2DeployerUtils.sol | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol b/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol index 9b308fd9e..8fe0ffcc8 100644 --- a/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2ERC20BridgeTest.t.sol @@ -19,11 +19,11 @@ import {L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol"; import {L2Utils, SystemContractsArgs} from "./L2Utils.sol"; import {SharedL2ContractL2DeployerUtils} from "./_SharedL2ContractL2DeployerUtils.sol"; -import {L2Erc20TestAbstract} from "../../l1/integration/l2-dummy-tests/L2Erc20TestAbstract.t.sol"; -import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; +import {L2Erc20TestAbstract} from "../../l1/integration/l2-tests-in-l1-context/L2Erc20TestAbstract.t.sol"; +import {SharedL2ContractDeployer} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol"; contract L2Erc20Test is Test, L2Erc20TestAbstract, SharedL2ContractL2DeployerUtils { function test() internal virtual override(DeployUtils, SharedL2ContractL2DeployerUtils) {} diff --git a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol index 9c4f5da05..b1ae7bb5f 100644 --- a/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol +++ b/l1-contracts/test/foundry/l2/integration/L2GatewayTests.t.sol @@ -30,9 +30,9 @@ import {IChainTypeManager} from "contracts/state-transition/IChainTypeManager.so import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; -import {L2GatewayTestAbstract} from "../../l1/integration/l2-dummy-tests/L2GatewayTestAbstract.t.sol"; -import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol"; +import {L2GatewayTestAbstract} from "../../l1/integration/l2-tests-in-l1-context/L2GatewayTestAbstract.t.sol"; +import {SharedL2ContractDeployer} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol"; contract L2GatewayTests is Test, L2GatewayTestAbstract, SharedL2ContractL2DeployerUtils { // We need to emulate a L1->L2 transaction from the L1 bridge to L2 counterpart. diff --git a/l1-contracts/test/foundry/l2/integration/L2Utils.sol b/l1-contracts/test/foundry/l2/integration/L2Utils.sol index 9a0afb563..d10105734 100644 --- a/l1-contracts/test/foundry/l2/integration/L2Utils.sol +++ b/l1-contracts/test/foundry/l2/integration/L2Utils.sol @@ -26,7 +26,7 @@ import {BridgedStandardERC20} from "contracts/bridge/BridgedStandardERC20.sol"; import {SystemContractsCaller} from "contracts/common/libraries/SystemContractsCaller.sol"; import {DeployFailed} from "contracts/common/L1ContractErrors.sol"; -import {SystemContractsArgs} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; +import {SystemContractsArgs} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol"; library L2Utils { address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); diff --git a/l1-contracts/test/foundry/l2/integration/WETH.t.sol b/l1-contracts/test/foundry/l2/integration/WETH.t.sol index 5a0b8e246..f7932b4eb 100644 --- a/l1-contracts/test/foundry/l2/integration/WETH.t.sol +++ b/l1-contracts/test/foundry/l2/integration/WETH.t.sol @@ -6,9 +6,9 @@ import {Test} from "forge-std/Test.sol"; import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; -import {SharedL2ContractDeployer} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractDeployer.sol"; -import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; -import {L2WethTestAbstract} from "../../l1/integration/l2-dummy-tests/L2WethTestAbstract.t.sol"; +import {SharedL2ContractDeployer} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractDeployer.sol"; +import {SharedL2ContractL1DeployerUtils} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol"; +import {L2WethTestAbstract} from "../../l1/integration/l2-tests-in-l1-context/L2WethTestAbstract.t.sol"; import {SharedL2ContractL2DeployerUtils, SystemContractsArgs} from "./_SharedL2ContractL2DeployerUtils.sol"; diff --git a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol index 61f51d0cd..0b42255b5 100644 --- a/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol +++ b/l1-contracts/test/foundry/l2/integration/_SharedL2ContractL2DeployerUtils.sol @@ -19,7 +19,7 @@ import {DeployUtils} from "deploy-scripts/DeployUtils.s.sol"; import {L2_BRIDGEHUB_ADDR, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2Utils} from "./L2Utils.sol"; -import {SharedL2ContractL1DeployerUtils, SystemContractsArgs} from "../../l1/integration/l2-dummy-tests/_SharedL2ContractL1DeployerUtils.sol"; +import {SharedL2ContractL1DeployerUtils, SystemContractsArgs} from "../../l1/integration/l2-tests-in-l1-context/_SharedL2ContractL1DeployerUtils.sol"; contract SharedL2ContractL2DeployerUtils is DeployUtils, SharedL2ContractL1DeployerUtils { using stdToml for string; From 37dc6cd76b5fc9d338fea89d4d01eb223e53ecdf Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 2 Oct 2024 18:54:01 +0100 Subject: [PATCH 27/27] missing broadcast --- l1-contracts/deploy-scripts/GatewayPreparation.s.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol index cf6220d5b..212b96055 100644 --- a/l1-contracts/deploy-scripts/GatewayPreparation.s.sol +++ b/l1-contracts/deploy-scripts/GatewayPreparation.s.sol @@ -347,6 +347,7 @@ contract GatewayPreparation is Script { { IBridgehub bridgehub = IBridgehub(config.bridgehub); bytes32 assetId = bridgehub.ctmAssetIdFromChainId(migratingChainId); + vm.broadcast(); l1Nullifier.finalizeDeposit( FinalizeL1DepositParams({ chainId: gatewayChainId,