Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
0x60c06040 | 21809379 | 101 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CTMDeploymentTracker
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol"; import {IBridgehub, L2TransactionRequestTwoBridgesInner} from "./IBridgehub.sol"; import {ICTMDeploymentTracker} from "./ICTMDeploymentTracker.sol"; import {IAssetRouterBase} from "../bridge/asset-router/IAssetRouterBase.sol"; import {TWO_BRIDGES_MAGIC_VALUE} from "../common/Config.sol"; import {L2_BRIDGEHUB_ADDR} from "../common/L2ContractAddresses.sol"; import {OnlyBridgehub, CTMNotRegistered, NotOwnerViaRouter, NoEthAllowed, NotOwner, WrongCounterPart} from "./L1BridgehubErrors.sol"; import {UnsupportedEncodingVersion} from "../common/L1ContractErrors.sol"; /// @dev The encoding version of the data. bytes1 constant CTM_DEPLOYMENT_TRACKER_ENCODING_VERSION = 0x01; /// @author Matter Labs /// @custom:security-contact [email protected] /// @dev Contract to be deployed on L1, can link together other contracts based on AssetInfo. contract CTMDeploymentTracker is ICTMDeploymentTracker, Ownable2StepUpgradeable { /// @dev Bridgehub smart contract that is used to operate with L2 via asynchronous L2 <-> L1 communication. IBridgehub public immutable override BRIDGE_HUB; /// @dev L1AssetRouter smart contract that is used to bridge assets (including chains) between L1 and L2. IAssetRouterBase public immutable override L1_ASSET_ROUTER; /// @notice Checks that the message sender is the bridgehub. modifier onlyBridgehub() { if (msg.sender != address(BRIDGE_HUB)) { revert OnlyBridgehub(msg.sender, address(BRIDGE_HUB)); } _; } /// @notice Checks that the message sender is the bridgehub. modifier onlyOwnerViaRouter(address _originalCaller) { if (msg.sender != address(L1_ASSET_ROUTER) || _originalCaller != owner()) { revert NotOwnerViaRouter(msg.sender, _originalCaller); } _; } /// @dev Contract is expected to be used as proxy implementation on L1. /// @dev Initialize the implementation to prevent Parity hack. constructor(IBridgehub _bridgehub, IAssetRouterBase _l1AssetRouter) { _disableInitializers(); BRIDGE_HUB = _bridgehub; L1_ASSET_ROUTER = _l1AssetRouter; } /// @notice used to initialize the contract /// @param _owner the owner of the contract function initialize(address _owner) external initializer { _transferOwnership(_owner); } /// @notice Used to register the ctm asset in L1 contracts, AssetRouter and Bridgehub. /// @param _ctmAddress the address of the ctm asset function registerCTMAssetOnL1(address _ctmAddress) external onlyOwner { if (!BRIDGE_HUB.chainTypeManagerIsRegistered(_ctmAddress)) { revert CTMNotRegistered(); } L1_ASSET_ROUTER.setAssetHandlerAddressThisChain(bytes32(uint256(uint160(_ctmAddress))), address(BRIDGE_HUB)); BRIDGE_HUB.setCTMAssetAddress(bytes32(uint256(uint160(_ctmAddress))), _ctmAddress); } /// @notice The function responsible for registering the L2 counterpart of an CTM asset on the L2 Bridgehub. /// @dev The function is called by the Bridgehub contract during the `Bridgehub.requestL2TransactionTwoBridges`. /// @dev Since the L2 settlement layers `_chainId` might potentially have ERC20 tokens as native assets, /// there are two ways to perform the L1->L2 transaction: /// - via the `Bridgehub.requestL2TransactionDirect`. However, this would require the CTMDeploymentTracker to /// handle the ERC20 balances to be used in the transaction. /// - via the `Bridgehub.requestL2TransactionTwoBridges`. This way it will be the sender that provides the funds /// for the L2 transaction. /// The second approach is used due to its simplicity even though it gives the sender slightly more control over the call: /// `gasLimit`, etc. /// @param _chainId the chainId of the chain /// @param _originalCaller the previous message sender /// @param _data the data of the transaction // slither-disable-next-line locked-ether function bridgehubDeposit( uint256 _chainId, address _originalCaller, uint256, bytes calldata _data ) external payable onlyBridgehub returns (L2TransactionRequestTwoBridgesInner memory request) { if (msg.value != 0) { revert NoEthAllowed(); } if (_originalCaller != owner()) { revert NotOwner(_originalCaller, owner()); } bytes1 encodingVersion = _data[0]; if (encodingVersion != CTM_DEPLOYMENT_TRACKER_ENCODING_VERSION) { revert UnsupportedEncodingVersion(); } (address _ctmL1Address, address _ctmL2Address) = abi.decode(_data[1:], (address, address)); request = _registerCTMAssetOnL2Bridgehub(_chainId, _ctmL1Address, _ctmL2Address); } /// @notice The function called by the Bridgehub after the L2 transaction has been initiated. /// @dev Not used in this contract. In case the transaction fails, we can just re-try it. function bridgehubConfirmL2Transaction( uint256 _chainId, bytes32 _txDataHash, bytes32 _txHash ) external onlyBridgehub {} /// @notice Used to register the ctm asset in L2 AssetRouter. /// @param _originalCaller the address that called the Router /// @param _assetHandlerAddressOnCounterpart the address of the asset handler on the counterpart chain. function bridgeCheckCounterpartAddress( uint256, bytes32, address _originalCaller, address _assetHandlerAddressOnCounterpart ) external view override onlyOwnerViaRouter(_originalCaller) { if (_assetHandlerAddressOnCounterpart != L2_BRIDGEHUB_ADDR) { revert WrongCounterPart(_assetHandlerAddressOnCounterpart, L2_BRIDGEHUB_ADDR); } } function calculateAssetId(address _l1CTM) public view override returns (bytes32) { return keccak256(abi.encode(block.chainid, address(this), bytes32(uint256(uint160(_l1CTM))))); } /// @notice Used to register the ctm asset in L2 Bridgehub. /// @param _chainId the chainId of the chain function _registerCTMAssetOnL2Bridgehub( // solhint-disable-next-line no-unused-vars uint256 _chainId, address _ctmL1Address, address _ctmL2Address ) internal pure returns (L2TransactionRequestTwoBridgesInner memory request) { bytes memory l2TxCalldata = abi.encodeCall( IBridgehub.setCTMAssetAddress, (bytes32(uint256(uint160(_ctmL1Address))), _ctmL2Address) ); request = L2TransactionRequestTwoBridgesInner({ magicValue: TWO_BRIDGES_MAGIC_VALUE, l2Contract: L2_BRIDGEHUB_ADDR, l2Calldata: l2TxCalldata, factoryDeps: new bytes[](0), // The `txDataHash` is typically used in usual ERC20 bridges to commit to the transaction data // so that the user can recover funds in case the bridging fails on L2. // However, this contract uses the `requestL2TransactionTwoBridges` method just to perform an L1->L2 transaction. // We do not need to recover anything and so `bytes32(0)` here is okay. txDataHash: bytes32(0) }); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @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[49] private __gap; }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {L2Message, L2Log, TxStatus} from "../common/Messaging.sol"; import {IL1AssetHandler} from "../bridge/interfaces/IL1AssetHandler.sol"; import {ICTMDeploymentTracker} from "./ICTMDeploymentTracker.sol"; import {IMessageRoot} from "./IMessageRoot.sol"; import {IAssetHandler} from "../bridge/interfaces/IAssetHandler.sol"; struct L2TransactionRequestDirect { uint256 chainId; uint256 mintValue; address l2Contract; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; } struct L2TransactionRequestTwoBridgesOuter { uint256 chainId; uint256 mintValue; uint256 l2Value; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; address refundRecipient; address secondBridgeAddress; uint256 secondBridgeValue; bytes secondBridgeCalldata; } struct L2TransactionRequestTwoBridgesInner { bytes32 magicValue; address l2Contract; bytes l2Calldata; bytes[] factoryDeps; bytes32 txDataHash; } struct BridgehubMintCTMAssetData { uint256 chainId; bytes32 baseTokenAssetId; bytes ctmData; bytes chainData; } struct BridgehubBurnCTMAssetData { uint256 chainId; bytes ctmData; bytes chainData; } /// @author Matter Labs /// @custom:security-contact [email protected] interface IBridgehub is IAssetHandler, IL1AssetHandler { /// @notice pendingAdmin is changed /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin); /// @notice Admin changed event NewAdmin(address indexed oldAdmin, address indexed newAdmin); /// @notice CTM asset registered event AssetRegistered( bytes32 indexed assetInfo, address indexed _assetAddress, bytes32 indexed additionalData, address sender ); event SettlementLayerRegistered(uint256 indexed chainId, bool indexed isWhitelisted); /// @notice Emitted when the bridging to the chain is started. /// @param chainId Chain ID of the ZK chain /// @param assetId Asset ID of the token for the zkChain's CTM /// @param settlementLayerChainId The chain id of the settlement layer the chain migrates to. event MigrationStarted(uint256 indexed chainId, bytes32 indexed assetId, uint256 indexed settlementLayerChainId); /// @notice Emitted when the bridging to the chain is complete. /// @param chainId Chain ID of the ZK chain /// @param assetId Asset ID of the token for the zkChain's CTM /// @param zkChain The address of the ZK chain on the chain where it is migrated to. event MigrationFinalized(uint256 indexed chainId, bytes32 indexed assetId, address indexed zkChain); /// @notice Starts the transfer of admin rights. Only the current admin or owner can propose a new pending one. /// @notice New admin can accept admin rights by calling `acceptAdmin` function. /// @param _newPendingAdmin Address of the new admin function setPendingAdmin(address _newPendingAdmin) external; /// @notice Accepts transfer of admin rights. Only pending admin can accept the role. function acceptAdmin() external; /// Getters function chainTypeManagerIsRegistered(address _chainTypeManager) external view returns (bool); function chainTypeManager(uint256 _chainId) external view returns (address); function assetIdIsRegistered(bytes32 _baseTokenAssetId) external view returns (bool); function baseToken(uint256 _chainId) external view returns (address); function baseTokenAssetId(uint256 _chainId) external view returns (bytes32); function sharedBridge() external view returns (address); function messageRoot() external view returns (IMessageRoot); function getZKChain(uint256 _chainId) external view returns (address); function getAllZKChains() external view returns (address[] memory); function getAllZKChainChainIDs() external view returns (uint256[] memory); function migrationPaused() external view returns (bool); function admin() external view returns (address); function assetRouter() external view returns (address); /// Mailbox forwarder function proveL2MessageInclusion( uint256 _chainId, uint256 _batchNumber, uint256 _index, L2Message calldata _message, bytes32[] calldata _proof ) external view returns (bool); function proveL2LogInclusion( uint256 _chainId, uint256 _batchNumber, uint256 _index, L2Log memory _log, bytes32[] calldata _proof ) external view returns (bool); function proveL1ToL2TransactionStatus( uint256 _chainId, bytes32 _l2TxHash, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes32[] calldata _merkleProof, TxStatus _status ) external view returns (bool); function requestL2TransactionDirect( L2TransactionRequestDirect calldata _request ) external payable returns (bytes32 canonicalTxHash); function requestL2TransactionTwoBridges( L2TransactionRequestTwoBridgesOuter calldata _request ) external payable returns (bytes32 canonicalTxHash); function l2TransactionBaseCost( uint256 _chainId, uint256 _gasPrice, uint256 _l2GasLimit, uint256 _l2GasPerPubdataByteLimit ) external view returns (uint256); //// Registry function createNewChain( uint256 _chainId, address _chainTypeManager, bytes32 _baseTokenAssetId, uint256 _salt, address _admin, bytes calldata _initData, bytes[] calldata _factoryDeps ) external returns (uint256 chainId); function addChainTypeManager(address _chainTypeManager) external; function removeChainTypeManager(address _chainTypeManager) external; function addTokenAssetId(bytes32 _baseTokenAssetId) external; function setAddresses( address _sharedBridge, ICTMDeploymentTracker _l1CtmDeployer, IMessageRoot _messageRoot ) external; event NewChain(uint256 indexed chainId, address chainTypeManager, address indexed chainGovernance); event ChainTypeManagerAdded(address indexed chainTypeManager); event ChainTypeManagerRemoved(address indexed chainTypeManager); event BaseTokenAssetIdRegistered(bytes32 indexed assetId); function whitelistedSettlementLayers(uint256 _chainId) external view returns (bool); function registerSettlementLayer(uint256 _newSettlementLayerChainId, bool _isWhitelisted) external; function settlementLayer(uint256 _chainId) external view returns (uint256); // function finalizeMigrationToGateway( // uint256 _chainId, // address _baseToken, // address _sharedBridge, // address _admin, // uint256 _expectedProtocolVersion, // ZKChainCommitment calldata _commitment, // bytes calldata _diamondCut // ) external; function forwardTransactionOnGateway( uint256 _chainId, bytes32 _canonicalTxHash, uint64 _expirationTimestamp ) external; function ctmAssetIdFromChainId(uint256 _chainId) external view returns (bytes32); function ctmAssetIdFromAddress(address _ctmAddress) external view returns (bytes32); function l1CtmDeployer() external view returns (ICTMDeploymentTracker); function ctmAssetIdToAddress(bytes32 _assetInfo) external view returns (address); function setCTMAssetAddress(bytes32 _additionalData, address _assetAddress) external; function L1_CHAIN_ID() external view returns (uint256); function registerAlreadyDeployedZKChain(uint256 _chainId, address _hyperchain) external; /// @notice return the ZK chain contract for a chainId /// @dev It is a legacy method. Do not use! function getHyperchain(uint256 _chainId) external view returns (address); function registerLegacyChain(uint256 _chainId) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {L2TransactionRequestTwoBridgesInner, IBridgehub} from "./IBridgehub.sol"; import {IAssetRouterBase} from "../bridge/asset-router/IAssetRouterBase.sol"; import {IL1AssetDeploymentTracker} from "../bridge/interfaces/IL1AssetDeploymentTracker.sol"; /// @author Matter Labs /// @custom:security-contact [email protected] interface ICTMDeploymentTracker is IL1AssetDeploymentTracker { function bridgehubDeposit( uint256 _chainId, address _originalCaller, uint256 _l2Value, bytes calldata _data ) external payable returns (L2TransactionRequestTwoBridgesInner memory request); function BRIDGE_HUB() external view returns (IBridgehub); function L1_ASSET_ROUTER() external view returns (IAssetRouterBase); function registerCTMAssetOnL1(address _ctmAddress) external; function calculateAssetId(address _l1CTM) external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IBridgehub} from "../../bridgehub/IBridgehub.sol"; /// @dev The encoding version used for legacy txs. bytes1 constant LEGACY_ENCODING_VERSION = 0x00; /// @dev The encoding version used for new txs. bytes1 constant NEW_ENCODING_VERSION = 0x01; /// @dev The encoding version used for txs that set the asset handler on the counterpart contract. bytes1 constant SET_ASSET_HANDLER_COUNTERPART_ENCODING_VERSION = 0x02; /// @title L1 Bridge contract interface /// @author Matter Labs /// @custom:security-contact [email protected] interface IAssetRouterBase { event BridgehubDepositBaseTokenInitiated( uint256 indexed chainId, address indexed from, bytes32 assetId, uint256 amount ); event BridgehubDepositInitiated( uint256 indexed chainId, bytes32 indexed txDataHash, address indexed from, bytes32 assetId, bytes bridgeMintCalldata ); event BridgehubWithdrawalInitiated( uint256 chainId, address indexed sender, bytes32 indexed assetId, bytes32 assetDataHash // Todo: What's the point of emitting hash? ); event AssetDeploymentTrackerRegistered( bytes32 indexed assetId, bytes32 indexed additionalData, address assetDeploymentTracker ); event AssetHandlerRegistered(bytes32 indexed assetId, address indexed _assetHandlerAddress); event DepositFinalizedAssetRouter(uint256 indexed chainId, bytes32 indexed assetId, bytes assetData); function BRIDGE_HUB() external view returns (IBridgehub); /// @notice Sets the asset handler address for a specified asset ID on the chain of the asset deployment tracker. /// @dev The caller of this function is encoded within the `assetId`, therefore, it should be invoked by the asset deployment tracker contract. /// @dev No access control on the caller, as msg.sender is encoded in the assetId. /// @dev Typically, for most tokens, ADT is the native token vault. However, custom tokens may have their own specific asset deployment trackers. /// @dev `setAssetHandlerAddressOnCounterpart` should be called on L1 to set asset handlers on L2 chains for a specific asset ID. /// @param _assetRegistrationData The asset data which may include the asset address and any additional required data or encodings. /// @param _assetHandlerAddress The address of the asset handler to be set for the provided asset. function setAssetHandlerAddressThisChain(bytes32 _assetRegistrationData, address _assetHandlerAddress) external; function assetHandlerAddress(bytes32 _assetId) external view returns (address); /// @notice Finalize the withdrawal and release funds. /// @param _chainId The chain ID of the transaction to check. /// @param _assetId The bridged asset ID. /// @param _transferData The position in the L2 logs Merkle tree of the l2Log that was sent with the message. /// @dev We have both the legacy finalizeWithdrawal and the new finalizeDeposit functions, /// finalizeDeposit uses the new format. On the L2 we have finalizeDeposit with new and old formats both. function finalizeDeposit(uint256 _chainId, bytes32 _assetId, bytes memory _transferData) external payable; }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev `keccak256("")` bytes32 constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; /// @dev Bytes in raw L2 log /// @dev Equal to the bytes size of the tuple - (uint8 ShardId, bool isService, uint16 txNumberInBatch, address sender, /// bytes32 key, bytes32 value) uint256 constant L2_TO_L1_LOG_SERIALIZE_SIZE = 88; /// @dev The maximum length of the bytes array with L2 -> L1 logs uint256 constant MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES = 4 + L2_TO_L1_LOG_SERIALIZE_SIZE * 512; /// @dev The value of default leaf hash for L2 -> L1 logs Merkle tree /// @dev An incomplete fixed-size tree is filled with this value to be a full binary tree /// @dev Actually equal to the `keccak256(new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE))` bytes32 constant L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = 0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba; bytes32 constant DEFAULT_L2_LOGS_TREE_ROOT_HASH = bytes32(0); /// @dev Denotes the type of the ZKsync transaction that came from L1. uint256 constant PRIORITY_OPERATION_L2_TX_TYPE = 255; /// @dev Denotes the type of the ZKsync transaction that is used for system upgrades. uint256 constant SYSTEM_UPGRADE_L2_TX_TYPE = 254; /// @dev The maximal allowed difference between protocol minor versions in an upgrade. The 100 gap is needed /// in case a protocol version has been tested on testnet, but then not launched on mainnet, e.g. /// due to a bug found. /// We are allowed to jump at most 100 minor versions at a time. The major version is always expected to be 0. uint256 constant MAX_ALLOWED_MINOR_VERSION_DELTA = 100; /// @dev The amount of time in seconds the validator has to process the priority transaction /// NOTE: The constant is set to zero for the Alpha release period uint256 constant PRIORITY_EXPIRATION = 0 days; /// @dev Timestamp - seconds since unix epoch. uint256 constant COMMIT_TIMESTAMP_NOT_OLDER = 3 days; /// @dev Maximum available error between real commit batch timestamp and analog used in the verifier (in seconds) /// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 12 seconds) uint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 1 hours; /// @dev Shift to apply to verify public input before verifying. uint256 constant PUBLIC_INPUT_SHIFT = 32; /// @dev The maximum number of L2 gas that a user can request for an L2 transaction uint256 constant MAX_GAS_PER_TRANSACTION = 80_000_000; /// @dev Even though the price for 1 byte of pubdata is 16 L1 gas, we have a slightly increased /// value. uint256 constant L1_GAS_PER_PUBDATA_BYTE = 17; /// @dev The intrinsic cost of the L1->l2 transaction in computational L2 gas uint256 constant L1_TX_INTRINSIC_L2_GAS = 167_157; /// @dev The intrinsic cost of the L1->l2 transaction in pubdata uint256 constant L1_TX_INTRINSIC_PUBDATA = 88; /// @dev The minimal base price for L1 transaction uint256 constant L1_TX_MIN_L2_GAS_BASE = 173_484; /// @dev The number of L2 gas the transaction starts costing more with each 544 bytes of encoding uint256 constant L1_TX_DELTA_544_ENCODING_BYTES = 1656; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64; /// @dev The number of pubdata an L1->L2 transaction requires with each new factory dependency uint256 constant MAX_NEW_FACTORY_DEPS = 64; /// @dev The L2 gasPricePerPubdata required to be used in bridges. uint256 constant REQUIRED_L2_GAS_PRICE_PER_PUBDATA = 800; /// @dev The mask which should be applied to the packed batch and L2 block timestamp in order /// to obtain the L2 block timestamp. Applying this mask is equivalent to calculating modulo 2**128 uint256 constant PACKED_L2_BLOCK_TIMESTAMP_MASK = 0xffffffffffffffffffffffffffffffff; /// @dev Address of the point evaluation precompile used for EIP-4844 blob verification. address constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A); /// @dev The overhead for a transaction slot in L2 gas. /// It is roughly equal to 80kk/MAX_TRANSACTIONS_IN_BATCH, i.e. how many gas would an L1->L2 transaction /// need to pay to compensate for the batch being closed. /// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate /// the operator in case the batch is closed because of tx slots filling up. uint256 constant TX_SLOT_OVERHEAD_L2_GAS = 10000; /// @dev The overhead for each byte of the bootloader memory that the encoding of the transaction. /// It is roughly equal to 80kk/BOOTLOADER_MEMORY_FOR_TXS, i.e. how many gas would an L1->L2 transaction /// need to pay to compensate for the batch being closed. /// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate /// the operator in case the batch is closed because of the memory for transactions being filled up. uint256 constant MEMORY_OVERHEAD_GAS = 10; /// @dev The maximum gas limit for a priority transaction in L2. uint256 constant PRIORITY_TX_MAX_GAS_LIMIT = 72_000_000; /// @dev the address used to identify eth as the base token for chains. address constant ETH_TOKEN_ADDRESS = address(1); /// @dev the value returned in bridgehubDeposit in the TwoBridges function. bytes32 constant TWO_BRIDGES_MAGIC_VALUE = bytes32(uint256(keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1); /// @dev https://eips.ethereum.org/EIPS/eip-1352 address constant BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS = address(uint160(type(uint16).max)); /// @dev the maximum number of supported chains, this is an arbitrary limit. /// @dev Note, that in case of a malicious Bridgehub admin, the total number of chains /// can be up to 2 times higher. This may be possible, in case the old ChainTypeManager /// had `100` chains and these were migrated to the Bridgehub only after `MAX_NUMBER_OF_ZK_CHAINS` /// were added to the bridgehub via creation of new chains. uint256 constant MAX_NUMBER_OF_ZK_CHAINS = 100; /// @dev Used as the `msg.sender` for transactions that relayed via a settlement layer. address constant SETTLEMENT_LAYER_RELAY_SENDER = address(uint160(0x1111111111111111111111111111111111111111)); /// @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; uint256 unprocessedIndex; bytes32[] sides; } // Info that allows to restore a chain. struct ZKChainCommitment { /// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch /// (batch 0 is genesis) uint256 totalBatchesExecuted; /// @notice Total number of proved batches i.e. batches[totalBatchesProved] points at the latest proved batch uint256 totalBatchesVerified; /// @notice Total number of committed batches i.e. batches[totalBatchesCommitted] points at the latest committed /// batch uint256 totalBatchesCommitted; /// @notice The hash of the L2 system contracts ugpgrade transaction. /// @dev It is non zero if the migration happens while the upgrade is not yet finalized. bytes32 l2SystemContractsUpgradeTxHash; /// @notice The batch when the system contracts upgrade transaction was executed. /// @dev It is non-zero if the migration happens while the batch where the upgrade tx was present /// has not been finalized (executed) yet. uint256 l2SystemContractsUpgradeBatchNumber; /// @notice The hashes of the batches that are needed to keep the blockchain working. /// @dev The length of the array is equal to the `totalBatchesCommitted - totalBatchesExecuted + 1`, i.e. we need /// to store all the unexecuted batches' hashes + 1 latest executed one. bytes32[] batchHashes; /// @notice Commitment to the priority merkle tree. PriorityTreeCommitment priorityTree; /// @notice Whether a chain is a permanent rollup. bool isPermanentRollup; }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev The formal address of the initial program of the system: the bootloader address constant L2_BOOTLOADER_ADDRESS = address(0x8001); /// @dev The address of the known code storage system contract address constant L2_KNOWN_CODE_STORAGE_SYSTEM_CONTRACT_ADDR = address(0x8004); /// @dev The address of the L2 deployer system contract. address constant L2_DEPLOYER_SYSTEM_CONTRACT_ADDR = address(0x8006); /// @dev The special reserved L2 address. It is located in the system contracts space but doesn't have deployed /// bytecode. /// @dev The L2 deployer system contract allows changing bytecodes on any address if the `msg.sender` is this address. /// @dev So, whenever the governor wants to redeploy system contracts, it just initiates the L1 upgrade call deployer /// system contract /// via the L1 -> L2 transaction with `sender == L2_FORCE_DEPLOYER_ADDR`. For more details see the /// `diamond-initializers` contracts. address constant L2_FORCE_DEPLOYER_ADDR = address(0x8007); /// @dev The address of the special smart contract that can send arbitrary length message as an L2 log address constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = address(0x8008); /// @dev The address of the eth token system contract address constant L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR = address(0x800a); /// @dev The address of the context system contract address constant L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR = address(0x800b); /// @dev The address of the pubdata chunk publisher contract address constant L2_PUBDATA_CHUNK_PUBLISHER_ADDR = address(0x8011); /// @dev The address used to execute complex upgragedes, also used for the genesis upgrade address constant L2_COMPLEX_UPGRADER_ADDR = address(0x800f); /// @dev The address used to execute the genesis upgrade address constant L2_GENESIS_UPGRADE_ADDR = address(0x10001); /// @dev The address of the L2 bridge hub system contract, used to start L1->L2 transactions address constant L2_BRIDGEHUB_ADDR = address(0x10002); /// @dev the address of the l2 asset router. address constant L2_ASSET_ROUTER_ADDR = address(0x10003); /** * @author Matter Labs * @custom:security-contact [email protected] * @notice Smart contract for sending arbitrary length messages to L1 * @dev by default ZkSync can send fixed-length messages on L1. * A fixed length message has 4 parameters `senderAddress`, `isService`, `key`, `value`, * the first one is taken from the context, the other three are chosen by the sender. * @dev To send a variable-length message we use this trick: * - This system contract accepts an arbitrary length message and sends a fixed length message with * parameters `senderAddress == this`, `isService == true`, `key == msg.sender`, `value == keccak256(message)`. * - The contract on L1 accepts all sent messages and if the message came from this system contract * it requires that the preimage of `value` be provided. */ interface IL2Messenger { /// @notice Sends an arbitrary length message to L1. /// @param _message The variable length message to be sent to L1. /// @return Returns the keccak256 hashed value of the message. function sendToL1(bytes calldata _message) external returns (bytes32); } /// @dev An l2 system contract address, used in the assetId calculation for native assets. /// This is needed for automatic bridging, i.e. without deploying the AssetHandler contract, /// if the assetId can be calculated with this address then it is in fact an NTV asset address constant L2_NATIVE_TOKEN_VAULT_ADDR = address(0x10004); /// @dev the address of the l2 asset router. address constant L2_MESSAGE_ROOT_ADDR = address(0x10005); /// @dev the offset for the system contracts uint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15 /// @dev the address of the l2 messenger system contract IL2Messenger constant L2_MESSENGER = IL2Messenger(address(SYSTEM_CONTRACTS_OFFSET + 0x08)); /// @dev the address of the msg value system contract address constant MSG_VALUE_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x09);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0xa2ac02a0 error NotRelayedSender(address msgSender, address settlementLayerRelaySender); // 0xf306a770 error NotAssetRouter(address msgSender, address sharedBridge); // 0xff514c10 error ChainIdAlreadyPresent(); // 0x4bd4ae07 error ChainNotPresentInCTM(); // 0xfe919e28 error AssetIdAlreadyRegistered(); // 0xc630ef3c error CTMNotRegistered(); // 0x4c0f5001 error ChainIdNotRegistered(); // 0xb78dbaa7 error SecondBridgeAddressTooLow(address secondBridgeAddress, address minSecondBridgeAddress); // 0x472477e2 error NotInGatewayMode(); // 0x90c7cbf1 error SLNotWhitelisted(); // 0x48857c1d error IncorrectChainAssetId(bytes32 assetId, bytes32 assetIdFromChainId); // 0xc0ca9182 error NotCurrentSL(uint256 settlementLayerChainId, uint256 blockChainId); // 0xeab895aa error HyperchainNotRegistered(); // 0xf5e39c1f error IncorrectSender(address prevMsgSender, address chainAdmin); // 0x587df426 error AlreadyCurrentSL(uint256 blockChainId); // 0x65e8a019 error ChainExists(); // 0x913183d8 error MessageRootNotRegistered(); // 0x7f4316f3 error NoEthAllowed(); // 0x23295f0e error NotOwner(address sender, address owner); // 0x92626457 error WrongCounterPart(address addressOnCounterPart, address l2BridgehubAddress); // 0xecb34449 error NotL1(uint256 l1ChainId, uint256 blockChainId); // 0x527b87c7 error OnlyBridgehub(address msgSender, address bridgehub); // 0x73fe6c1b error OnlyChain(address msgSender, address zkChainAddress); // 0x693cd3dc error NotOwnerViaRouter(address msgSender, address originalCaller); // 0x5de72107 error ChainNotLegacy();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0x5ecf2d7a error AccessToFallbackDenied(address target, address invoker); // 0x3995f750 error AccessToFunctionDenied(address target, bytes4 selector, address invoker); // 0x6c167909 error OnlySelfAllowed(); // 0x52e22c98 error RestrictionWasNotPresent(address restriction); // 0xf126e113 error RestrictionWasAlreadyPresent(address restriction); // 0x3331e9c0 error CallNotAllowed(bytes call); // 0xf6fd7071 error RemovingPermanentRestriction(); // 0xfcb9b2e1 error UnallowedImplementation(bytes32 implementationHash); // 0x1ff9d522 error AddressAlreadyUsed(address addr); // 0x0dfb42bf error AddressAlreadySet(address addr); // 0x86bb51b8 error AddressHasNoCode(address); // 0x1f73225f error AddressMismatch(address expected, address supplied); // 0x5e85ae73 error AmountMustBeGreaterThanZero(); // 0xfde974f4 error AssetHandlerDoesNotExist(bytes32 assetId); // 0x1294e9e1 error AssetIdMismatch(bytes32 expected, bytes32 supplied); // 0xfe919e28 error AssetIdAlreadyRegistered(); // 0x0bfcef28 error AlreadyWhitelisted(address); // 0x04a0b7e9 error AssetIdNotSupported(bytes32 assetId); // 0x6ef9a972 error BaseTokenGasPriceDenominatorNotSet(); // 0x55ad3fd3 error BatchHashMismatch(bytes32 expected, bytes32 actual); // 0x2078a6a0 error BatchNotExecuted(uint256 batchNumber); // 0xbd4455ff error BatchNumberMismatch(uint256 expectedBatchNumber, uint256 providedBatchNumber); // 0x6cf12312 error BridgeHubAlreadyRegistered(); // 0xdb538614 error BridgeMintNotImplemented(); // 0xe85392f9 error CanOnlyProcessOneBatch(); // 0x00c6ead2 error CantExecuteUnprovenBatches(); // 0xe18cb383 error CantRevertExecutedBatch(); // 0x24591d89 error ChainIdAlreadyExists(); // 0x717a1656 error ChainIdCantBeCurrentChain(); // 0xa179f8c9 error ChainIdMismatch(); // 0x23f3c357 error ChainIdNotRegistered(uint256 chainId); // 0x8f620a06 error ChainIdTooBig(); // 0xf7a01e4d error DelegateCallFailed(bytes returnData); // 0x0a8ed92c error DenominatorIsZero(); // 0xb4f54111 error DeployFailed(); // 0x138ee1a3 error DeployingBridgedTokenForNativeToken(); // 0xc7c9660f error DepositDoesNotExist(); // 0xad2fa98e error DepositExists(); // 0x0e7ee319 error DiamondAlreadyFrozen(); // 0xa7151b9a error DiamondNotFrozen(); // 0x7138356f error EmptyAddress(); // 0x2d4d012f error EmptyAssetId(); // 0x1c25715b error EmptyBytes32(); // 0x95b66fe9 error EmptyDeposit(); // 0x627e0872 error ETHDepositNotSupported(); // 0xac4a3f98 error FacetExists(bytes4 selector, address); // 0xc91cf3b1 error GasPerPubdataMismatch(); // 0x6d4a7df8 error GenesisBatchCommitmentZero(); // 0x7940c83f error GenesisBatchHashZero(); // 0xb4fc6835 error GenesisIndexStorageZero(); // 0x3a1a8589 error GenesisUpgradeZero(); // 0xd356e6ba error HashedLogIsDefault(); // 0x0b08d5be error HashMismatch(bytes32 expected, bytes32 actual); // 0x601b6882 error ZKChainLimitReached(); // 0xdd381a4c error IncorrectBridgeHubAddress(address bridgehub); // 0x826fb11e error InsufficientChainBalance(); // 0xcbd9d2e0 error InvalidCaller(address); // 0x4fbe5dba error InvalidDelay(); // 0xc1780bd6 error InvalidLogSender(address sender, uint256 logKey); // 0xd8e9405c error InvalidNumberOfBlobs(uint256 expected, uint256 numCommitments, uint256 numHashes); // 0x09bde339 error InvalidProof(); // 0x5428eae7 error InvalidProtocolVersion(); // 0x5513177c error InvalidPubdataHash(bytes32 expectedHash, bytes32 provided); // 0x6f1cf752 error InvalidPubdataPricingMode(); // 0x12ba286f error InvalidSelector(bytes4 func); // 0x5cb29523 error InvalidTxType(uint256 txType); // 0x0214acb6 error InvalidUpgradeTxn(UpgradeTxVerifyParam); // 0xfb5c22e6 error L2TimestampTooBig(); // 0xd2c011d6 error L2UpgradeNonceNotEqualToNewProtocolVersion(uint256 nonce, uint256 protocolVersion); // 0x97e1359e error L2WithdrawalMessageWrongLength(uint256 messageLen); // 0xe37d2c02 error LengthIsNotDivisibleBy32(uint256 length); // 0x1b6825bb error LogAlreadyProcessed(uint8); // 0xcea34703 error MalformedBytecode(BytecodeError); // 0x9bb54c35 error MerkleIndexOutOfBounds(); // 0x8e23ac1a error MerklePathEmpty(); // 0x1c500385 error MerklePathOutOfBounds(); // 0x3312a450 error MigrationPaused(); // 0xfa44b527 error MissingSystemLogs(uint256 expected, uint256 actual); // 0x4a094431 error MsgValueMismatch(uint256 expectedMsgValue, uint256 providedMsgValue); // 0xb385a3da error MsgValueTooLow(uint256 required, uint256 provided); // 0x72ea85ad error NewProtocolMajorVersionNotZero(); // 0x79cc2d22 error NoCallsProvided(); // 0xa6fef710 error NoFunctionsForDiamondCut(); // 0xcab098d8 error NoFundsTransferred(); // 0xc21b1ab7 error NonEmptyCalldata(); // 0x536ec84b error NonEmptyMsgValue(); // 0xd018e08e error NonIncreasingTimestamp(); // 0x0105f9c0 error NonSequentialBatch(); // 0x0ac76f01 error NonSequentialVersion(); // 0xdd629f86 error NotEnoughGas(); // 0xdd7e3621 error NotInitializedReentrancyGuard(); // 0xdf17e316 error NotWhitelisted(address); // 0xf3ed9dfa error OnlyEraSupported(); // 0x1a21feed error OperationExists(); // 0xeda2fbb1 error OperationMustBePending(); // 0xe1c1ff37 error OperationMustBeReady(); // 0xb926450e error OriginChainIdNotFound(); // 0xd7f50a9d error PatchCantSetUpgradeTxn(); // 0x962fd7d0 error PatchUpgradeCantSetBootloader(); // 0x559cc34e error PatchUpgradeCantSetDefaultAccount(); // 0x9b48e060 error PreviousOperationNotExecuted(); // 0x5c598b60 error PreviousProtocolMajorVersionNotZero(); // 0xa0f47245 error PreviousUpgradeNotCleaned(); // 0x101ba748 error PreviousUpgradeNotFinalized(bytes32 txHash); // 0xd5a99014 error PriorityOperationsRollingHashMismatch(); // 0x1a4d284a error PriorityTxPubdataExceedsMaxPubDataPerBatch(); // 0xa461f651 error ProtocolIdMismatch(uint256 expectedProtocolVersion, uint256 providedProtocolId); // 0x64f94ec2 error ProtocolIdNotGreater(); // 0xd328c12a error ProtocolVersionMinorDeltaTooBig(uint256 limit, uint256 proposed); // 0x88d7b498 error ProtocolVersionTooSmall(); // 0x53dee67b error PubdataCommitmentsEmpty(); // 0x959f26fb error PubdataGreaterThanLimit(uint256 limit, uint256 length); // 0x63c36549 error QueueIsEmpty(); // 0xab143c06 error Reentrancy(); // 0x667d17de error RemoveFunctionFacetAddressNotZero(address facet); // 0xa2d4b16c error RemoveFunctionFacetAddressZero(); // 0x3580370c error ReplaceFunctionFacetAddressZero(); // 0x9a67c1cb error RevertedBatchNotAfterNewLastBatch(); // 0xd3b6535b error SelectorsMustAllHaveSameFreezability(); // 0xd7a6b5e6 error SharedBridgeValueNotSet(SharedBridgeKey); // 0x856d5b77 error SharedBridgeNotSet(); // 0xdf3a8fdd error SlotOccupied(); // 0xec273439 error CTMAlreadyRegistered(); // 0xc630ef3c error CTMNotRegistered(); // 0xae43b424 error SystemLogsSizeTooBig(); // 0x08753982 error TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp); // 0x2d50c33b error TimestampError(); // 0x06439c6b error TokenNotSupported(address token); // 0x23830e28 error TokensWithFeesNotSupported(); // 0x76da24b9 error TooManyFactoryDeps(); // 0xf0b4e88f error TooMuchGas(); // 0x00c5a6a9 error TransactionNotAllowed(); // 0x4c991078 error TxHashMismatch(); // 0x2e311df8 error TxnBodyGasLimitNotEnoughGas(); // 0x8e4a23d6 error Unauthorized(address caller); // 0xe52478c7 error UndefinedDiamondCutAction(); // 0x6aa39880 error UnexpectedSystemLog(uint256 logKey); // 0xf093c2e5 error UpgradeBatchNumberIsNotZero(); // 0x084a1449 error UnsupportedEncodingVersion(); // 0x47b3b145 error ValidateTxnNotEnoughGas(); // 0x626ade30 error ValueMismatch(uint256 expected, uint256 actual); // 0xe1022469 error VerifiedBatchesExceedsCommittedBatches(); // 0xae899454 error WithdrawalAlreadyFinalized(); // 0x750b219c error WithdrawFailed(); // 0x15e8e429 error WrongMagicValue(uint256 expectedMagicValue, uint256 providedMagicValue); // 0xd92e233d error ZeroAddress(); // 0xc84885d4 error ZeroChainId(); // 0x99d8fec9 error EmptyData(); // 0xf3dd1b9c error UnsupportedCommitBatchEncoding(uint8 version); // 0xf338f830 error UnsupportedProofBatchEncoding(uint8 version); // 0x14d2ed8a error UnsupportedExecuteBatchEncoding(uint8 version); // 0xd7d93e1f error IncorrectBatchBounds( uint256 processFromExpected, uint256 processToExpected, uint256 processFromProvided, uint256 processToProvided ); // 0x64107968 error AssetHandlerNotRegistered(bytes32 assetId); // 0x64846fe4 error NotARestriction(address addr); // 0xfa5cd00f error NotAllowed(address addr); // 0xccdd18d2 error BytecodeAlreadyPublished(bytes32 bytecodeHash); // 0x25d8333c error CallerNotTimerAdmin(); // 0x907f8e51 error DeadlineNotYetPassed(); // 0x6eef58d1 error NewDeadlineNotGreaterThanCurrent(); // 0x8b7e144a error NewDeadlineExceedsMaxDeadline(); // 0x2a5989a0 error AlreadyPermanentRollup(); // 0x92daded2 error InvalidDAForPermanentRollup(); // 0xd0266e26 error NotSettlementLayer(); // 0x7a4902ad error TimerAlreadyStarted(); // 0x09aa9830 error MerklePathLengthMismatch(uint256 pathLength, uint256 expectedLength); // 0xc33e6128 error MerkleNothingToProve(); // 0xafbb7a4e error MerkleIndexOrHeightMismatch(); // 0x1b582fcf error MerkleWrongIndex(uint256 index, uint256 maxNodeNumber); // 0x485cfcaa error MerkleWrongLength(uint256 newLeavesLength, uint256 leafNumber); // 0xce63ce17 error NoCTMForAssetId(bytes32 assetId); // 0x02181a13 error SettlementLayersMustSettleOnL1(); // 0x1850b46b error TokenNotLegacy(); // 0x1929b7de error IncorrectTokenAddressFromNTV(bytes32 assetId, address tokenAddress); // 0x48c5fa28 error InvalidProofLengthForFinalNode(); // 0x7acd7817 error TokenIsNotLegacy(); // 0xfade089a error LegacyEncodingUsedForNonL1Token(); // 0xa51fa558 error TokenIsLegacy(); // 0x29963361 error LegacyBridgeUsesNonNativeToken(); // 0x11832de8 error AssetRouterAllowanceNotZero(); // 0xaa5f6180 error BurningNativeWETHNotSupported(); // 0xb20b58ce error NoLegacySharedBridge(); // 0x8e3ce3cb error TooHighDeploymentNonce(); // 0x78d2ed02 error ChainAlreadyLive(); // 0x4e98b356 error MigrationsNotPaused(); // 0xf20c5c2a error WrappedBaseTokenAlreadyRegistered(); // 0xde4c0b96 error InvalidNTVBurnData(); // 0xbe7193d4 error InvalidSystemLogsLength(); // 0x8efef97a error LegacyBridgeNotSet(); // 0x767eed08 error LegacyMethodForNonL1Token(); enum SharedBridgeKey { PostUpgradeFirstBatch, LegacyBridgeFirstBatch, LegacyBridgeLastDepositBatch, LegacyBridgeLastDepositTxn } enum BytecodeError { Version, NumberOfWords, Length, WordsMustBeOdd } enum UpgradeTxVerifyParam { From, To, Paymaster, Value, MaxFeePerGas, MaxPriorityFeePerGas, Reserved0, Reserved1, Reserved2, Reserved3, Signature, PaymasterInput, ReservedDynamic }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @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[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev The enum that represents the transaction execution status /// @param Failure The transaction execution failed /// @param Success The transaction execution succeeded enum TxStatus { Failure, Success } /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter /// All other values are not used but are reserved for the future /// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address. /// This field is required formally but does not have any special meaning /// @param txNumberInBatch The L2 transaction number in a Batch, in which the log was sent /// @param sender The L2 address which sent the log /// @param key The 32 bytes of information that was sent in the log /// @param value The 32 bytes of information that was sent in the log // Both `key` and `value` are arbitrary 32-bytes selected by the log sender struct L2Log { uint8 l2ShardId; bool isService; uint16 txNumberInBatch; address sender; bytes32 key; bytes32 value; } /// @dev An arbitrary length message passed from L2 /// @notice Under the hood it is `L2Log` sent from the special system L2 contract /// @param txNumberInBatch The L2 transaction number in a Batch, in which the message was sent /// @param sender The address of the L2 account from which the message was passed /// @param data An arbitrary length message struct L2Message { uint16 txNumberInBatch; address sender; bytes data; } /// @dev Internal structure that contains the parameters for the writePriorityOp /// internal function. /// @param txId The id of the priority transaction. /// @param l2GasPrice The gas price for the l2 priority operation. /// @param expirationTimestamp The timestamp by which the priority operation must be processed by the operator. /// @param request The external calldata request for the priority operation. struct WritePriorityOpParams { uint256 txId; uint256 l2GasPrice; uint64 expirationTimestamp; BridgehubL2TransactionRequest request; } /// @dev Structure that includes all fields of the L2 transaction /// @dev The hash of this structure is the "canonical L2 transaction hash" and can /// be used as a unique identifier of a tx /// @param txType The tx type number, depending on which the L2 transaction can be /// interpreted differently /// @param from The sender's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param to The recipient's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param gasLimit The L2 gas limit for L2 transaction. Analog to the `gasLimit` on an /// L1 transactions /// @param gasPerPubdataByteLimit Maximum number of L2 gas that will cost one byte of pubdata /// (every piece of data that will be stored on L1 as calldata) /// @param maxFeePerGas The absolute maximum sender willing to pay per unit of L2 gas to get /// the transaction included in a Batch. Analog to the EIP-1559 `maxFeePerGas` on an L1 transactions /// @param maxPriorityFeePerGas The additional fee that is paid directly to the validator /// to incentivize them to include the transaction in a Batch. Analog to the EIP-1559 /// `maxPriorityFeePerGas` on an L1 transactions /// @param paymaster The address of the EIP-4337 paymaster, that will pay fees for the /// transaction. `uint256` type for possible address format changes and maintaining backward compatibility /// @param nonce The nonce of the transaction. For L1->L2 transactions it is the priority /// operation Id /// @param value The value to pass with the transaction /// @param reserved The fixed-length fields for usage in a future extension of transaction /// formats /// @param data The calldata that is transmitted for the transaction call /// @param signature An abstract set of bytes that are used for transaction authorization /// @param factoryDeps The set of L2 bytecode hashes whose preimages were shown on L1 /// @param paymasterInput The arbitrary-length data that is used as a calldata to the paymaster pre-call /// @param reservedDynamic The arbitrary-length field for usage in a future extension of transaction formats struct L2CanonicalTransaction { uint256 txType; uint256 from; uint256 to; uint256 gasLimit; uint256 gasPerPubdataByteLimit; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; uint256 paymaster; uint256 nonce; uint256 value; // In the future, we might want to add some // new fields to the struct. The `txData` struct // is to be passed to account and any changes to its structure // would mean a breaking change to these accounts. To prevent this, // we should keep some fields as "reserved" // It is also recommended that their length is fixed, since // it would allow easier proof integration (in case we will need // some special circuit for preprocessing transactions) uint256[4] reserved; bytes data; bytes signature; uint256[] factoryDeps; bytes paymasterInput; // Reserved dynamic type for the future use-case. Using it should be avoided, // But it is still here, just in case we want to enable some additional functionality bytes reservedDynamic; } /// @param sender The sender's address. /// @param contractAddressL2 The address of the contract on L2 to call. /// @param valueToMint The amount of base token that should be minted on L2 as the result of this transaction. /// @param l2Value The msg.value of the L2 transaction. /// @param l2Calldata The calldata for the L2 transaction. /// @param l2GasLimit The limit of the L2 gas for the L2 transaction /// @param l2GasPerPubdataByteLimit The price for a single pubdata byte in L2 gas. /// @param factoryDeps The array of L2 bytecodes that the tx depends on. /// @param refundRecipient The recipient of the refund for the transaction on L2. If the transaction fails, then /// this address will receive the `l2Value`. // solhint-disable-next-line gas-struct-packing struct BridgehubL2TransactionRequest { address sender; address contractL2; uint256 mintValue; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title L1 Asset Handler contract interface /// @author Matter Labs /// @custom:security-contact [email protected] /// @notice Used for any asset handler and called by the L1AssetRouter interface IL1AssetHandler { /// @param _chainId the chainId that the message will be sent to /// @param _assetId the assetId of the asset being bridged /// @param _depositSender the address of the entity that initiated the deposit. /// @param _data the actual data specified for the function function bridgeRecoverFailedTransfer( uint256 _chainId, bytes32 _assetId, address _depositSender, bytes calldata _data ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IBridgehub} from "./IBridgehub.sol"; /** * @author Matter Labs * @notice MessageRoot contract is responsible for storing and aggregating the roots of the batches from different chains into the MessageRoot. * @custom:security-contact [email protected] */ interface IMessageRoot { function BRIDGE_HUB() external view returns (IBridgehub); function addNewChain(uint256 _chainId) external; function addChainBatchRoot(uint256 _chainId, uint256 _batchNumber, bytes32 _chainBatchRoot) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title Asset Handler contract interface /// @author Matter Labs /// @custom:security-contact [email protected] /// @notice Used for any asset handler and called by the AssetRouter interface IAssetHandler { /// @dev Emitted when a token is minted event BridgeMint(uint256 indexed chainId, bytes32 indexed assetId, address receiver, uint256 amount); /// @dev Emitted when a token is burned event BridgeBurn( uint256 indexed chainId, bytes32 indexed assetId, address indexed sender, address receiver, uint256 amount ); /// @param _chainId the chainId that the message is from /// @param _assetId the assetId of the asset being bridged /// @param _data the actual data specified for the function /// @dev Note, that while payable, this function will only receive base token on L2 chains, /// while L1 the provided msg.value is always 0. However, this may change in the future, /// so if your AssetHandler implementation relies on it, it is better to explicitly check it. function bridgeMint(uint256 _chainId, bytes32 _assetId, bytes calldata _data) external payable; /// @notice Burns bridged tokens and returns the calldata for L2 <-> L1 message. /// @dev In case of native token vault _data is the tuple of _depositAmount and _l2Receiver. /// @param _chainId the chainId that the message will be sent to /// @param _msgValue the msg.value of the L2 transaction. For now it is always 0. /// @param _assetId the assetId of the asset being bridged /// @param _originalCaller the original caller of the /// @param _data the actual data specified for the function /// @return _bridgeMintData The calldata used by counterpart asset handler to unlock tokens for recipient. function bridgeBurn( uint256 _chainId, uint256 _msgValue, bytes32 _assetId, address _originalCaller, bytes calldata _data ) external payable returns (bytes memory _bridgeMintData); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @author Matter Labs /// @custom:security-contact [email protected] interface IL1AssetDeploymentTracker { function bridgeCheckCounterpartAddress( uint256 _chainId, bytes32 _assetId, address _originalCaller, address _assetHandlerAddressOnCounterpart ) external view; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @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[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "@ensdomains/=node_modules/@ensdomains/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "murky/=lib/murky/src/", "foundry-test/=test/foundry/", "l2-contracts/=../l2-contracts/contracts/", "@openzeppelin/contracts-v4/=lib/openzeppelin-contracts-v4/contracts/", "@openzeppelin/contracts-upgradeable-v4/=lib/openzeppelin-contracts-upgradeable-v4/contracts/", "@openzeppelin/=node_modules/@openzeppelin/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable-v4/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable-v4/=lib/openzeppelin-contracts-upgradeable-v4/", "openzeppelin-contracts-v4/=lib/openzeppelin-contracts-v4/", "openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IBridgehub","name":"_bridgehub","type":"address"},{"internalType":"contract IAssetRouterBase","name":"_l1AssetRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CTMNotRegistered","type":"error"},{"inputs":[],"name":"NoEthAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"originalCaller","type":"address"}],"name":"NotOwnerViaRouter","type":"error"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"address","name":"bridgehub","type":"address"}],"name":"OnlyBridgehub","type":"error"},{"inputs":[],"name":"UnsupportedEncodingVersion","type":"error"},{"inputs":[{"internalType":"address","name":"addressOnCounterPart","type":"address"},{"internalType":"address","name":"l2BridgehubAddress","type":"address"}],"name":"WrongCounterPart","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"BRIDGE_HUB","outputs":[{"internalType":"contract IBridgehub","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_ASSET_ROUTER","outputs":[{"internalType":"contract IAssetRouterBase","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"_originalCaller","type":"address"},{"internalType":"address","name":"_assetHandlerAddressOnCounterpart","type":"address"}],"name":"bridgeCheckCounterpartAddress","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes32","name":"_txDataHash","type":"bytes32"},{"internalType":"bytes32","name":"_txHash","type":"bytes32"}],"name":"bridgehubConfirmL2Transaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_originalCaller","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"bridgehubDeposit","outputs":[{"components":[{"internalType":"bytes32","name":"magicValue","type":"bytes32"},{"internalType":"address","name":"l2Contract","type":"address"},{"internalType":"bytes","name":"l2Calldata","type":"bytes"},{"internalType":"bytes[]","name":"factoryDeps","type":"bytes[]"},{"internalType":"bytes32","name":"txDataHash","type":"bytes32"}],"internalType":"struct L2TransactionRequestTwoBridgesInner","name":"request","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1CTM","type":"address"}],"name":"calculateAssetId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ctmAddress","type":"address"}],"name":"registerCTMAssetOnL1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405234801561000f575f80fd5b5060405161100a38038061100a83398101604081905261002e91610120565b61003661004d565b6001600160a01b039182166080521660a052610158565b5f54610100900460ff16156100b85760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614610107575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811461011d575f80fd5b50565b5f8060408385031215610131575f80fd5b825161013c81610109565b602084015190925061014d81610109565b809150509250929050565b60805160a051610e536101b75f395f8181610272015281816103c401526105b801525f818160f5015281816102f70152818161039c0152818161043f015281816105380152818161057a015281816107a601526107e80152610e535ff3fe6080604052600436106100bf575f3560e01c80639cc395d01161007c578063ca408c2311610057578063ca408c2314610241578063cdf2543014610261578063e30c397814610294578063f2fde38b146102b1575f80fd5b80639cc395d014610198578063b68c104a146101b7578063c4d66de814610222575f80fd5b80632f9db630146100c35780635d4edca7146100e4578063715018a61461013457806379ba5097146101485780638da5cb5b1461015c5780638eb7db5714610179575b5f80fd5b3480156100ce575f80fd5b506100e26100dd366004610b5a565b6102d0565b005b3480156100ef575f80fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013f575f80fd5b506100e261049b565b348015610153575f80fd5b506100e26104ae565b348015610167575f80fd5b506033546001600160a01b0316610117565b348015610184575f80fd5b506100e2610193366004610b7c565b61052d565b3480156101a3575f80fd5b506100e26101b2366004610ba5565b6105ac565b3480156101c2575f80fd5b506102146101d1366004610b5a565b6040805146602082015230918101919091526001600160a01b03821660608201525f90608001604051602081830303815290604052805190602001209050919050565b60405190815260200161012b565b34801561022d575f80fd5b506100e261023c366004610b5a565b610662565b61025461024f366004610bec565b61076f565b60405161012b9190610cbd565b34801561026c575f80fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b34801561029f575f80fd5b506065546001600160a01b0316610117565b3480156102bc575f80fd5b506100e26102cb366004610b5a565b610908565b6102d8610979565b604051635c9e49b360e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b93c936690602401602060405180830381865afa15801561033c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103609190610d67565b61037d5760405163318c3bcf60e21b815260040160405180910390fd5b60405163548a5a3360e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063548a5a33906044015f604051808303815f87803b158015610405575f80fd5b505af1158015610417573d5f803e3d5ffd5b5050604051632dbcf55f60e01b81526001600160a01b038481166004830181905260248301527f0000000000000000000000000000000000000000000000000000000000000000169250632dbcf55f91506044015f604051808303815f87803b158015610482575f80fd5b505af1158015610494573d5f803e3d5ffd5b5050505050565b6104a3610979565b6104ac5f6109d3565b565b60655433906001600160a01b031681146105215760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61052a816109d3565b50565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105a75760405163527b87c760e01b81523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610518565b505050565b81336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415806105f357506033546001600160a01b03828116911614155b1561062257604051631a4f34f760e21b81523360048201526001600160a01b0382166024820152604401610518565b6001600160a01b038216620100021461049457604051639262645760e01b81526001600160a01b0383166004820152620100026024820152604401610518565b5f54610100900460ff161580801561068057505f54600160ff909116105b806106995750303b15801561069957505f5460ff166001145b6106fc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610518565b5f805460ff19166001179055801561071d575f805461ff0019166101001790555b610726826109d3565b801561076b575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6040805160a0810182525f808252602082018190526060928201839052828201929092526080810191909152336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108155760405163527b87c760e01b81523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610518565b341561083457604051637f4316f360e01b815260040160405180910390fd5b6033546001600160a01b03868116911614610888578461085c6033546001600160a01b031690565b604051631194af8760e11b81526001600160a01b03928316600482015291166024820152604401610518565b5f83835f81811061089b5761089b610d86565b909101356001600160f81b031916915050600160f81b81146108d05760405163084a144960e01b815260040160405180910390fd5b5f806108df8560018189610d9a565b8101906108ec9190610dc1565b915091506108fb8983836109ec565b9998505050505050505050565b610910610979565b606580546001600160a01b0383166001600160a01b031990911681179091556109416033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146104ac5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610518565b606580546001600160a01b031916905561052a81610af5565b6040805160a0810182525f8082526020820181905260609282018390528282019290925260808101919091526040516001600160a01b038481166024830152831660448201525f9060640160408051601f198184030181529181526020820180516001600160e01b0316632dbcf55f60e01b179052805160a0810190915290915080610a9960017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e610df8565b8152620100026020820152604081018390526060015f604051908082528060200260200182016040528015610ae257816020015b6060815260200190600190039081610acd5790505b5081525f60209091015295945050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b038116811461052a575f80fd5b5f60208284031215610b6a575f80fd5b8135610b7581610b46565b9392505050565b5f805f60608486031215610b8e575f80fd5b505081359360208301359350604090920135919050565b5f805f8060808587031215610bb8575f80fd5b84359350602085013592506040850135610bd181610b46565b91506060850135610be181610b46565b939692955090935050565b5f805f805f60808688031215610c00575f80fd5b853594506020860135610c1281610b46565b935060408601359250606086013567ffffffffffffffff80821115610c35575f80fd5b818801915088601f830112610c48575f80fd5b813581811115610c56575f80fd5b896020828501011115610c67575f80fd5b9699959850939650602001949392505050565b5f81518084525f5b81811015610c9e57602081850181015186830182015201610c82565b505f602082860101526020601f19601f83011685010191505092915050565b5f602080835283518184015260018060a01b0381850151166040840152604084015160a06060850152610cf360c0850182610c7a565b6060860151601f198683038101608088015281518084529293509084019184840190600581901b850186015f5b82811015610d4c5784878303018452610d3a828751610c7a565b95880195938801939150600101610d20565b5060808a015160a08a01528097505050505050505092915050565b5f60208284031215610d77575f80fd5b81518015158114610b75575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8085851115610da8575f80fd5b83861115610db4575f80fd5b5050820193919092039150565b5f8060408385031215610dd2575f80fd5b8235610ddd81610b46565b91506020830135610ded81610b46565b809150509250929050565b81810381811115610e1757634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220876c7ca01a5a44ee291bf115fdb24820f8178148027b2b06cc592f227f0ac6b664736f6c63430008180033000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb52130000000000000000000000008829ad80e425c646dab305381ff105169feece56
Deployed Bytecode
0x6080604052600436106100bf575f3560e01c80639cc395d01161007c578063ca408c2311610057578063ca408c2314610241578063cdf2543014610261578063e30c397814610294578063f2fde38b146102b1575f80fd5b80639cc395d014610198578063b68c104a146101b7578063c4d66de814610222575f80fd5b80632f9db630146100c35780635d4edca7146100e4578063715018a61461013457806379ba5097146101485780638da5cb5b1461015c5780638eb7db5714610179575b5f80fd5b3480156100ce575f80fd5b506100e26100dd366004610b5a565b6102d0565b005b3480156100ef575f80fd5b506101177f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521381565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013f575f80fd5b506100e261049b565b348015610153575f80fd5b506100e26104ae565b348015610167575f80fd5b506033546001600160a01b0316610117565b348015610184575f80fd5b506100e2610193366004610b7c565b61052d565b3480156101a3575f80fd5b506100e26101b2366004610ba5565b6105ac565b3480156101c2575f80fd5b506102146101d1366004610b5a565b6040805146602082015230918101919091526001600160a01b03821660608201525f90608001604051602081830303815290604052805190602001209050919050565b60405190815260200161012b565b34801561022d575f80fd5b506100e261023c366004610b5a565b610662565b61025461024f366004610bec565b61076f565b60405161012b9190610cbd565b34801561026c575f80fd5b506101177f0000000000000000000000008829ad80e425c646dab305381ff105169feece5681565b34801561029f575f80fd5b506065546001600160a01b0316610117565b3480156102bc575f80fd5b506100e26102cb366004610b5a565b610908565b6102d8610979565b604051635c9e49b360e11b81526001600160a01b0382811660048301527f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213169063b93c936690602401602060405180830381865afa15801561033c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103609190610d67565b61037d5760405163318c3bcf60e21b815260040160405180910390fd5b60405163548a5a3360e01b81526001600160a01b0382811660048301527f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213811660248301527f0000000000000000000000008829ad80e425c646dab305381ff105169feece56169063548a5a33906044015f604051808303815f87803b158015610405575f80fd5b505af1158015610417573d5f803e3d5ffd5b5050604051632dbcf55f60e01b81526001600160a01b038481166004830181905260248301527f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213169250632dbcf55f91506044015f604051808303815f87803b158015610482575f80fd5b505af1158015610494573d5f803e3d5ffd5b5050505050565b6104a3610979565b6104ac5f6109d3565b565b60655433906001600160a01b031681146105215760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61052a816109d3565b50565b336001600160a01b037f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521316146105a75760405163527b87c760e01b81523360048201526001600160a01b037f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213166024820152604401610518565b505050565b81336001600160a01b037f0000000000000000000000008829ad80e425c646dab305381ff105169feece56161415806105f357506033546001600160a01b03828116911614155b1561062257604051631a4f34f760e21b81523360048201526001600160a01b0382166024820152604401610518565b6001600160a01b038216620100021461049457604051639262645760e01b81526001600160a01b0383166004820152620100026024820152604401610518565b5f54610100900460ff161580801561068057505f54600160ff909116105b806106995750303b15801561069957505f5460ff166001145b6106fc5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610518565b5f805460ff19166001179055801561071d575f805461ff0019166101001790555b610726826109d3565b801561076b575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6040805160a0810182525f808252602082018190526060928201839052828201929092526080810191909152336001600160a01b037f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521316146108155760405163527b87c760e01b81523360048201526001600160a01b037f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213166024820152604401610518565b341561083457604051637f4316f360e01b815260040160405180910390fd5b6033546001600160a01b03868116911614610888578461085c6033546001600160a01b031690565b604051631194af8760e11b81526001600160a01b03928316600482015291166024820152604401610518565b5f83835f81811061089b5761089b610d86565b909101356001600160f81b031916915050600160f81b81146108d05760405163084a144960e01b815260040160405180910390fd5b5f806108df8560018189610d9a565b8101906108ec9190610dc1565b915091506108fb8983836109ec565b9998505050505050505050565b610910610979565b606580546001600160a01b0383166001600160a01b031990911681179091556109416033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146104ac5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610518565b606580546001600160a01b031916905561052a81610af5565b6040805160a0810182525f8082526020820181905260609282018390528282019290925260808101919091526040516001600160a01b038481166024830152831660448201525f9060640160408051601f198184030181529181526020820180516001600160e01b0316632dbcf55f60e01b179052805160a0810190915290915080610a9960017fa175e001c0e5684bc26302c2f9a55aec9f3936fe2aef558034003ef4da7fc77e610df8565b8152620100026020820152604081018390526060015f604051908082528060200260200182016040528015610ae257816020015b6060815260200190600190039081610acd5790505b5081525f60209091015295945050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b038116811461052a575f80fd5b5f60208284031215610b6a575f80fd5b8135610b7581610b46565b9392505050565b5f805f60608486031215610b8e575f80fd5b505081359360208301359350604090920135919050565b5f805f8060808587031215610bb8575f80fd5b84359350602085013592506040850135610bd181610b46565b91506060850135610be181610b46565b939692955090935050565b5f805f805f60808688031215610c00575f80fd5b853594506020860135610c1281610b46565b935060408601359250606086013567ffffffffffffffff80821115610c35575f80fd5b818801915088601f830112610c48575f80fd5b813581811115610c56575f80fd5b896020828501011115610c67575f80fd5b9699959850939650602001949392505050565b5f81518084525f5b81811015610c9e57602081850181015186830182015201610c82565b505f602082860101526020601f19601f83011685010191505092915050565b5f602080835283518184015260018060a01b0381850151166040840152604084015160a06060850152610cf360c0850182610c7a565b6060860151601f198683038101608088015281518084529293509084019184840190600581901b850186015f5b82811015610d4c5784878303018452610d3a828751610c7a565b95880195938801939150600101610d20565b5060808a015160a08a01528097505050505050505092915050565b5f60208284031215610d77575f80fd5b81518015158114610b75575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8085851115610da8575f80fd5b83861115610db4575f80fd5b5050820193919092039150565b5f8060408385031215610dd2575f80fd5b8235610ddd81610b46565b91506020830135610ded81610b46565b809150509250929050565b81810381811115610e1757634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220876c7ca01a5a44ee291bf115fdb24820f8178148027b2b06cc592f227f0ac6b664736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb52130000000000000000000000008829ad80e425c646dab305381ff105169feece56
-----Decoded View---------------
Arg [0] : _bridgehub (address): 0x303a465B659cBB0ab36eE643eA362c509EEb5213
Arg [1] : _l1AssetRouter (address): 0x8829AD80E425C646DAB305381ff105169FeEcE56
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213
Arg [1] : 0000000000000000000000008829ad80e425c646dab305381ff105169feece56
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.