Skip to content

Commit

Permalink
First iteration on testing the gateway upgrade (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
StanislavBreadless authored Sep 30, 2024
1 parent c99b936 commit c3030f5
Show file tree
Hide file tree
Showing 64 changed files with 2,461 additions and 297 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ l1-contracts/test/foundry/l1/integration/deploy-scripts/script-out/*.toml
l1-contracts/test/foundry/l1/integration/deploy-scripts/script-out/*
l1-contracts/test/foundry/l1/integration/deploy-scripts/script-config/config-deploy-zk-chain-*.toml
l1-contracts/test/foundry/integration/deploy-scripts/script-out/*
l1-contracts/test/foundry/l1/integration/upgrade-envs/script-out/*.toml
l1-contracts/zkout/*
6 changes: 6 additions & 0 deletions l1-contracts/contracts/bridge/L1Nullifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ contract L1Nullifier is IL1Nullifier, ReentrancyGuard, Ownable2StepUpgradeable,
/// NOTE: this function may be removed in the future, don't rely on it!
mapping(uint256 chainId => mapping(address l1Token => uint256 balance)) public __DEPRECATED_chainBalance;

/// @dev Admin has the ability to register new chains within the shared bridge.
address public __DEPRECATED_admin;

/// @dev The pending admin, i.e. the candidate to the admin role.
address public __DEPRECATED_pendingAdmin;

/// @dev Address of L1 asset router.
IL1AssetRouter public l1AssetRouter;

Expand Down
44 changes: 43 additions & 1 deletion l1-contracts/contracts/bridge/L2SharedBridgeLegacy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ import {BridgedStandardERC20} from "./BridgedStandardERC20.sol";
import {DEPLOYER_SYSTEM_CONTRACT, L2_ASSET_ROUTER_ADDR, L2_NATIVE_TOKEN_VAULT_ADDR} from "../common/L2ContractAddresses.sol";
import {SystemContractsCaller} from "../common/libraries/SystemContractsCaller.sol";
import {L2ContractHelper, IContractDeployer} from "../common/libraries/L2ContractHelper.sol";
import {AddressAliasHelper} from "../vendor/AddressAliasHelper.sol";

import {IL2AssetRouter} from "./asset-router/IL2AssetRouter.sol";
import {IL2NativeTokenVault} from "./ntv/IL2NativeTokenVault.sol";

import {IL2SharedBridgeLegacy} from "./interfaces/IL2SharedBridgeLegacy.sol";
import {ZeroAddress, EmptyBytes32, Unauthorized, AmountMustBeGreaterThanZero, DeployFailed} from "../common/L1ContractErrors.sol";
import {InvalidCaller, ZeroAddress, EmptyBytes32, Unauthorized, AmountMustBeGreaterThanZero, DeployFailed} from "../common/L1ContractErrors.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @notice The "default" bridge implementation for the ERC20 tokens. Note, that it does not
/// support any custom token logic, i.e. rebase tokens' functionality is not supported.
/// @dev Note, that this contract should be compatible with its previous version as it will be
/// the primary bridge to be used during migration.
contract L2SharedBridgeLegacy is IL2SharedBridgeLegacy, Initializable {
/// @dev The address of the L1 shared bridge counterpart.
address public override l1SharedBridge;
Expand All @@ -37,6 +40,7 @@ contract L2SharedBridgeLegacy is IL2SharedBridgeLegacy, Initializable {

/// @dev The address of the legacy L1 erc20 bridge counterpart.
/// This is non-zero only on Era, and should not be renamed for backward compatibility with the SDKs.
// slither-disable-next-line uninitialized-state
address public override l1Bridge;

modifier onlyNTV() {
Expand Down Expand Up @@ -103,6 +107,44 @@ contract L2SharedBridgeLegacy is IL2SharedBridgeLegacy, Initializable {
IL2AssetRouter(L2_ASSET_ROUTER_ADDR).withdrawLegacyBridge(_l1Receiver, _l2Token, _amount, msg.sender);
}

/// @notice Finalize the deposit and mint funds
/// @param _l1Sender The account address that initiated the deposit on L1
/// @param _l2Receiver The account address that would receive minted ether
/// @param _l1Token The address of the token that was locked on the L1
/// @param _amount Total amount of tokens deposited from L1
/// @param _data The additional data that user can pass with the deposit
function finalizeDeposit(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) external {
// Only the L1 bridge counterpart can initiate and finalize the deposit.
if (
AddressAliasHelper.undoL1ToL2Alias(msg.sender) != l1Bridge &&
AddressAliasHelper.undoL1ToL2Alias(msg.sender) != l1SharedBridge
) {
revert InvalidCaller(msg.sender);
}

IL2AssetRouter(L2_ASSET_ROUTER_ADDR).finalizeDepositLegacyBridge({
_l1Sender: _l1Sender,
_l2Receiver: _l2Receiver,
_l1Token: _l1Token,
_amount: _amount,
_data: _data
});

address l2Token = IL2NativeTokenVault(L2_NATIVE_TOKEN_VAULT_ADDR).l2TokenAddress(_l1Token);

if (l1TokenAddress[l2Token] == address(0)) {
l1TokenAddress[l2Token] = _l1Token;
}

emit FinalizeDeposit(_l1Sender, _l2Receiver, l2Token, _amount);
}

/// @return Address of an L2 token counterpart
function l2TokenAddress(address _l1Token) public view override returns (address) {
address token = IL2NativeTokenVault(L2_NATIVE_TOKEN_VAULT_ADDR).l2TokenAddress(_l1Token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {IL1Nullifier} from "../interfaces/IL1Nullifier.sol";
import {INativeTokenVault} from "../ntv/INativeTokenVault.sol";
import {IAssetRouterBase} from "./IAssetRouterBase.sol";
import {L2TransactionRequestTwoBridgesInner} from "../../bridgehub/IBridgehub.sol";
import {IL1SharedBridgeLegacy} from "../interfaces/IL1SharedBridgeLegacy.sol";

/// @title L1 Bridge contract interface
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IL1AssetRouter is IAssetRouterBase {
interface IL1AssetRouter is IAssetRouterBase, IL1SharedBridgeLegacy {
event BridgehubMintData(bytes bridgeMintData);

event BridgehubDepositFinalized(
Expand Down
8 changes: 8 additions & 0 deletions l1-contracts/contracts/bridge/asset-router/IL2AssetRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ interface IL2AssetRouter {

function withdrawLegacyBridge(address _l1Receiver, address _l2Token, uint256 _amount, address _sender) external;

function finalizeDepositLegacyBridge(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) external;

/// @dev Used to set the assedAddress for a given assetId.
/// @dev Will be used by ZK Gateway
function setAssetHandlerAddress(uint256 _originChainId, bytes32 _assetId, address _assetAddress) external;
Expand Down
7 changes: 7 additions & 0 deletions l1-contracts/contracts/bridge/asset-router/L1AssetRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -585,4 +585,11 @@ contract L1AssetRouter is AssetRouterBase, IL1AssetRouter, ReentrancyGuard {
_merkleProof: _merkleProof
});
}

/// @notice Legacy function to get the L2 shared bridge address for a chain.
/// @dev In case the chain has been deployed after the gateway release,
/// the returned value is 0.
function l2BridgeAddress(uint256 _chainId) external view override returns (address) {
return L1_NULLIFIER.l2BridgeAddress(_chainId);
}
}
32 changes: 32 additions & 0 deletions l1-contracts/contracts/bridge/asset-router/L2AssetRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,38 @@ contract L2AssetRouter is AssetRouterBase, IL2AssetRouter {
uint256 _amount,
bytes calldata _data
) external onlyAssetRouterCounterpart(L1_CHAIN_ID) {
_translateLegacyFinalizeDeposit({
_l1Sender: _l1Sender,
_l2Receiver: _l2Receiver,
_l1Token: _l1Token,
_amount: _amount,
_data: _data
});
}

function finalizeDepositLegacyBridge(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) external onlyLegacyBridge {
_translateLegacyFinalizeDeposit({
_l1Sender: _l1Sender,
_l2Receiver: _l2Receiver,
_l1Token: _l1Token,
_amount: _amount,
_data: _data
});
}

function _translateLegacyFinalizeDeposit(
address _l1Sender,
address _l2Receiver,
address _l1Token,
uint256 _amount,
bytes calldata _data
) internal {
bytes32 assetId = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, _l1Token);
// solhint-disable-next-line func-named-parameters
bytes memory data = DataEncoding.encodeBridgeMintData(_l1Sender, _l2Receiver, _l1Token, _amount, _data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,4 @@ pragma solidity 0.8.24;
/// @custom:security-contact [email protected]
interface IL1SharedBridgeLegacy {
function l2BridgeAddress(uint256 _chainId) external view returns (address);

event LegacyDepositInitiated(
uint256 indexed chainId,
bytes32 indexed l2DepositTxHash,
address indexed from,
address to,
address l1Asset,
uint256 amount
);
}
11 changes: 11 additions & 0 deletions l1-contracts/contracts/bridge/interfaces/IL2SharedBridgeLegacy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@

pragma solidity ^0.8.20;

import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IL2SharedBridgeLegacy {
event FinalizeDeposit(
address indexed l1Sender,
address indexed l2Receiver,
address indexed l2Token,
uint256 amount
);

function l2TokenBeacon() external returns (UpgradeableBeacon);

function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external;

function l1TokenAddress(address _l2Token) external view returns (address);
Expand Down
15 changes: 12 additions & 3 deletions l1-contracts/contracts/bridgehub/Bridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,24 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
// We will change this with interop.
ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(L1_CHAIN_ID, ETH_TOKEN_ADDRESS);
_transferOwnership(_owner);
whitelistedSettlementLayers[_l1ChainId] = true;
_initializeInner();
}

/// @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 {
function initialize(address _owner) external reentrancyGuardInitializer onlyL1 {
_transferOwnership(_owner);
_initializeInner();
}

/// @notice Used to initialize the contract on L1
function initializeV2() external initializer onlyL1 {
_initializeInner();
}

/// @notice Initializes the contract
function _initializeInner() internal {
assetIdIsRegistered[ETH_TOKEN_ASSET_ID] = true;
whitelistedSettlementLayers[L1_CHAIN_ID] = true;
}
Expand Down Expand Up @@ -356,7 +366,6 @@ contract Bridgehub is IBridgehub, ReentrancyGuard, Ownable2StepUpgradeable, Paus
address chainAddress = IChainTypeManager(_chainTypeManager).createNewChain({
_chainId: _chainId,
_baseTokenAssetId: _baseTokenAssetId,
_assetRouter: assetRouter,
_admin: _admin,
_initData: _initData,
_factoryDeps: _factoryDeps
Expand Down
6 changes: 6 additions & 0 deletions l1-contracts/contracts/dev-contracts/test/DummyBridgehub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ contract DummyBridgehub {

address public zkChain;

address public sharedBridge;

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

Expand All @@ -41,4 +43,8 @@ contract DummyBridgehub {
function getZKChain(uint256) external view returns (address) {
return address(0);
}

function setSharedBridge(address addr) external {
sharedBridge = addr;
}
}
22 changes: 22 additions & 0 deletions l1-contracts/contracts/governance/L2ProxyAdminDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

// solhint-disable gas-length-in-loops

import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @notice The contract that deterministically deploys a ProxyAdmin, while
/// ensuring that its owner is the aliased governance contract
contract L2ProxyAdminDeployer {
address public immutable PROXY_ADMIN_ADDRESS;

constructor(address _aliasedGovernance) {
ProxyAdmin admin = new ProxyAdmin{salt: bytes32(0)}();
admin.transferOwnership(_aliasedGovernance);

PROXY_ADMIN_ADDRESS = address(admin);
}
}
25 changes: 25 additions & 0 deletions l1-contracts/contracts/governance/TransitionaryOwner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

// solhint-disable gas-length-in-loops

import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol";

/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @notice The contract that is used a temporary owner for Ownable2Step contracts until the
/// governance can accept the ownership
contract TransitionaryOwner {
address public immutable GOVERNANCE_ADDRESS;

constructor(address _governanceAddress) {
GOVERNANCE_ADDRESS = _governanceAddress;
}

/// @notice Claims that ownership of a contract and transfers it to the governance
function claimOwnershipAndGiveToGovernance(address target) external {
Ownable2Step(target).acceptOwnership();
Ownable2Step(target).transferOwnership(GOVERNANCE_ADDRESS);
}
}
8 changes: 1 addition & 7 deletions l1-contracts/contracts/state-transition/ChainTypeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,11 @@ contract ChainTypeManager is IChainTypeManager, ReentrancyGuard, Ownable2StepUpg
/// @notice deploys a full set of chains contracts
/// @param _chainId the chain's id
/// @param _baseTokenAssetId the base token asset id used to pay for gas fees
/// @param _sharedBridge the shared bridge address, used as base token bridge
/// @param _admin the chain's admin address
/// @param _diamondCut the diamond cut data that initializes the chains Diamond Proxy
function _deployNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _sharedBridge,
address _admin,
bytes memory _diamondCut
) internal returns (address zkChainAddress) {
Expand Down Expand Up @@ -383,7 +381,6 @@ contract ChainTypeManager is IChainTypeManager, ReentrancyGuard, Ownable2StepUpg
bytes32(uint256(uint160(_admin))),
bytes32(uint256(uint160(validatorTimelock))),
_baseTokenAssetId,
bytes32(uint256(uint160(_sharedBridge))),
storedBatchZero,
diamondCut.initCalldata
);
Expand All @@ -400,23 +397,21 @@ contract ChainTypeManager is IChainTypeManager, ReentrancyGuard, Ownable2StepUpg
/// @notice called by Bridgehub when a chain registers
/// @param _chainId the chain's id
/// @param _baseTokenAssetId the base token asset id used to pay for gas fees
/// @param _assetRouter the shared bridge address, used as base token bridge
/// @param _admin the chain's admin address
/// @param _initData the diamond cut data, force deployments and factoryDeps encoded
/// @param _factoryDeps the factory dependencies used for the genesis upgrade
/// that initializes the chains Diamond Proxy
function createNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _assetRouter,
address _admin,
bytes calldata _initData,
bytes[] calldata _factoryDeps
) external onlyBridgehub returns (address zkChainAddress) {
(bytes memory _diamondCut, bytes memory _forceDeploymentData) = abi.decode(_initData, (bytes, bytes));

// solhint-disable-next-line func-named-parameters
zkChainAddress = _deployNewChain(_chainId, _baseTokenAssetId, _assetRouter, _admin, _diamondCut);
zkChainAddress = _deployNewChain(_chainId, _baseTokenAssetId, _admin, _diamondCut);

{
// check input
Expand Down Expand Up @@ -492,7 +487,6 @@ contract ChainTypeManager is IChainTypeManager, ReentrancyGuard, Ownable2StepUpg
chainAddress = _deployNewChain({
_chainId: _chainId,
_baseTokenAssetId: _baseTokenAssetId,
_sharedBridge: address(IBridgehub(BRIDGE_HUB).sharedBridge()),
_admin: _admin,
_diamondCut: _diamondCut
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ interface IChainTypeManager {
function createNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _assetRouter,
address _admin,
bytes calldata _initData,
bytes[] calldata _factoryDeps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ contract DiamondInit is ZKChainBase, IDiamondInit {
if (_initializeData.baseTokenAssetId == bytes32(0)) {
revert ZeroAddress();
}
if (_initializeData.baseTokenBridge == address(0)) {
revert ZeroAddress();
}
if (_initializeData.blobVersionedHashRetriever == address(0)) {
revert ZeroAddress();
}
Expand All @@ -56,7 +53,6 @@ contract DiamondInit is ZKChainBase, IDiamondInit {
s.bridgehub = _initializeData.bridgehub;
s.chainTypeManager = _initializeData.chainTypeManager;
s.baseTokenAssetId = _initializeData.baseTokenAssetId;
s.baseTokenBridge = _initializeData.baseTokenBridge;
s.protocolVersion = _initializeData.protocolVersion;

s.verifier = _initializeData.verifier;
Expand Down
Loading

0 comments on commit c3030f5

Please sign in to comment.