Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
Amount
|
||
|---|---|---|---|---|---|---|---|
| 0x60a06040 | 8975423 | 121 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
ChainTypeManager
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 9999999 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {EnumerableMap} from "@openzeppelin/contracts-v4/utils/structs/EnumerableMap.sol";
import {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol";
import {Diamond} from "./libraries/Diamond.sol";
import {DiamondProxy} from "./chain-deps/DiamondProxy.sol";
import {IAdmin} from "./chain-interfaces/IAdmin.sol";
import {IDiamondInit} from "./chain-interfaces/IDiamondInit.sol";
import {IExecutor} from "./chain-interfaces/IExecutor.sol";
import {ChainCreationParams, ChainTypeManagerInitializeData, IChainTypeManager} from "./IChainTypeManager.sol";
import {IZKChain} from "./chain-interfaces/IZKChain.sol";
import {FeeParams} from "./chain-deps/ZKChainStorage.sol";
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol";
import {DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY_STRING_KECCAK, L2_TO_L1_LOG_SERIALIZE_SIZE} from "../common/Config.sol";
import {AdminZero, InitialForceDeploymentMismatch, OutdatedProtocolVersion} from "./L1StateTransitionErrors.sol";
import {ChainAlreadyLive, GenesisBatchCommitmentZero, GenesisBatchHashZero, GenesisIndexStorageZero, GenesisUpgradeZero, HashMismatch, MigrationsNotPaused, Unauthorized, ZeroAddress} from "../common/L1ContractErrors.sol";
import {SemVer} from "../common/libraries/SemVer.sol";
import {IBridgehub} from "../bridgehub/IBridgehub.sol";
import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
/// @title Chain Type Manager contract
/// @author Matter Labs
/// @custom:security-contact [email protected]
contract ChainTypeManager is IChainTypeManager, ReentrancyGuard, Ownable2StepUpgradeable {
using EnumerableMap for EnumerableMap.UintToAddressMap;
/// @notice Address of the bridgehub
address public immutable BRIDGE_HUB;
/// @notice The map from chainId => zkChain contract
EnumerableMap.UintToAddressMap internal __DEPRECATED_zkChainMap;
/// @dev The batch zero hash, calculated at initialization
bytes32 public storedBatchZero;
/// @dev The stored cutData for diamond cut
bytes32 public initialCutHash;
/// @dev The l1GenesisUpgrade contract address, used to set chainId
address public l1GenesisUpgrade;
/// @dev The current packed protocolVersion. To access human-readable version, use `getSemverProtocolVersion` function.
uint256 public protocolVersion;
/// @dev The timestamp when protocolVersion can be last used
mapping(uint256 _protocolVersion => uint256) public protocolVersionDeadline;
/// @dev The validatorTimelock contract address.
/// @dev Note, that address contains validator timelock for pre-v29 protocol versions. It is deprecated and will be removed in the future.
address internal __DEPRECATED_validatorTimelock;
/// @dev The stored cutData for upgrade diamond cut. protocolVersion => cutHash
mapping(uint256 protocolVersion => bytes32 cutHash) public upgradeCutHash;
/// @dev The address used to manage non critical updates
address public admin;
/// @dev The address to accept the admin role
address private pendingAdmin;
/// @dev The initial force deployment hash
bytes32 public initialForceDeploymentHash;
/// @dev The contract, that notifies server about l1 changes
address public serverNotifierAddress;
/// @dev The address of the post-V29 upgradeable validatorTimelock.
/// @dev Both validatorTimelock and validatorTimelockPostV29 getters are available for backward compatibility of nodes that rely on the validatorTimelock address being available.
address public validatorTimelockPostV29;
/// @dev Contract is expected to be used as proxy implementation.
/// @dev Initialize the implementation to prevent Parity hack.
/// @dev Note, that while the contract does not use `nonReentrant` modifier, we still keep the `reentrancyGuardInitializer`
/// here for two reasons:
/// - It prevents the function from being called twice (including in the proxy impl).
/// - It makes the local version consistent with the one in production, which already had the reentrancy guard
/// initialized.
constructor(address _bridgehub) reentrancyGuardInitializer {
BRIDGE_HUB = _bridgehub;
// While this does not provide a protection in the production, it is needed for local testing
// Length of the L2Log encoding should not be equal to the length of other L2Logs' tree nodes preimages
assert(L2_TO_L1_LOG_SERIALIZE_SIZE != 2 * 32);
_disableInitializers();
}
/// @notice only the bridgehub can call
modifier onlyBridgehub() {
if (msg.sender != BRIDGE_HUB) {
revert Unauthorized(msg.sender);
}
_;
}
/// @notice the admin can call, for non-critical updates
modifier onlyOwnerOrAdmin() {
if (msg.sender != admin && msg.sender != owner()) {
revert Unauthorized(msg.sender);
}
_;
}
/// @notice only the chain asset handler can call
modifier onlyChainAssetHandler() {
if (msg.sender != IBridgehub(BRIDGE_HUB).chainAssetHandler()) {
revert Unauthorized(msg.sender);
}
_;
}
/// @return The tuple of (major, minor, patch) protocol version.
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32) {
// slither-disable-next-line unused-return
return SemVer.unpackSemVer(SafeCast.toUint96(protocolVersion));
}
/// @notice return the chain contract address for a chainId
function getZKChain(uint256 _chainId) public view returns (address) {
return IBridgehub(BRIDGE_HUB).getZKChain(_chainId);
}
/// @notice return the chain contract address for a chainId
/// @notice Do not use! use getZKChain instead. This will be removed.
function getZKChainLegacy(uint256 _chainId) public view returns (address chainAddress) {
// slither-disable-next-line unused-return
(, chainAddress) = __DEPRECATED_zkChainMap.tryGet(_chainId);
}
/// @notice Returns the address of the ZK chain admin with the corresponding chainID.
/// @notice Not related to the CTM, but it is here for legacy reasons.
/// @param _chainId the chainId of the chain
function getChainAdmin(uint256 _chainId) external view override returns (address) {
return IZKChain(getZKChain(_chainId)).getAdmin();
}
/// @dev initialize
/// @dev Note, that while the contract does not use `nonReentrant` modifier, we still keep the `reentrancyGuardInitializer`
/// here for two reasons:
/// - It prevents the function from being called twice (including in the proxy impl).
/// - It makes the local version consistent with the one in production, which already had the reentrancy guard
/// initialized.
function initialize(ChainTypeManagerInitializeData calldata _initializeData) external reentrancyGuardInitializer {
if (_initializeData.owner == address(0)) {
revert ZeroAddress();
}
_transferOwnership(_initializeData.owner);
protocolVersion = _initializeData.protocolVersion;
_setProtocolVersionDeadline(_initializeData.protocolVersion, type(uint256).max);
validatorTimelockPostV29 = _initializeData.validatorTimelock;
serverNotifierAddress = _initializeData.serverNotifier;
_setChainCreationParams(_initializeData.chainCreationParams);
}
/// @notice Updates the parameters with which a new chain is created
/// @param _chainCreationParams The new chain creation parameters
function _setChainCreationParams(ChainCreationParams calldata _chainCreationParams) internal {
if (_chainCreationParams.genesisUpgrade == address(0)) {
revert GenesisUpgradeZero();
}
if (_chainCreationParams.genesisBatchHash == bytes32(0)) {
revert GenesisBatchHashZero();
}
if (_chainCreationParams.genesisIndexRepeatedStorageChanges == uint64(0)) {
revert GenesisIndexStorageZero();
}
if (_chainCreationParams.genesisBatchCommitment == bytes32(0)) {
revert GenesisBatchCommitmentZero();
}
l1GenesisUpgrade = _chainCreationParams.genesisUpgrade;
// We need to initialize the state hash because it is used in the commitment of the next batch
IExecutor.StoredBatchInfo memory batchZero = IExecutor.StoredBatchInfo({
batchNumber: 0,
batchHash: _chainCreationParams.genesisBatchHash,
indexRepeatedStorageChanges: _chainCreationParams.genesisIndexRepeatedStorageChanges,
numberOfLayer1Txs: 0,
priorityOperationsHash: EMPTY_STRING_KECCAK,
l2LogsTreeRoot: DEFAULT_L2_LOGS_TREE_ROOT_HASH,
dependencyRootsRollingHash: bytes32(0),
timestamp: 0,
commitment: _chainCreationParams.genesisBatchCommitment
});
storedBatchZero = keccak256(abi.encode(batchZero));
bytes32 newInitialCutHash = keccak256(abi.encode(_chainCreationParams.diamondCut));
initialCutHash = newInitialCutHash;
bytes32 forceDeploymentHash = keccak256(abi.encode(_chainCreationParams.forceDeploymentsData));
initialForceDeploymentHash = forceDeploymentHash;
emit NewChainCreationParams({
genesisUpgrade: _chainCreationParams.genesisUpgrade,
genesisBatchHash: _chainCreationParams.genesisBatchHash,
genesisIndexRepeatedStorageChanges: _chainCreationParams.genesisIndexRepeatedStorageChanges,
genesisBatchCommitment: _chainCreationParams.genesisBatchCommitment,
newInitialCut: _chainCreationParams.diamondCut,
newInitialCutHash: newInitialCutHash,
forceDeploymentsData: _chainCreationParams.forceDeploymentsData,
forceDeploymentHash: forceDeploymentHash
});
}
/// @notice Updates the parameters with which a new chain is created
/// @param _chainCreationParams The new chain creation parameters
function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external onlyOwner {
_setChainCreationParams(_chainCreationParams);
}
/// @notice Starts the transfer of admin rights. Only the current admin can propose a new pending one.
/// @notice New admin can accept admin rights by calling `acceptAdmin` function.
/// @param _newPendingAdmin Address of the new admin
/// @dev Please note, if the owner wants to enforce the admin change it must execute both `setPendingAdmin` and
/// `acceptAdmin` atomically. Otherwise `admin` can set different pending admin and so fail to accept the admin rights.
function setPendingAdmin(address _newPendingAdmin) external onlyOwnerOrAdmin {
// Save previous value into the stack to put it into the event later
address oldPendingAdmin = pendingAdmin;
// Change pending admin
pendingAdmin = _newPendingAdmin;
emit NewPendingAdmin(oldPendingAdmin, _newPendingAdmin);
}
/// @notice Accepts transfer of admin rights. Only pending admin can accept the role.
function acceptAdmin() external {
address currentPendingAdmin = pendingAdmin;
// Only proposed by current admin address can claim the admin rights
if (msg.sender != currentPendingAdmin) {
revert Unauthorized(msg.sender);
}
address previousAdmin = admin;
admin = currentPendingAdmin;
delete pendingAdmin;
emit NewPendingAdmin(currentPendingAdmin, address(0));
emit NewAdmin(previousAdmin, currentPendingAdmin);
}
/// @dev Used to set legacy validatorTimelock.
/// @dev Note, that the validator timelock that this function sets is only used for pre-v29 protocol versions.
/// It is kept only for convenience.
/// @param _validatorTimelock the new validatorTimelock address
function setLegacyValidatorTimelock(address _validatorTimelock) external onlyOwner {
address oldValidatorTimelock = __DEPRECATED_validatorTimelock;
__DEPRECATED_validatorTimelock = _validatorTimelock;
emit NewValidatorTimelock(oldValidatorTimelock, _validatorTimelock);
}
/// @dev Used to set post-V29 validator timelock. Cannot do it during initialization, as validatorTimelockPostV29 is deployed after CTM.
/// @param _validatorTimelockPostV29 the new post-V29 upgradeable validatorTimelock address
function setValidatorTimelockPostV29(address _validatorTimelockPostV29) external onlyOwner {
address oldValidatorTimelockPostV29 = validatorTimelockPostV29;
validatorTimelockPostV29 = _validatorTimelockPostV29;
emit NewValidatorTimelockPostV29(oldValidatorTimelockPostV29, _validatorTimelockPostV29);
}
/// @dev set ServerNotifier.
/// @param _serverNotifier the new serverNotifier address
function setServerNotifier(address _serverNotifier) external onlyOwnerOrAdmin {
address oldServerNotifier = serverNotifierAddress;
serverNotifierAddress = _serverNotifier;
emit NewServerNotifier(oldServerNotifier, _serverNotifier);
}
/// @dev set New Version with upgrade from old version
/// @param _cutData the new diamond cut data
/// @param _oldProtocolVersion the old protocol version
/// @param _oldProtocolVersionDeadline the deadline for the old protocol version
/// @param _newProtocolVersion the new protocol version
function setNewVersionUpgrade(
Diamond.DiamondCutData calldata _cutData,
uint256 _oldProtocolVersion,
uint256 _oldProtocolVersionDeadline,
uint256 _newProtocolVersion
) external onlyOwner {
if (!IBridgehub(BRIDGE_HUB).migrationPaused()) {
revert MigrationsNotPaused();
}
bytes32 newCutHash = keccak256(abi.encode(_cutData));
uint256 previousProtocolVersion = protocolVersion;
upgradeCutHash[_oldProtocolVersion] = newCutHash;
_setProtocolVersionDeadline(_oldProtocolVersion, _oldProtocolVersionDeadline);
_setProtocolVersionDeadline(_newProtocolVersion, type(uint256).max);
protocolVersion = _newProtocolVersion;
emit NewProtocolVersion(previousProtocolVersion, _newProtocolVersion);
emit NewUpgradeCutHash(_oldProtocolVersion, newCutHash);
emit NewUpgradeCutData(_newProtocolVersion, _cutData);
}
/// @dev check that the protocolVersion is active
/// @param _protocolVersion the protocol version to check
function protocolVersionIsActive(uint256 _protocolVersion) external view override returns (bool) {
return block.timestamp <= protocolVersionDeadline[_protocolVersion];
}
/// @notice Set the protocol version deadline
/// @param _protocolVersion the protocol version
/// @param _timestamp the timestamp is the deadline
function setProtocolVersionDeadline(uint256 _protocolVersion, uint256 _timestamp) external onlyOwner {
_setProtocolVersionDeadline(_protocolVersion, _timestamp);
}
/// @dev set upgrade for some protocolVersion
/// @param _cutData the new diamond cut data
/// @param _oldProtocolVersion the old protocol version
function setUpgradeDiamondCut(
Diamond.DiamondCutData calldata _cutData,
uint256 _oldProtocolVersion
) external onlyOwner {
bytes32 newCutHash = keccak256(abi.encode(_cutData));
upgradeCutHash[_oldProtocolVersion] = newCutHash;
emit NewUpgradeCutHash(_oldProtocolVersion, newCutHash);
}
/// @dev freezes the specified chain
/// @param _chainId the chainId of the chain
function freezeChain(uint256 _chainId) external onlyOwner {
IZKChain(getZKChain(_chainId)).freezeDiamond();
}
/// @dev freezes the specified chain
/// @param _chainId the chainId of the chain
function unfreezeChain(uint256 _chainId) external onlyOwner {
IZKChain(getZKChain(_chainId)).unfreezeDiamond();
}
/// @dev reverts batches on the specified chain
/// @param _chainId the chainId of the chain
/// @param _newLastBatch the new last batch
function revertBatches(uint256 _chainId, uint256 _newLastBatch) external onlyOwner {
address zkChainAddr = getZKChain(_chainId);
IZKChain(zkChainAddr).revertBatchesSharedBridge(zkChainAddr, _newLastBatch);
}
/// @dev execute predefined upgrade
/// @param _chainId the chainId of the chain
/// @param _oldProtocolVersion the old protocol version
/// @param _diamondCut the diamond cut data
function upgradeChainFromVersion(
uint256 _chainId,
uint256 _oldProtocolVersion,
Diamond.DiamondCutData calldata _diamondCut
) external onlyOwner {
IZKChain(getZKChain(_chainId)).upgradeChainFromVersion(_oldProtocolVersion, _diamondCut);
}
/// @dev executes upgrade on chain
/// @param _chainId the chainId of the chain
/// @param _diamondCut the diamond cut data
function executeUpgrade(uint256 _chainId, Diamond.DiamondCutData calldata _diamondCut) external onlyOwner {
IZKChain(getZKChain(_chainId)).executeUpgrade(_diamondCut);
}
/// @dev setPriorityTxMaxGasLimit for the specified chain
/// @param _chainId the chainId of the chain
/// @param _maxGasLimit the new max gas limit
function setPriorityTxMaxGasLimit(uint256 _chainId, uint256 _maxGasLimit) external onlyOwner {
IZKChain(getZKChain(_chainId)).setPriorityTxMaxGasLimit(_maxGasLimit);
}
/// @dev setTokenMultiplier for the specified chain
/// @param _chainId the chainId of the chain
/// @param _nominator the new nominator of the token multiplier
/// @param _denominator the new denominator of the token multiplier
function setTokenMultiplier(uint256 _chainId, uint128 _nominator, uint128 _denominator) external onlyOwner {
IZKChain(getZKChain(_chainId)).setTokenMultiplier(_nominator, _denominator);
}
/// @dev changeFeeParams for the specified chain
/// @param _chainId the chainId of the chain
/// @param _newFeeParams the new fee params
function changeFeeParams(uint256 _chainId, FeeParams calldata _newFeeParams) external onlyOwner {
IZKChain(getZKChain(_chainId)).changeFeeParams(_newFeeParams);
}
/// @dev setValidator for the specified chain
/// @param _chainId the chainId of the chain
/// @param _validator the new validator
/// @param _active whether the validator is active
function setValidator(uint256 _chainId, address _validator, bool _active) external onlyOwner {
IZKChain(getZKChain(_chainId)).setValidator(_validator, _active);
}
/// @dev setPorterAvailability for the specified chain
/// @param _chainId the chainId of the chain
/// @param _zkPorterIsAvailable whether the zkPorter mode is available
function setPorterAvailability(uint256 _chainId, bool _zkPorterIsAvailable) external onlyOwner {
IZKChain(getZKChain(_chainId)).setPorterAvailability(_zkPorterIsAvailable);
}
/// registration
/// @notice deploys a full set of chains contracts
/// @param _chainId the chain's id
/// @param _baseTokenAssetId the base token asset id used to pay for gas fees
/// @param _admin the chain's admin address
/// @param _diamondCut the diamond cut data that initializes the chains Diamond Proxy
function _deployNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _admin,
bytes memory _diamondCut
) internal returns (address zkChainAddress) {
if (getZKChain(_chainId) != address(0)) {
// ZKChain already registered
revert ChainAlreadyLive();
}
Diamond.DiamondCutData memory diamondCut = abi.decode(_diamondCut, (Diamond.DiamondCutData));
{
// check input
bytes32 cutHashInput = keccak256(_diamondCut);
if (cutHashInput != initialCutHash) {
revert HashMismatch(initialCutHash, cutHashInput);
}
}
// construct init data
bytes memory initData;
/// all together 4+9*32=292 bytes for the selector + mandatory data
// solhint-disable-next-line func-named-parameters
initData = bytes.concat(
IDiamondInit.initialize.selector,
bytes32(_chainId),
bytes32(uint256(uint160(BRIDGE_HUB))),
bytes32(uint256(uint160(address(this)))),
bytes32(protocolVersion),
bytes32(uint256(uint160(_admin))),
bytes32(uint256(uint160(validatorTimelockPostV29))),
_baseTokenAssetId,
storedBatchZero,
diamondCut.initCalldata
);
diamondCut.initCalldata = initData;
// deploy zkChainContract
// slither-disable-next-line reentrancy-no-eth
DiamondProxy zkChainContract = new DiamondProxy{salt: bytes32(0)}(block.chainid, diamondCut);
// save data
zkChainAddress = address(zkChainContract);
emit NewZKChain(_chainId, zkChainAddress);
}
/// @notice called by Bridgehub when a chain registers
/// @param _chainId the chain's id
/// @param _baseTokenAssetId the base token asset id used to pay for gas fees
/// @param _admin the chain's admin address
/// @param _initData the diamond cut data, force deployments and factoryDeps encoded
/// @param _factoryDeps the factory dependencies used for the genesis upgrade
/// that initializes the chains Diamond Proxy
function createNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _admin,
bytes calldata _initData,
bytes[] calldata _factoryDeps
) external onlyBridgehub returns (address zkChainAddress) {
(bytes memory _diamondCut, bytes memory _forceDeploymentData) = abi.decode(_initData, (bytes, bytes));
// solhint-disable-next-line func-named-parameters
zkChainAddress = _deployNewChain(_chainId, _baseTokenAssetId, _admin, _diamondCut);
{
// check input
bytes32 forceDeploymentHash = keccak256(abi.encode(_forceDeploymentData));
if (forceDeploymentHash != initialForceDeploymentHash) {
revert InitialForceDeploymentMismatch(forceDeploymentHash, initialForceDeploymentHash);
}
}
// genesis upgrade, deploys some contracts, sets chainId
IAdmin(zkChainAddress).genesisUpgrade(
l1GenesisUpgrade,
address(IBridgehub(BRIDGE_HUB).l1CtmDeployer()),
_forceDeploymentData,
_factoryDeps
);
}
/// @param _chainId the chainId of the chain
function getProtocolVersion(uint256 _chainId) public view returns (uint256) {
return IZKChain(getZKChain(_chainId)).getProtocolVersion();
}
/// @notice Called by the bridgehub during the migration of a chain to another settlement layer.
/// @param _chainId The chain id of the chain to be migrated.
/// @param _data The data needed to perform the migration.
function forwardedBridgeBurn(
uint256 _chainId,
bytes calldata _data
) external view override onlyChainAssetHandler returns (bytes memory ctmForwardedBridgeMintData) {
// Note that the `_diamondCut` here is not for the current chain, for the chain where the migration
// happens. The correctness of it will be checked on the CTM on the new settlement layer.
(address _newSettlementLayerAdmin, bytes memory _diamondCut) = abi.decode(_data, (address, bytes));
if (_newSettlementLayerAdmin == address(0)) {
revert AdminZero();
}
// We ensure that the chain has the latest protocol version to avoid edge cases
// related to different protocol version support.
uint256 chainProtocolVersion = IZKChain(getZKChain(_chainId)).getProtocolVersion();
if (chainProtocolVersion != protocolVersion) {
revert OutdatedProtocolVersion(protocolVersion, chainProtocolVersion);
}
return
abi.encode(
IBridgehub(BRIDGE_HUB).baseTokenAssetId(_chainId),
_newSettlementLayerAdmin,
protocolVersion,
_diamondCut
);
}
/// @notice Called by the bridgehub during the migration of a chain to the current settlement layer.
/// @param _chainId The chain id of the chain to be migrated.
/// @param _ctmData The data returned from `forwardedBridgeBurn` for the chain.
function forwardedBridgeMint(
uint256 _chainId,
bytes calldata _ctmData
) external override onlyChainAssetHandler returns (address chainAddress) {
(bytes32 _baseTokenAssetId, address _admin, uint256 _protocolVersion, bytes memory _diamondCut) = abi.decode(
_ctmData,
(bytes32, address, uint256, bytes)
);
// We ensure that the chain has the latest protocol version to avoid edge cases
// related to different protocol version support.
if (_protocolVersion != protocolVersion) {
revert OutdatedProtocolVersion(protocolVersion, _protocolVersion);
}
chainAddress = _deployNewChain({
_chainId: _chainId,
_baseTokenAssetId: _baseTokenAssetId,
_admin: _admin,
_diamondCut: _diamondCut
});
}
/// @notice Called by the bridgehub during the failed migration of a chain.
/// param _chainId the chainId of the chain
/// param _assetInfo the assetInfo of the chain
/// param _depositSender the address of that sent the deposit
/// param _ctmData the data of the migration
function forwardedBridgeRecoverFailedTransfer(
uint256 /* _chainId */,
bytes32 /* _assetInfo */,
address /* _depositSender */,
bytes calldata /* _ctmData */
) external {
// Function is empty due to the fact that when calling `forwardedBridgeBurn` there are no
// state updates that occur.
}
/// @notice Set the protocol version deadline
/// @param _protocolVersion the protocol version
/// @param _timestamp the timestamp is the deadline
function _setProtocolVersionDeadline(uint256 _protocolVersion, uint256 _timestamp) internal {
protocolVersionDeadline[_protocolVersion] = _timestamp;
emit UpdateProtocolVersionDeadline(_protocolVersion, _timestamp);
}
/*//////////////////////////////////////////////////////////////
Legacy functions
//////////////////////////////////////////////////////////////*/
/// @notice return the chain contract address for a chainId
function getHyperchain(uint256 _chainId) public view returns (address) {
// During upgrade, there will be a period when the zkChains mapping on
// bridgehub will not be filled yet, while the ValidatorTimelock
// will still query the address to obtain the chain id.
//
// To cover this case, we firstly use the existing storage and only then
// we use the bridgehub if the former was not present.
// This logic should be deleted in one of the future upgrades.
address legacyAddress = getZKChainLegacy(_chainId);
if (legacyAddress != address(0)) {
return legacyAddress;
}
return getZKChain(_chainId);
}
/// @notice Returns the legacy validator timelock address.
/// @dev This function is used to return the validator timelock address for pre-v29 protocol versions.
/// @dev This function is deprecated and will be removed in the future.
function validatorTimelock() external view returns (address) {
return __DEPRECATED_validatorTimelock;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableMap.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
pragma solidity ^0.8.0;
import "./EnumerableSet.sol";
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* The following map types are supported:
*
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
* - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableMap.
* ====
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
// UintToUintMap
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintToAddressMap
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressToUintMap
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(AddressToUintMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// 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 {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol";
import {UncheckedMath} from "../../common/libraries/UncheckedMath.sol";
import {AddressHasNoCode, DelegateCallFailed, FacetExists, NoFunctionsForDiamondCut, NonEmptyCalldata, RemoveFunctionFacetAddressNotZero, RemoveFunctionFacetAddressZero, ReplaceFunctionFacetAddressZero, SelectorsMustAllHaveSameFreezability, UndefinedDiamondCutAction} from "../../common/L1ContractErrors.sol";
/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @notice The helper library for managing the EIP-2535 diamond proxy.
library Diamond {
using UncheckedMath for uint256;
using SafeCast for uint256;
/// @dev Magic value that should be returned by diamond cut initialize contracts.
/// @dev Used to distinguish calls to contracts that were supposed to be used as diamond initializer from other contracts.
bytes32 internal constant DIAMOND_INIT_SUCCESS_RETURN_VALUE =
0x33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a2; // keccak256("diamond.zksync.init") - 1
/// @dev Storage position of `DiamondStorage` structure.
bytes32 private constant DIAMOND_STORAGE_POSITION =
0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b; // keccak256("diamond.standard.diamond.storage") - 1;
event DiamondCut(FacetCut[] facetCuts, address initAddress, bytes initCalldata);
/// @dev Utility struct that contains associated facet & meta information of selector
/// @param facetAddress address of the facet which is connected with selector
/// @param selectorPosition index in `FacetToSelectors.selectors` array, where is selector stored
/// @param isFreezable denotes whether the selector can be frozen.
struct SelectorToFacet {
address facetAddress;
uint16 selectorPosition;
bool isFreezable;
}
/// @dev Utility struct that contains associated selectors & meta information of facet
/// @param selectors list of all selectors that belong to the facet
/// @param facetPosition index in `DiamondStorage.facets` array, where is facet stored
struct FacetToSelectors {
bytes4[] selectors;
uint16 facetPosition;
}
/// @notice The structure that holds all diamond proxy associated parameters
/// @dev According to the EIP-2535 should be stored on a special storage key - `DIAMOND_STORAGE_POSITION`
/// @param selectorToFacet A mapping from the selector to the facet address and its meta information
/// @param facetToSelectors A mapping from facet address to its selectors with meta information
/// @param facets The array of all unique facet addresses that belong to the diamond proxy
/// @param isFrozen Denotes whether the diamond proxy is frozen and all freezable facets are not accessible
struct DiamondStorage {
mapping(bytes4 selector => SelectorToFacet selectorInfo) selectorToFacet;
mapping(address facetAddress => FacetToSelectors facetInfo) facetToSelectors;
address[] facets;
bool isFrozen;
}
/// @dev Parameters for diamond changes that touch one of the facets
/// @param facet The address of facet that's affected by the cut
/// @param action The action that is made on the facet
/// @param isFreezable Denotes whether the facet & all their selectors can be frozen
/// @param selectors An array of unique selectors that belongs to the facet address
// solhint-disable-next-line gas-struct-packing
struct FacetCut {
address facet;
Action action;
bool isFreezable;
bytes4[] selectors;
}
/// @dev Structure of the diamond proxy changes
/// @param facetCuts The set of changes (adding/removing/replacement) of implementation contracts
/// @param initAddress The address that's delegate called after setting up new facet changes
/// @param initCalldata Calldata for the delegate call to `initAddress`
struct DiamondCutData {
FacetCut[] facetCuts;
address initAddress;
bytes initCalldata;
}
/// @dev Type of change over diamond: add/replace/remove facets
enum Action {
Add,
Replace,
Remove
}
/// @return diamondStorage The pointer to the storage where all specific diamond proxy parameters stored
function getDiamondStorage() internal pure returns (DiamondStorage storage diamondStorage) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
diamondStorage.slot := position
}
}
/// @dev Add/replace/remove any number of selectors and optionally execute a function with delegatecall
/// @param _diamondCut Diamond's facet changes and the parameters to optional initialization delegatecall
function diamondCut(DiamondCutData memory _diamondCut) internal {
FacetCut[] memory facetCuts = _diamondCut.facetCuts;
address initAddress = _diamondCut.initAddress;
bytes memory initCalldata = _diamondCut.initCalldata;
uint256 facetCutsLength = facetCuts.length;
for (uint256 i = 0; i < facetCutsLength; i = i.uncheckedInc()) {
Action action = facetCuts[i].action;
address facet = facetCuts[i].facet;
bool isFacetFreezable = facetCuts[i].isFreezable;
bytes4[] memory selectors = facetCuts[i].selectors;
if (selectors.length == 0) {
revert NoFunctionsForDiamondCut();
}
if (action == Action.Add) {
_addFunctions(facet, selectors, isFacetFreezable);
} else if (action == Action.Replace) {
_replaceFunctions(facet, selectors, isFacetFreezable);
} else if (action == Action.Remove) {
_removeFunctions(facet, selectors);
} else {
revert UndefinedDiamondCutAction();
}
}
_initializeDiamondCut(initAddress, initCalldata);
emit DiamondCut(facetCuts, initAddress, initCalldata);
}
/// @dev Add new functions to the diamond proxy
/// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array
function _addFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private {
DiamondStorage storage ds = getDiamondStorage();
// Facet with no code cannot be added.
// This check also verifies that the facet does not have zero address, since it is the
// address with which 0x00000000 selector is associated.
if (_facet.code.length == 0) {
revert AddressHasNoCode(_facet);
}
// Add facet to the list of facets if the facet address is new one
_saveFacetIfNew(_facet);
uint256 selectorsLength = _selectors.length;
for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {
bytes4 selector = _selectors[i];
SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];
if (oldFacet.facetAddress != address(0)) {
revert FacetExists(selector, oldFacet.facetAddress);
}
_addOneFunction(_facet, selector, _isFacetFreezable);
}
}
/// @dev Change associated facets to already known function selectors
/// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array
function _replaceFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private {
DiamondStorage storage ds = getDiamondStorage();
// Facet with no code cannot be added.
// This check also verifies that the facet does not have zero address, since it is the
// address with which 0x00000000 selector is associated.
if (_facet.code.length == 0) {
revert AddressHasNoCode(_facet);
}
uint256 selectorsLength = _selectors.length;
for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {
bytes4 selector = _selectors[i];
SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];
// it is impossible to replace the facet with zero address
if (oldFacet.facetAddress == address(0)) {
revert ReplaceFunctionFacetAddressZero();
}
_removeOneFunction(oldFacet.facetAddress, selector);
// Add facet to the list of facets if the facet address is a new one
_saveFacetIfNew(_facet);
_addOneFunction(_facet, selector, _isFacetFreezable);
}
}
/// @dev Remove association with function and facet
/// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array
function _removeFunctions(address _facet, bytes4[] memory _selectors) private {
DiamondStorage storage ds = getDiamondStorage();
// facet address must be zero
if (_facet != address(0)) {
revert RemoveFunctionFacetAddressNotZero(_facet);
}
uint256 selectorsLength = _selectors.length;
for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) {
bytes4 selector = _selectors[i];
SelectorToFacet memory oldFacet = ds.selectorToFacet[selector];
// Can't delete a non-existent facet
if (oldFacet.facetAddress == address(0)) {
revert RemoveFunctionFacetAddressZero();
}
_removeOneFunction(oldFacet.facetAddress, selector);
}
}
/// @dev Add address to the list of known facets if it is not on the list yet
/// NOTE: should be called ONLY before adding a new selector associated with the address
function _saveFacetIfNew(address _facet) private {
DiamondStorage storage ds = getDiamondStorage();
uint256 selectorsLength = ds.facetToSelectors[_facet].selectors.length;
// If there are no selectors associated with facet then save facet as new one
if (selectorsLength == 0) {
ds.facetToSelectors[_facet].facetPosition = ds.facets.length.toUint16();
ds.facets.push(_facet);
}
}
/// @dev Add one function to the already known facet
/// NOTE: It is expected but NOT enforced that:
/// - `_facet` is NON-ZERO address
/// - `_facet` is already stored address in `DiamondStorage.facets`
/// - `_selector` is NOT associated by another facet
function _addOneFunction(address _facet, bytes4 _selector, bool _isSelectorFreezable) private {
DiamondStorage storage ds = getDiamondStorage();
uint16 selectorPosition = (ds.facetToSelectors[_facet].selectors.length).toUint16();
// if selectorPosition is nonzero, it means it is not a new facet
// so the freezability of the first selector must be matched to _isSelectorFreezable
// so all the selectors in a facet will have the same freezability
if (selectorPosition != 0) {
bytes4 selector0 = ds.facetToSelectors[_facet].selectors[0];
if (_isSelectorFreezable != ds.selectorToFacet[selector0].isFreezable) {
revert SelectorsMustAllHaveSameFreezability();
}
}
ds.selectorToFacet[_selector] = SelectorToFacet({
facetAddress: _facet,
selectorPosition: selectorPosition,
isFreezable: _isSelectorFreezable
});
ds.facetToSelectors[_facet].selectors.push(_selector);
}
/// @dev Remove one associated function with facet
/// NOTE: It is expected but NOT enforced that `_facet` is NON-ZERO address
function _removeOneFunction(address _facet, bytes4 _selector) private {
DiamondStorage storage ds = getDiamondStorage();
// Get index of `FacetToSelectors.selectors` of the selector and last element of array
uint256 selectorPosition = ds.selectorToFacet[_selector].selectorPosition;
uint256 lastSelectorPosition = ds.facetToSelectors[_facet].selectors.length - 1;
// If the selector is not at the end of the array then move the last element to the selector position
if (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = ds.facetToSelectors[_facet].selectors[lastSelectorPosition];
ds.facetToSelectors[_facet].selectors[selectorPosition] = lastSelector;
ds.selectorToFacet[lastSelector].selectorPosition = selectorPosition.toUint16();
}
// Remove last element from the selectors array
ds.facetToSelectors[_facet].selectors.pop();
// Finally, clean up the association with facet
delete ds.selectorToFacet[_selector];
// If there are no selectors for facet then remove the facet from the list of known facets
if (lastSelectorPosition == 0) {
_removeFacet(_facet);
}
}
/// @dev remove facet from the list of known facets
/// NOTE: It is expected but NOT enforced that there are no selectors associated with `_facet`
function _removeFacet(address _facet) private {
DiamondStorage storage ds = getDiamondStorage();
// Get index of `DiamondStorage.facets` of the facet and last element of array
uint256 facetPosition = ds.facetToSelectors[_facet].facetPosition;
uint256 lastFacetPosition = ds.facets.length - 1;
// If the facet is not at the end of the array then move the last element to the facet position
if (facetPosition != lastFacetPosition) {
address lastFacet = ds.facets[lastFacetPosition];
ds.facets[facetPosition] = lastFacet;
ds.facetToSelectors[lastFacet].facetPosition = facetPosition.toUint16();
}
// Remove last element from the facets array
ds.facets.pop();
}
/// @dev Delegates call to the initialization address with provided calldata
/// @dev Used as a final step of diamond cut to execute the logic of the initialization for changed facets
function _initializeDiamondCut(address _init, bytes memory _calldata) private {
if (_init == address(0)) {
// Non-empty calldata for zero address
if (_calldata.length != 0) {
revert NonEmptyCalldata();
}
} else {
// Do not check whether `_init` is a contract since later we check that it returns data.
(bool success, bytes memory data) = _init.delegatecall(_calldata);
if (!success) {
// If the returndata is too small, we still want to produce some meaningful error
if (data.length < 4) {
revert DelegateCallFailed(data);
}
assembly {
revert(add(data, 0x20), mload(data))
}
}
// Check that called contract returns magic value to make sure that contract logic
// supposed to be used as diamond cut initializer.
if (data.length != 32) {
revert DelegateCallFailed(data);
}
if (abi.decode(data, (bytes32)) != DIAMOND_INIT_SUCCESS_RETURN_VALUE) {
revert DelegateCallFailed(data);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
// Note, that while we do try to make use of custom errors whenever possible,
// we do not change it for `DiamondProxy`, since it is a contract that can not be
// upgraded or changed, so we keep its code always consistent with the production version.
// solhint-disable gas-custom-errors
import {Diamond} from "../libraries/Diamond.sol";
/// @title Diamond Proxy Contract (EIP-2535)
/// @author Matter Labs
/// @custom:security-contact [email protected]
contract DiamondProxy {
constructor(uint256 _chainId, Diamond.DiamondCutData memory _diamondCut) {
// Check that the contract is deployed on the expected chain.
// Thus, the contract deployed by the same Create2 factory on the different chain will have different addresses!
require(_chainId == block.chainid, "pr");
Diamond.diamondCut(_diamondCut);
}
/// @dev 1. Find the facet for the function that is called.
/// @dev 2. Delegate the execution to the found facet via `delegatecall`.
fallback() external payable {
Diamond.DiamondStorage storage diamondStorage = Diamond.getDiamondStorage();
// Check whether the data contains a "full" selector or it is empty.
// Required because Diamond proxy finds a facet by function signature,
// which is not defined for data length in range [1, 3].
require(msg.data.length >= 4 || msg.data.length == 0, "Ut");
// Get facet from function selector
Diamond.SelectorToFacet memory facet = diamondStorage.selectorToFacet[msg.sig];
address facetAddress = facet.facetAddress;
require(facetAddress != address(0), "F"); // Proxy has no facet for this selector
require(!diamondStorage.isFrozen || !facet.isFreezable, "q1"); // Facet is frozen
assembly {
// The pointer to the free memory slot
let ptr := mload(0x40)
// Copy function signature and arguments from calldata at zero position into memory at pointer position
calldatacopy(ptr, 0, calldatasize())
// Delegatecall method of the implementation contract returns 0 on error
let result := delegatecall(gas(), facetAddress, ptr, calldatasize(), 0, 0)
// Get the size of the last return data
let size := returndatasize()
// Copy the size length of bytes from return data at zero position to pointer position
returndatacopy(ptr, 0, size)
// Depending on the result value
switch result
case 0 {
// End execution and revert state changes
revert(ptr, size)
}
default {
// Return data with length of size at pointers position
return(ptr, size)
}
}
}
}// 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 {IZKChainBase} from "../chain-interfaces/IZKChainBase.sol";
import {Diamond} from "../libraries/Diamond.sol";
import {FeeParams, PubdataPricingMode} from "../chain-deps/ZKChainStorage.sol";
import {ZKChainCommitment} from "../../common/Config.sol";
/// @title The interface of the Admin Contract that controls access rights for contract management.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IAdmin is IZKChainBase {
/// @notice Starts the transfer of admin rights. Only the current admin 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;
/// @notice Change validator status (active or not active)
/// @param _validator Validator address
/// @param _active Active flag
function setValidator(address _validator, bool _active) external;
/// @notice Change zk porter availability
/// @param _zkPorterIsAvailable The availability of zk porter shard
function setPorterAvailability(bool _zkPorterIsAvailable) external;
/// @notice Change the max L2 gas limit for L1 -> L2 transactions
/// @param _newPriorityTxMaxGasLimit The maximum number of L2 gas that a user can request for L1 -> L2 transactions
function setPriorityTxMaxGasLimit(uint256 _newPriorityTxMaxGasLimit) external;
/// @notice Change the fee params for L1->L2 transactions
/// @param _newFeeParams The new fee params
function changeFeeParams(FeeParams calldata _newFeeParams) external;
/// @notice Change the token multiplier for L1->L2 transactions
function setTokenMultiplier(uint128 _nominator, uint128 _denominator) external;
/// @notice Change the pubdata pricing mode before the first batch is processed
/// @param _pricingMode The new pubdata pricing mode
function setPubdataPricingMode(PubdataPricingMode _pricingMode) external;
/// @notice Set the transaction filterer
function setTransactionFilterer(address _transactionFilterer) external;
/// @notice Allow EVM emulation on chain
function allowEvmEmulation() external returns (bytes32 canonicalTxHash);
/// @notice Perform the upgrade from the current protocol version with the corresponding upgrade data
/// @param _protocolVersion The current protocol version from which upgrade is executed
/// @param _cutData The diamond cut parameters that is executed in the upgrade
function upgradeChainFromVersion(uint256 _protocolVersion, Diamond.DiamondCutData calldata _cutData) external;
/// @notice Executes a proposed governor upgrade
/// @dev Only the ChainTypeManager contract can execute the upgrade
/// @param _diamondCut The diamond cut parameters to be executed
function executeUpgrade(Diamond.DiamondCutData calldata _diamondCut) external;
/// @notice Instantly pause the functionality of all freezable facets & their selectors
/// @dev Only the governance mechanism may freeze Diamond Proxy
function freezeDiamond() external;
/// @notice Unpause the functionality of all freezable facets & their selectors
/// @dev Only the CTM can unfreeze Diamond Proxy
function unfreezeDiamond() external;
function genesisUpgrade(
address _l1GenesisUpgrade,
address _ctmDeployer,
bytes calldata _forceDeploymentData,
bytes[] calldata _factoryDeps
) external;
/// @notice Returns address of the RollupDAManager of the ZK Chain.
function getRollupDAManager() external view returns (address);
/// @notice Set the L1 DA validator address as well as the L2 DA validator address.
/// @dev While in principle it is possible that updating only one of the addresses is needed,
/// usually these should work in pair and L1 validator typically expects a specific input from the L2 Validator.
/// That's why we change those together to prevent admins of chains from shooting themselves in the foot.
/// @param _l1DAValidator The address of the L1 DA validator
/// @param _l2DAValidator The address of the L2 DA validator
function setDAValidatorPair(address _l1DAValidator, address _l2DAValidator) external;
/// @notice Makes the chain as permanent rollup.
/// @dev This is a security feature needed for chains that should be
/// trusted to keep their data available even if the chain admin becomes malicious
/// and tries to set the DA validator pair to something which does not publish DA to Ethereum.
/// @dev DANGEROUS: once activated, there is no way back!
function makePermanentRollup() external;
/// @notice Porter availability status changes
event IsPorterAvailableStatusUpdate(bool isPorterAvailable);
/// @notice Validator's status changed
event ValidatorStatusUpdate(address indexed validatorAddress, bool isActive);
/// @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 Priority transaction max L2 gas limit changed
event NewPriorityTxMaxGasLimit(uint256 oldPriorityTxMaxGasLimit, uint256 newPriorityTxMaxGasLimit);
/// @notice Fee params for L1->L2 transactions changed
event NewFeeParams(FeeParams oldFeeParams, FeeParams newFeeParams);
/// @notice Validium mode status changed
event PubdataPricingModeUpdate(PubdataPricingMode validiumMode);
/// @notice The transaction filterer has been updated
event NewTransactionFilterer(address oldTransactionFilterer, address newTransactionFilterer);
/// @notice BaseToken multiplier for L1->L2 transactions changed
event NewBaseTokenMultiplier(
uint128 oldNominator,
uint128 oldDenominator,
uint128 newNominator,
uint128 newDenominator
);
/// @notice Emitted when an upgrade is executed.
event ExecuteUpgrade(Diamond.DiamondCutData diamondCut);
/// @notice Emitted when the migration to the new settlement layer is complete.
event MigrationComplete();
/// @notice Emitted when the contract is frozen.
event Freeze();
/// @notice Emitted when the contract is unfrozen.
event Unfreeze();
/// @notice The EVM emulator has been enabled
event EnableEvmEmulator();
/// @notice New pair of DA validators set
event NewL2DAValidator(address indexed oldL2DAValidator, address indexed newL2DAValidator);
event NewL1DAValidator(address indexed oldL1DAValidator, address indexed newL1DAValidator);
event BridgeMint(address indexed _account, uint256 _amount);
/// @dev Similar to IL1AssetHandler interface, used to send chains.
function forwardedBridgeBurn(
address _settlementLayer,
address _originalCaller,
bytes calldata _data
) external payable returns (bytes memory _bridgeMintData);
/// @dev Similar to IL1AssetHandler interface, used to claim failed chain transfers.
function forwardedBridgeRecoverFailedTransfer(
uint256 _chainId,
bytes32 _assetInfo,
address _originalCaller,
bytes calldata _chainData
) external payable;
/// @dev Similar to IL1AssetHandler interface, used to receive chains.
function forwardedBridgeMint(bytes calldata _data, bool _contractAlreadyDeployed) external payable;
function prepareChainCommitment() external view returns (ZKChainCommitment memory commitment);
}// 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 {IVerifier, VerifierParams} from "./IVerifier.sol";
import {FeeParams} from "../chain-deps/ZKChainStorage.sol";
/// @param chainId the id of the chain
/// @param bridgehub the address of the bridgehub contract
/// @param chainTypeManager contract's address
/// @param protocolVersion initial protocol version
/// @param validatorTimelock address of the validator timelock that delays execution
/// @param admin address who can manage the contract
/// @param baseTokenAssetId asset id of the base token of the chain
/// @param storedBatchZero hash of the initial genesis batch
/// @param verifier address of Verifier contract
/// @param verifierParams Verifier config parameters that describes the circuit to be verified
/// @param l2BootloaderBytecodeHash The hash of bootloader L2 bytecode
/// @param l2DefaultAccountBytecodeHash The hash of default account L2 bytecode
/// @param l2EvmEmulatorBytecodeHash The hash of EVM emulator L2 bytecode
/// @param priorityTxMaxGasLimit maximum number of the L2 gas that a user can request for L1 -> L2 transactions
/// @param feeParams Fee parameters to be used for L1->L2 transactions
// solhint-disable-next-line gas-struct-packing
struct InitializeData {
uint256 chainId;
address bridgehub;
address chainTypeManager;
uint256 protocolVersion;
address admin;
address validatorTimelock;
bytes32 baseTokenAssetId;
bytes32 storedBatchZero;
IVerifier verifier;
VerifierParams verifierParams;
bytes32 l2BootloaderBytecodeHash;
bytes32 l2DefaultAccountBytecodeHash;
bytes32 l2EvmEmulatorBytecodeHash;
uint256 priorityTxMaxGasLimit;
FeeParams feeParams;
}
/// @param verifier address of Verifier contract
/// @param verifierParams Verifier config parameters that describes the circuit to be verified
/// @param l2BootloaderBytecodeHash The hash of bootloader L2 bytecode
/// @param l2DefaultAccountBytecodeHash The hash of default account L2 bytecode
/// @param l2EvmEmulatorBytecodeHash The hash of EVM emulator L2 bytecode
/// @param priorityTxMaxGasLimit maximum number of the L2 gas that a user can request for L1 -> L2 transactions
/// @param feeParams Fee parameters to be used for L1->L2 transactions
struct InitializeDataNewChain {
IVerifier verifier;
VerifierParams verifierParams;
bytes32 l2BootloaderBytecodeHash;
bytes32 l2DefaultAccountBytecodeHash;
bytes32 l2EvmEmulatorBytecodeHash;
uint256 priorityTxMaxGasLimit;
FeeParams feeParams;
}
interface IDiamondInit {
function initialize(InitializeData calldata _initData) external returns (bytes32);
}// 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 {IZKChainBase} from "./IZKChainBase.sol";
/// @dev Enum used by L2 System Contracts to differentiate logs.
enum SystemLogKey {
L2_TO_L1_LOGS_TREE_ROOT_KEY,
PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY,
CHAINED_PRIORITY_TXN_HASH_KEY,
NUMBER_OF_LAYER_1_TXS_KEY,
// Note, that it is important that `PREV_BATCH_HASH_KEY` has position
// `4` since it is the same as it was in the previous protocol version and
// it is the only one that is emitted before the system contracts are upgraded.
PREV_BATCH_HASH_KEY,
L2_DA_VALIDATOR_OUTPUT_HASH_KEY,
USED_L2_DA_VALIDATOR_ADDRESS_KEY,
MESSAGE_ROOT_ROLLING_HASH_KEY,
L2_TXS_STATUS_ROLLING_HASH_KEY,
EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY
}
struct LogProcessingOutput {
uint256 numberOfLayer1Txs;
bytes32 chainedPriorityTxsHash;
bytes32 previousBatchHash;
bytes32 pubdataHash;
bytes32 stateDiffHash;
bytes32 l2LogsTreeRoot;
uint256 packedBatchAndL2BlockTimestamp;
bytes32 l2DAValidatorOutputHash;
bytes32 l2TxsStatusRollingHash;
bytes32 dependencyRootsRollingHash;
}
/// @dev Maximal value that SystemLogKey variable can have.
uint256 constant MAX_LOG_KEY = uint256(type(SystemLogKey).max);
/// @dev Offset used to pull Address From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch)
uint256 constant L2_LOG_ADDRESS_OFFSET = 4;
/// @dev Offset used to pull Key From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch) + 20 (bytes for address)
uint256 constant L2_LOG_KEY_OFFSET = 24;
/// @dev Offset used to pull Value From Log. Equal to 4 (bytes for shardId, isService and txNumberInBatch) + 20 (bytes for address) + 32 (bytes for key)
uint256 constant L2_LOG_VALUE_OFFSET = 56;
/// @dev Max number of blobs currently supported
uint256 constant MAX_NUMBER_OF_BLOBS = 6;
/// @dev The number of blobs that must be present in the commitment to a batch.
/// It represents the maximal number of blobs that circuits can support and can be larger
/// than the maximal number of blobs supported by the contract (`MAX_NUMBER_OF_BLOBS`).
uint256 constant TOTAL_BLOBS_IN_COMMITMENT = 16;
/// @title The interface of the ZKsync Executor contract capable of processing events emitted in the ZKsync protocol.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IExecutor is IZKChainBase {
/// @notice Rollup batch stored data
/// @param batchNumber Rollup batch number
/// @param batchHash Hash of L2 batch
/// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more
/// @param numberOfLayer1Txs Number of priority operations to be processed
/// @param priorityOperationsHash Hash of all priority operations from this batch
/// @param l2LogsTreeRoot Root hash of tree that contains L2 -> L1 messages from this batch
/// @param timestamp Rollup batch timestamp, have the same format as Ethereum batch constant
/// @param commitment Verified input for the ZKsync circuit
// solhint-disable-next-line gas-struct-packing
struct StoredBatchInfo {
uint64 batchNumber;
bytes32 batchHash;
uint64 indexRepeatedStorageChanges;
uint256 numberOfLayer1Txs;
bytes32 priorityOperationsHash;
bytes32 dependencyRootsRollingHash;
bytes32 l2LogsTreeRoot;
uint256 timestamp;
bytes32 commitment;
}
/// @notice Legacy StoredBatchInfo struct
/// @dev dependencyRootsRollingHash is not included in the struct
// solhint-disable-next-line gas-struct-packing
struct LegacyStoredBatchInfo {
uint64 batchNumber;
bytes32 batchHash;
uint64 indexRepeatedStorageChanges;
uint256 numberOfLayer1Txs;
bytes32 priorityOperationsHash;
bytes32 l2LogsTreeRoot;
uint256 timestamp;
bytes32 commitment;
}
/// @notice Data needed to commit new batch
/// @param batchNumber Number of the committed batch
/// @param timestamp Unix timestamp denoting the start of the batch execution
/// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more
/// @param newStateRoot The state root of the full state tree
/// @param numberOfLayer1Txs Number of priority operations to be processed
/// @param priorityOperationsHash Hash of all priority operations from this batch
/// @param bootloaderHeapInitialContentsHash Hash of the initial contents of the bootloader heap. In practice it serves as the commitment to the transactions in the batch.
/// @param eventsQueueStateHash Hash of the events queue state. In practice it serves as the commitment to the events in the batch.
/// @param systemLogs concatenation of all L2 -> L1 system logs in the batch
/// @param operatorDAInput Packed pubdata commitments/data.
/// @dev pubdataCommitments format: This will always start with a 1 byte pubdataSource flag. Current allowed values are 0 (calldata) or 1 (blobs)
/// kzg: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes) = 144 bytes
/// calldata: pubdataCommitments.length - 1 - 32 bytes of pubdata
/// and 32 bytes appended to serve as the blob commitment part for the aux output part of the batch commitment
/// @dev For 2 blobs we will be sending 288 bytes of calldata instead of the full amount for pubdata.
/// @dev When using calldata, we only need to send one blob commitment since the max number of bytes in calldata fits in a single blob and we can pull the
/// linear hash from the system logs
struct CommitBatchInfo {
uint64 batchNumber;
uint64 timestamp;
uint64 indexRepeatedStorageChanges;
bytes32 newStateRoot;
uint256 numberOfLayer1Txs;
bytes32 priorityOperationsHash;
bytes32 bootloaderHeapInitialContentsHash;
bytes32 eventsQueueStateHash;
bytes systemLogs;
bytes operatorDAInput;
}
/// @notice Container for a list of transaction statuses to precommit.
/// @param txs A packed array of individual transaction status commitments for the batch. Each is expected to be
/// of length 33 and have the following format: <32-byte tx hash, 1-byte status>. where status is either 0 (failed) or 1 (success).
/// @param untrustedLastL2BlockNumberHint The "hint" for what the last L2 block number that these txs represent is.
struct PrecommitInfo {
bytes packedTxsCommitments;
uint256 untrustedLastL2BlockNumberHint;
}
/// @notice Precommits the status of all L2 transactions for the next batch on the shared bridge.
/// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,
/// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both
/// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.
/// @param _batchNumber The sequential batch number to precommit (must equal `s.totalBatchesCommitted + 1`).
/// @param _precommitData ABI‐encoded transaction status list for the precommit.
function precommitSharedBridge(address _chainAddress, uint256 _batchNumber, bytes calldata _precommitData) external;
/// @notice Function called by the operator to commit new batches. It is responsible for:
/// - Verifying the correctness of their timestamps.
/// - Processing their L2->L1 logs.
/// - Storing batch commitments.
/// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,
/// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both
/// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.
/// @param _processFrom The batch number from which the processing starts.
/// @param _processTo The batch number at which the processing ends.
/// @param _commitData The encoded data of the new batches to be committed.
function commitBatchesSharedBridge(
address _chainAddress,
uint256 _processFrom,
uint256 _processTo,
bytes calldata _commitData
) external;
/// @notice Batches commitment verification.
/// @dev Only verifies batch commitments without any other processing.
/// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,
/// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both
/// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.
/// @param _processBatchFrom The batch number from which the verification starts.
/// @param _processBatchTo The batch number at which the verification ends.
/// @param _proofData The encoded data of the new batches to be verified.
function proveBatchesSharedBridge(
address _chainAddress,
uint256 _processBatchFrom,
uint256 _processBatchTo,
bytes calldata _proofData
) external;
/// @notice The function called by the operator to finalize (execute) batches. It is responsible for:
/// - Processing all pending operations (commpleting priority requests).
/// - Finalizing this batch (i.e. allowing to withdraw funds from the system)
/// @param _chainAddress The address of the DiamondProxy of the chain. Note, that it is not used in the implementation,
/// because it is expected to be equal to the `address(this)`, but it is kept here to maintain the same interface on both
/// `ValidatorTimelock` and `Executor` for easier and cheaper implementation of the timelock.
/// @param _processFrom The batch number from which the execution starts.
/// @param _processTo The batch number at which the execution ends.
/// @param _executeData The encoded data of the new batches to be executed.
function executeBatchesSharedBridge(
address _chainAddress,
uint256 _processFrom,
uint256 _processTo,
bytes calldata _executeData
) external;
/// @notice Reverts unexecuted batches
/// @param _chainAddress The address of the DiamondProxy of the chain.
/// @param _newLastBatch batch number after which batches should be reverted
/// @dev When the _newLastBatch is equal to the number of committed batches,
/// only the precommitment is erased.
/// NOTE: Doesn't delete the stored data about batches, but only decreases
/// counters that are responsible for the number of batches
function revertBatchesSharedBridge(address _chainAddress, uint256 _newLastBatch) external;
/// @notice Event emitted when a batch is committed
/// @param batchNumber Number of the batch committed
/// @param batchHash Hash of the L2 batch
/// @param commitment Calculated input for the ZKsync circuit
/// @dev It has the name "BlockCommit" and not "BatchCommit" due to backward compatibility considerations
event BlockCommit(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment);
/// @notice Event emitted when batches are verified
/// @param previousLastVerifiedBatch Batch number of the previous last verified batch
/// @param currentLastVerifiedBatch Batch number of the current last verified batch
/// @dev It has the name "BlocksVerification" and not "BatchesVerification" due to backward compatibility considerations
event BlocksVerification(uint256 indexed previousLastVerifiedBatch, uint256 indexed currentLastVerifiedBatch);
/// @notice Event emitted when a batch is executed
/// @param batchNumber Number of the batch executed
/// @param batchHash Hash of the L2 batch
/// @param commitment Verified input for the ZKsync circuit
/// @dev It has the name "BlockExecution" and not "BatchExecution" due to backward compatibility considerations
event BlockExecution(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment);
/// @notice Event emitted when batches are reverted
/// @param totalBatchesCommitted Total number of committed batches after the revert
/// @param totalBatchesVerified Total number of verified batches after the revert
/// @param totalBatchesExecuted Total number of executed batches
/// @dev It has the name "BlocksRevert" and not "BatchesRevert" due to backward compatibility considerations
event BlocksRevert(uint256 totalBatchesCommitted, uint256 totalBatchesVerified, uint256 totalBatchesExecuted);
/// @notice Emitted when a new precommitment is set for a batch.
/// @param batchNumber The batch number for which the precommitment was recorded.
/// @param untrustedLastL2BlockNumberHint The hint to what L2 block number the precommitment should correspond to. Note, that there are no
/// guarantees on its correctness, it is just a way for the server to make external nodes' indexing simpler.
/// @param precommitment The resulting rolling hash of all transaction statuses.
event BatchPrecommitmentSet(
uint256 indexed batchNumber,
uint256 indexed untrustedLastL2BlockNumberHint,
bytes32 precommitment
);
}// 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 {Diamond} from "./libraries/Diamond.sol";
import {L2CanonicalTransaction} from "../common/Messaging.sol";
import {FeeParams} from "./chain-deps/ZKChainStorage.sol";
// import {IBridgehub} from "../bridgehub/IBridgehub.sol";
/// @notice Struct that holds all data needed for initializing CTM Proxy.
/// @dev We use struct instead of raw parameters in `initialize` function to prevent "Stack too deep" error
/// @param owner The address who can manage non-critical updates in the contract
/// @param validatorTimelock The address that serves as consensus, i.e. can submit blocks to be processed
/// @param chainCreationParams The struct that contains the fields that define how a new chain should be created
/// @param protocolVersion The initial protocol version on the newly deployed chain
/// @param serverNotifier The address that serves as server notifier
// solhint-disable-next-line gas-struct-packing
struct ChainTypeManagerInitializeData {
address owner;
address validatorTimelock;
ChainCreationParams chainCreationParams;
uint256 protocolVersion;
address serverNotifier;
}
/// @notice The struct that contains the fields that define how a new chain should be created
/// within this CTM.
/// @param genesisUpgrade The address that is used in the diamond cut initialize address on chain creation
/// @param genesisBatchHash Batch hash of the genesis (initial) batch
/// @param genesisIndexRepeatedStorageChanges The serial number of the shortcut storage key for the genesis batch
/// @param genesisBatchCommitment The zk-proof commitment for the genesis batch
/// @param diamondCut The diamond cut for the first upgrade transaction on the newly deployed chain
// solhint-disable-next-line gas-struct-packing
struct ChainCreationParams {
address genesisUpgrade;
bytes32 genesisBatchHash;
uint64 genesisIndexRepeatedStorageChanges;
bytes32 genesisBatchCommitment;
Diamond.DiamondCutData diamondCut;
bytes forceDeploymentsData;
}
interface IChainTypeManager {
/// @dev Emitted when a new ZKChain is added
event NewZKChain(uint256 indexed _chainId, address indexed _zkChainContract);
/// @dev emitted when an chain registers and a GenesisUpgrade happens
event GenesisUpgrade(
address indexed _zkChain,
L2CanonicalTransaction _l2Transaction,
uint256 indexed _protocolVersion
);
/// @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 ValidatorTimelock changed
event NewValidatorTimelock(address indexed oldValidatorTimelock, address indexed newValidatorTimelock);
/// @notice ValidatorTimelockPostV29 changed
event NewValidatorTimelockPostV29(
address indexed oldValidatorTimelockPostV29,
address indexed newvalidatorTimelockPostV29
);
/// @notice ServerNotifier changed
event NewServerNotifier(address indexed oldServerNotifier, address indexed newServerNotifier);
/// @notice chain creation parameters changed
event NewChainCreationParams(
address genesisUpgrade,
bytes32 genesisBatchHash,
uint64 genesisIndexRepeatedStorageChanges,
bytes32 genesisBatchCommitment,
Diamond.DiamondCutData newInitialCut,
bytes32 newInitialCutHash,
bytes forceDeploymentsData,
bytes32 forceDeploymentHash
);
/// @notice New UpgradeCutHash
event NewUpgradeCutHash(uint256 indexed protocolVersion, bytes32 indexed upgradeCutHash);
/// @notice New UpgradeCutData
event NewUpgradeCutData(uint256 indexed protocolVersion, Diamond.DiamondCutData diamondCutData);
/// @notice New ProtocolVersion
event NewProtocolVersion(uint256 indexed oldProtocolVersion, uint256 indexed newProtocolVersion);
/// @notice Updated ProtocolVersion deadline
event UpdateProtocolVersionDeadline(uint256 indexed protocolVersion, uint256 deadline);
function BRIDGE_HUB() external view returns (address);
function setPendingAdmin(address _newPendingAdmin) external;
function acceptAdmin() external;
function getZKChain(uint256 _chainId) external view returns (address);
function getHyperchain(uint256 _chainId) external view returns (address);
function getZKChainLegacy(uint256 _chainId) external view returns (address);
function storedBatchZero() external view returns (bytes32);
function initialCutHash() external view returns (bytes32);
function l1GenesisUpgrade() external view returns (address);
function upgradeCutHash(uint256 _protocolVersion) external view returns (bytes32);
function protocolVersion() external view returns (uint256);
function protocolVersionDeadline(uint256 _protocolVersion) external view returns (uint256);
function protocolVersionIsActive(uint256 _protocolVersion) external view returns (bool);
function getProtocolVersion(uint256 _chainId) external view returns (uint256);
function initialize(ChainTypeManagerInitializeData calldata _initializeData) external;
function setLegacyValidatorTimelock(address _validatorTimelock) external;
function setValidatorTimelockPostV29(address _validatorTimelockPostV29) external;
function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external;
function getChainAdmin(uint256 _chainId) external view returns (address);
function createNewChain(
uint256 _chainId,
bytes32 _baseTokenAssetId,
address _admin,
bytes calldata _initData,
bytes[] calldata _factoryDeps
) external returns (address);
function setNewVersionUpgrade(
Diamond.DiamondCutData calldata _cutData,
uint256 _oldProtocolVersion,
uint256 _oldProtocolVersionDeadline,
uint256 _newProtocolVersion
) external;
function setUpgradeDiamondCut(Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion) external;
function executeUpgrade(uint256 _chainId, Diamond.DiamondCutData calldata _diamondCut) external;
function setPriorityTxMaxGasLimit(uint256 _chainId, uint256 _maxGasLimit) external;
function freezeChain(uint256 _chainId) external;
function unfreezeChain(uint256 _chainId) external;
function setTokenMultiplier(uint256 _chainId, uint128 _nominator, uint128 _denominator) external;
function changeFeeParams(uint256 _chainId, FeeParams calldata _newFeeParams) external;
function setValidator(uint256 _chainId, address _validator, bool _active) external;
function setPorterAvailability(uint256 _chainId, bool _zkPorterIsAvailable) external;
function upgradeChainFromVersion(
uint256 _chainId,
uint256 _oldProtocolVersion,
Diamond.DiamondCutData calldata _diamondCut
) external;
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);
function forwardedBridgeBurn(
uint256 _chainId,
bytes calldata _data
) external returns (bytes memory _bridgeMintData);
function forwardedBridgeMint(uint256 _chainId, bytes calldata _data) external returns (address);
function forwardedBridgeRecoverFailedTransfer(
uint256 _chainId,
bytes32 _assetInfo,
address _depositSender,
bytes calldata _ctmData
) external;
}// 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 {IAdmin} from "./IAdmin.sol";
import {IExecutor} from "./IExecutor.sol";
import {IGetters} from "./IGetters.sol";
import {IMailbox} from "./IMailbox.sol";
import {Diamond} from "../libraries/Diamond.sol";
interface IZKChain is IAdmin, IExecutor, IGetters, IMailbox {
// We need this structure for the server for now
event ProposeTransparentUpgrade(
Diamond.DiamondCutData diamondCut,
uint256 indexed proposalId,
bytes32 proposalSalt
);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IVerifier, VerifierParams} from "../chain-interfaces/IVerifier.sol";
import {PriorityQueue} from "../../state-transition/libraries/PriorityQueue.sol";
import {PriorityTree} from "../../state-transition/libraries/PriorityTree.sol";
/// @notice Indicates whether an upgrade is initiated and if yes what type
/// @param None Upgrade is NOT initiated
/// @param Transparent Fully transparent upgrade is initiated, upgrade data is publicly known
/// @param Shadow Shadow upgrade is initiated, upgrade data is hidden
enum UpgradeState {
None,
Transparent,
Shadow
}
/// @dev Logically separated part of the storage structure, which is responsible for everything related to proxy
/// upgrades and diamond cuts
/// @param proposedUpgradeHash The hash of the current upgrade proposal, zero if there is no active proposal
/// @param state Indicates whether an upgrade is initiated and if yes what type
/// @param securityCouncil Address which has the permission to approve instant upgrades (expected to be a Gnosis
/// multisig)
/// @param approvedBySecurityCouncil Indicates whether the security council has approved the upgrade
/// @param proposedUpgradeTimestamp The timestamp when the upgrade was proposed, zero if there are no active proposals
/// @param currentProposalId The serial number of proposed upgrades, increments when proposing a new one
struct UpgradeStorage {
bytes32 proposedUpgradeHash;
UpgradeState state;
address securityCouncil;
bool approvedBySecurityCouncil;
uint40 proposedUpgradeTimestamp;
uint40 currentProposalId;
}
/// @notice The struct that describes whether users will be charged for pubdata for L1->L2 transactions.
/// @param Rollup The users are charged for pubdata & it is priced based on the gas price on Ethereum.
/// @param Validium The pubdata is considered free with regard to the L1 gas price.
enum PubdataPricingMode {
Rollup,
Validium
}
/// @notice The fee params for L1->L2 transactions for the network.
/// @param pubdataPricingMode How the users will charged for pubdata in L1->L2 transactions.
/// @param batchOverheadL1Gas The amount of L1 gas required to process the batch (except for the calldata).
/// @param maxPubdataPerBatch The maximal number of pubdata that can be emitted per batch.
/// @param priorityTxMaxPubdata The maximal amount of pubdata a priority transaction is allowed to publish.
/// It can be slightly less than maxPubdataPerBatch in order to have some margin for the bootloader execution.
/// @param minimalL2GasPrice The minimal L2 gas price to be used by L1->L2 transactions. It should represent
/// the price that a single unit of compute costs.
struct FeeParams {
PubdataPricingMode pubdataPricingMode;
uint32 batchOverheadL1Gas;
uint32 maxPubdataPerBatch;
uint32 maxL2GasPerBatch;
uint32 priorityTxMaxPubdata;
uint64 minimalL2GasPrice;
}
/// @dev storing all storage variables for ZK chain diamond facets
/// NOTE: It is used in a proxy, so it is possible to add new variables to the end
/// but NOT to modify already existing variables or change their order.
/// NOTE: variables prefixed with '__DEPRECATED_' are deprecated and shouldn't be used.
/// Their presence is maintained for compatibility and to prevent storage collision.
// solhint-disable-next-line gas-struct-packing
struct ZKChainStorage {
/// @dev Storage of variables needed for deprecated diamond cut facet
uint256[7] __DEPRECATED_diamondCutStorage;
/// @notice Address which will exercise critical changes to the Diamond Proxy (upgrades, freezing & unfreezing). Replaced by CTM
address __DEPRECATED_governor;
/// @notice Address that the governor proposed as one that will replace it
address __DEPRECATED_pendingGovernor;
/// @notice List of permitted validators
mapping(address validatorAddress => bool isValidator) validators;
/// @dev Verifier contract. Used to verify aggregated proof for batches
IVerifier verifier;
/// @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;
/// @dev Stored hashed StoredBatch for batch number
mapping(uint256 batchNumber => bytes32 batchHash) storedBatchHashes;
/// @dev Stored root hashes of L2 -> L1 logs
mapping(uint256 batchNumber => bytes32 l2LogsRootHash) l2LogsRootHashes;
/// @dev Container that stores transactions requested from L1
PriorityQueue.Queue __DEPRECATED_priorityQueue;
/// @dev The smart contract that manages the list with permission to call contract functions
address __DEPRECATED_allowList;
VerifierParams __DEPRECATED_verifierParams;
/// @notice Bytecode hash of bootloader program.
/// @dev Used as an input to zkp-circuit.
bytes32 l2BootloaderBytecodeHash;
/// @notice Bytecode hash of default account (bytecode for EOA).
/// @dev Used as an input to zkp-circuit.
bytes32 l2DefaultAccountBytecodeHash;
/// @dev Indicates that the porter may be touched on L2 transactions.
/// @dev Used as an input to zkp-circuit.
bool zkPorterIsAvailable;
/// @dev The maximum number of the L2 gas that a user can request for L1 -> L2 transactions
/// @dev This is the maximum number of L2 gas that is available for the "body" of the transaction, i.e.
/// without overhead for proving the batch.
uint256 priorityTxMaxGasLimit;
/// @dev Storage of variables needed for upgrade facet
UpgradeStorage __DEPRECATED_upgrades;
/// @dev A mapping L2 batch number => message number => flag.
/// @dev The L2 -> L1 log is sent for every withdrawal, so this mapping is serving as
/// a flag to indicate that the message was already processed.
/// @dev Used to indicate that eth withdrawal was already processed
mapping(uint256 l2BatchNumber => mapping(uint256 l2ToL1MessageNumber => bool isFinalized)) isEthWithdrawalFinalized;
/// @dev The most recent withdrawal time and amount reset
uint256 __DEPRECATED_lastWithdrawalLimitReset;
/// @dev The accumulated withdrawn amount during the withdrawal limit window
uint256 __DEPRECATED_withdrawnAmountInWindow;
/// @dev A mapping user address => the total deposited amount by the user
mapping(address => uint256) __DEPRECATED_totalDepositedAmountPerUser;
/// @dev Stores the protocol version. Note, that the protocol version may not only encompass changes to the
/// smart contracts, but also to the node behavior.
uint256 protocolVersion;
/// @dev Hash of the system contract upgrade transaction. If 0, then no upgrade transaction needs to be done.
bytes32 l2SystemContractsUpgradeTxHash;
/// @dev Batch number where the upgrade transaction has happened. If 0, then no upgrade transaction has happened
/// yet.
uint256 l2SystemContractsUpgradeBatchNumber;
/// @dev Address which will exercise non-critical changes to the Diamond Proxy (changing validator set & unfreezing)
address admin;
/// @notice Address that the admin proposed as one that will replace admin role
address pendingAdmin;
/// @dev Fee params used to derive gasPrice for the L1->L2 transactions. For L2 transactions,
/// the bootloader gives enough freedom to the operator.
/// @dev The value is only for the L1 deployment of the ZK Chain, since payment for all the priority transactions is
/// charged at that level.
FeeParams feeParams;
/// @dev Address of the blob versioned hash getter smart contract used for EIP-4844 versioned hashes.
address __DEPRECATED_blobVersionedHashRetriever;
/// @dev The chainId of the chain
uint256 chainId;
/// @dev The address of the bridgehub
address bridgehub;
/// @dev The address of the ChainTypeManager
address chainTypeManager;
/// @dev The address of the baseToken contract. Eth is address(1)
address __DEPRECATED_baseToken;
/// @dev The address of the baseTokenbridge. Eth also uses the shared bridge
address __DEPRECATED_baseTokenBridge;
/// @notice gasPriceMultiplier for each baseToken, so that each L1->L2 transaction pays for its transaction on the destination
/// we multiply by the nominator, and divide by the denominator
uint128 baseTokenGasPriceMultiplierNominator;
uint128 baseTokenGasPriceMultiplierDenominator;
/// @dev The optional address of the contract that has to be used for transaction filtering/whitelisting
address transactionFilterer;
/// @dev The address of the l1DAValidator contract.
/// This contract is responsible for the verification of the correctness of the DA on L1.
address l1DAValidator;
/// @dev The address of the contract on L2 that is responsible for the data availability verification.
/// This contract sends `l2DAValidatorOutputHash` to L1 via L2->L1 system log and it will routed to the `l1DAValidator` contract.
address l2DAValidator;
/// @dev the Asset Id of the baseToken
bytes32 baseTokenAssetId;
/// @dev If this ZKchain settles on this chain, then this is zero. Otherwise it is the address of the ZKchain that is a
/// settlement layer for this ZKchain. (think about it as a 'forwarding' address for the chain that migrated away).
address settlementLayer;
/// @dev Priority tree, the new data structure for priority queue
PriorityTree.Tree priorityTree;
/// @dev Whether the chain is a permanent rollup. Note, that it only enforces the DA validator pair, but
/// it does not enforce any other parameters, e.g. `pubdataPricingMode`
bool isPermanentRollup;
/// @notice Bytecode hash of evm emulator.
/// @dev Used as an input to zkp-circuit.
bytes32 l2EvmEmulatorBytecodeHash;
/// @notice The precommitment for the latest uncommitted batch (i.e. totalBatchesCommitted + 1).
/// @dev Whenever the `totalBatchesCommitted` changes, this variable is reset to `DEFAULT_PRECOMMITMENT_FOR_THE_LAST_BATCH`
/// (the value of the constant can be found in Config.sol).
bytes32 precommitmentForTheLatestBatch;
}// 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;
/// @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 The chainId of Ethereum Mainnet
uint256 constant MAINNET_CHAIN_ID = 1;
/// @dev Timestamp - seconds since unix epoch. This value will be used on the mainnet.
uint256 constant MAINNET_COMMIT_TIMESTAMP_NOT_OLDER = 3 days;
/// @dev Timestamp - seconds since unix epoch. This value will be used on testnets.
uint256 constant TESTNET_COMMIT_TIMESTAMP_NOT_OLDER = 30 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;
/// @notice The precommitment to the transactions of the latest batch.
bytes32 precommitmentForTheLatestBatch;
}
/// @dev Used as the `msg.sender` for system service transactions.
address constant SERVICE_TRANSACTION_SENDER = address(uint160(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF));
/// @dev To avoid higher costs the writes, we avoid making the slot zero.
/// This ensures that the cost of writes is always 5k and avoids the 20k initial write from the non-zero value.
bytes32 constant DEFAULT_PRECOMMITMENT_FOR_THE_LAST_BATCH = bytes32(uint256(1));
/// @dev The length of a packed transaction precommitment in bytes. It consists of two parts: 32-byte tx hash and 1-byte status (0 or 1).
uint256 constant PACKED_L2_PRECOMMITMENT_LENGTH = 33;// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0xb325f767 error AdminZero(); // 0xca1c3cbc error AlreadyMigrated(); // 0x125d99b0 error BlobHashBlobCommitmentMismatchValue(); // 0xafda12bf error CommitBasedInteropNotSupported(); // 0xc02d3ee3 error ContractNotDeployed(); // 0xdf2c5fa5 error DependencyRootsRollingHashMismatch(bytes32 _expected, bytes32 _actual); // 0xedae13f3 error ExecutedIsNotConsistentWithVerified(uint256 batchesExecuted, uint256 batchesVerified); // 0xc866ff2c error InitialForceDeploymentMismatch(bytes32 forceDeploymentHash, bytes32 initialForceDeploymentHash); // 0xfbd630b8 error InvalidBatchesDataLength(uint256 batchesDataLength, uint256 priorityOpsDataLength); // 0x7a47c9a2 error InvalidChainId(); // 0xc06789fa error InvalidCommitment(); // 0xd2531c15 error InvalidL2DAOutputHash(bytes32 l2DAValidatorOutputHash); // 0x30043900 error InvalidNextLeafIndex(uint256 treeNextLeafIndex, uint256 commitmentNextLeafIndex); // 0xfb1a3b59 error InvalidNumberOfBatchHashes(uint256 batchHashesLength, uint256 expected); // 0xbeb96791 error InvalidNumberOfBlobs(uint256 blobsProvided, uint256 maxBlobsSupported); // 0x5513177c error InvalidPubdataHash(bytes32 fullPubdataHash, bytes32 providedPubdataHash); // 0x5717f940 error InvalidPubdataSource(uint8 pubdataSource); // 0x90f67ecf error InvalidStartIndex(uint256 treeStartIndex, uint256 commitmentStartIndex); // 0x0f67bc0a error InvalidUnprocessedIndex(uint256 treeUnprocessedIndex, uint256 commitmentUnprocessedIndex); // 0x2e89f517 error L1DAValidatorAddressIsZero(); // 0x7fbff2dd error L1DAValidatorInvalidSender(address msgSender); // 0x944bc075 error L2DAValidatorAddressIsZero(); // 0xa969e486 error LocalRootIsZero(); // 0xbdaf7d42 error LocalRootMustBeZero(); // 0x9b5f85eb error MessageRootIsZero(); // 0x2237c426 error MismatchL2DAValidator(); // 0x2c01a4af error MismatchNumberOfLayer1Txs(uint256 numberOfLayer1Txs, uint256 expectedLength); // 0xf9ba09d6 error NotAllBatchesExecuted(); // 0xf05c64c6 error NotChainAdmin(address prevMsgSender, address admin); // 0xa7050bf6 error NotHistoricalRoot(bytes32); // 0x32ddf9a2 error NotHyperchain(); // 0x87470e36 error NotL1(uint256 blockChainId); // 0xd7b2559b error NotMigrated(); // 0xd0266e26 error NotSettlementLayer(); // 0x04e05fd1 error OnlyOneBlobWithCalldataAllowed(); // 0x885ae069 error OperatorDAInputTooSmall(uint256 operatorDAInputLength, uint256 minAllowedLength); // 0x681150be error OutdatedProtocolVersion(uint256 protocolVersion, uint256 currentProtocolVersion); // 0xc59d372c error ProtocolVersionNotUpToDate(uint256 currentProtocolVersion, uint256 protocolVersion); // 0x2dc9747d error PubdataInputTooSmall(uint256 pubdataInputLength, uint256 totalBlobsCommitmentSize); // 0x9044dff9 error PubdataLengthTooBig(uint256 pubdataLength, uint256 totalBlobSizeBytes); // 0x79274f04 error UnsupportedProofMetadataVersion(uint256 metadataVersion); // 0x52595598 error ValL1DAWrongInputLength(uint256 inputLength, uint256 expectedLength); // 0x712d02d2 error VerifiedIsNotConsistentWithCommitted(uint256 batchesVerified, uint256 batchesCommitted);
// 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);
// 0x0dfb42bf
error AddressAlreadySet(address addr);
// 0x86bb51b8
error AddressHasNoCode(address);
// 0x1f73225f
error AddressMismatch(address expected, address supplied);
// 0x2a5989a0
error AlreadyPermanentRollup();
// 0x0bfcef28
error AlreadyWhitelisted(address);
// 0x5e85ae73
error AmountMustBeGreaterThanZero();
// 0xfde974f4
error AssetHandlerDoesNotExist(bytes32 assetId);
// 0x64107968
error AssetHandlerNotRegistered(bytes32 assetId);
// 0xfe919e28
error AssetIdAlreadyRegistered();
// 0x1294e9e1
error AssetIdMismatch(bytes32 expected, bytes32 supplied);
// 0x04a0b7e9
error AssetIdNotSupported(bytes32 assetId);
// 0x11832de8
error AssetRouterAllowanceNotZero();
// 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();
// 0xaa5f6180
error BurningNativeWETHNotSupported();
// 0xccdd18d2
error BytecodeAlreadyPublished(bytes32 bytecodeHash);
// 0x25d8333c
error CallerNotTimerAdmin();
// 0x3331e9c0
error CallNotAllowed(bytes call);
// 0xe85392f9
error CanOnlyProcessOneBatch();
// 0x00c6ead2
error CantExecuteUnprovenBatches();
// 0xe18cb383
error CantRevertExecutedBatch();
// 0x78d2ed02
error ChainAlreadyLive();
// 0x24591d89
error ChainIdAlreadyExists();
// 0x717a1656
error ChainIdCantBeCurrentChain();
// 0xa179f8c9
error ChainIdMismatch();
// 0x23f3c357
error ChainIdNotRegistered(uint256 chainId);
// 0x8f620a06
error ChainIdTooBig();
// 0xec273439
error CTMAlreadyRegistered();
// 0xc630ef3c
error CTMNotRegistered();
// 0x907f8e51
error DeadlineNotYetPassed();
// 0xf2885eb3
error DefaultAdminTransferNotAllowed();
// 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();
// 0x99d8fec9
error EmptyData();
// 0x95b66fe9
error EmptyDeposit();
// 0x84286507
error EmptyPrecommitData(uint256 batchNumber);
// 0x456f8f7a
error EmptyProofLength();
// 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);
// 0xd7d93e1f
error IncorrectBatchBounds(
uint256 processFromExpected,
uint256 processToExpected,
uint256 processFromProvided,
uint256 processToProvided
);
// 0xdd381a4c
error IncorrectBridgeHubAddress(address bridgehub);
// 0x1929b7de
error IncorrectTokenAddressFromNTV(bytes32 assetId, address tokenAddress);
// 0x826fb11e
error InsufficientChainBalance();
// 0x9bf8b9aa
error InvalidBatchNumber(uint256 provided, uint256 expected);
// 0xcbd9d2e0
error InvalidCaller(address);
// 0x92daded2
error InvalidDAForPermanentRollup();
// 0x4fbe5dba
error InvalidDelay();
// 0xc1780bd6
error InvalidLogSender(address sender, uint256 logKey);
// 0xa1ec1876
error InvalidMessageRoot(bytes32 expectedMessageRoot, bytes32 providedMessageRoot);
// 0xde4c0b96
error InvalidNTVBurnData();
// 0xd8e9405c
error InvalidNumberOfBlobs(uint256 expected, uint256 numCommitments, uint256 numHashes);
// 0x99f6cc22
error InvalidPackedPrecommitmentLength(uint256 length);
// 0x09bde339
error InvalidProof();
// 0x48c5fa28
error InvalidProofLengthForFinalNode();
// 0x5428eae7
error InvalidProtocolVersion();
// 0x6f1cf752
error InvalidPubdataPricingMode();
// 0x12ba286f
error InvalidSelector(bytes4 func);
// 0xbe7193d4
error InvalidSystemLogsLength();
// 0x5f1aa154
error InvalidUpgradeTxn(UpgradeTxVerifyParam);
// 0xfb5c22e6
error L2TimestampTooBig();
// 0x97e1359e
error L2WithdrawalMessageWrongLength(uint256 messageLen);
// 0x8efef97a
error LegacyBridgeNotSet();
// 0x29963361
error LegacyBridgeUsesNonNativeToken();
// 0xfade089a
error LegacyEncodingUsedForNonL1Token();
// 0x767eed08
error LegacyMethodForNonL1Token();
// 0xe37d2c02
error LengthIsNotDivisibleBy32(uint256 length);
// 0x1b6825bb
error LogAlreadyProcessed(uint8);
// 0x43e266b0
error MalformedBytecode(BytecodeError);
// 0xafbb7a4e
error MerkleIndexOrHeightMismatch();
// 0x9bb54c35
error MerkleIndexOutOfBounds();
// 0xc33e6128
error MerkleNothingToProve();
// 0x8e23ac1a
error MerklePathEmpty();
// 0x09aa9830
error MerklePathLengthMismatch(uint256 pathLength, uint256 expectedLength);
// 0x1c500385
error MerklePathOutOfBounds();
// 0x1b582fcf
error MerkleWrongIndex(uint256 index, uint256 maxNodeNumber);
// 0x485cfcaa
error MerkleWrongLength(uint256 newLeavesLength, uint256 leafNumber);
// 0x3312a450
error MigrationPaused();
// 0x4e98b356
error MigrationsNotPaused();
// 0xfa44b527
error MissingSystemLogs(uint256 expected, uint256 actual);
// 0x4a094431
error MsgValueMismatch(uint256 expectedMsgValue, uint256 providedMsgValue);
// 0xb385a3da
error MsgValueTooLow(uint256 required, uint256 provided);
// 0x8b7e144a
error NewDeadlineExceedsMaxDeadline();
// 0x6eef58d1
error NewDeadlineNotGreaterThanCurrent();
// 0x79cc2d22
error NoCallsProvided();
// 0xce63ce17
error NoCTMForAssetId(bytes32 assetId);
// 0xa6fef710
error NoFunctionsForDiamondCut();
// 0xcab098d8
error NoFundsTransferred();
// 0xb20b58ce
error NoLegacySharedBridge();
// 0xc21b1ab7
error NonEmptyCalldata();
// 0x536ec84b
error NonEmptyMsgValue();
// 0xd018e08e
error NonIncreasingTimestamp();
// 0x0105f9c0
error NonSequentialBatch();
// 0x0ac76f01
error NonSequentialVersion();
// 0xfa5cd00f
error NotAllowed(address addr);
// 0x64846fe4
error NotARestriction(address addr);
// 0xb49df1f2
error NotAZKChain(address addr);
// 0xdd7e3621
error NotInitializedReentrancyGuard();
// 0xdf17e316
error NotWhitelisted(address);
// 0xf3ed9dfa
error OnlyEraSupported();
// 0x6c167909
error OnlySelfAllowed();
// 0x1a21feed
error OperationExists();
// 0xeda2fbb1
error OperationMustBePending();
// 0xe1c1ff37
error OperationMustBeReady();
// 0xb926450e
error OriginChainIdNotFound();
// 0x688c63e5
error PrecommitmentMismatch(uint256 batchNumber, bytes32 expected, bytes32 found);
// 0x9b48e060
error PreviousOperationNotExecuted();
// 0xd5a99014
error PriorityOperationsRollingHashMismatch();
// 0x1a4d284a
error PriorityTxPubdataExceedsMaxPubDataPerBatch();
// 0xa461f651
error ProtocolIdMismatch(uint256 expectedProtocolVersion, uint256 providedProtocolId);
// 0x64f94ec2
error ProtocolIdNotGreater();
// 0x959f26fb
error PubdataGreaterThanLimit(uint256 limit, uint256 length);
// 0x63c36549
error QueueIsEmpty();
// 0xab143c06
error Reentrancy();
// 0x667d17de
error RemoveFunctionFacetAddressNotZero(address facet);
// 0xa2d4b16c
error RemoveFunctionFacetAddressZero();
// 0xf6fd7071
error RemovingPermanentRestriction();
// 0x3580370c
error ReplaceFunctionFacetAddressZero();
// 0xf126e113
error RestrictionWasAlreadyPresent(address restriction);
// 0x52e22c98
error RestrictionWasNotPresent(address restriction);
// 0x9a67c1cb
error RevertedBatchNotAfterNewLastBatch();
// 0xfe0aa4f2
error RoleAccessDenied(address chainAddress, bytes32 role, address account);
// 0xd3b6535b
error SelectorsMustAllHaveSameFreezability();
// 0x02181a13
error SettlementLayersMustSettleOnL1();
// 0x856d5b77
error SharedBridgeNotSet();
// 0x7774d2f9
error SharedBridgeValueNotSet(SharedBridgeKey);
// 0xdf3a8fdd
error SlotOccupied();
// 0xae43b424
error SystemLogsSizeTooBig();
// 0x08753982
error TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp);
// 0x7a4902ad
error TimerAlreadyStarted();
// 0x2d50c33b
error TimestampError();
// 0xa51fa558
error TokenIsLegacy();
// 0x1850b46b
error TokenNotLegacy();
// 0x06439c6b
error TokenNotSupported(address token);
// 0x23830e28
error TokensWithFeesNotSupported();
// 0x8e3ce3cb
error TooHighDeploymentNonce();
// 0x76da24b9
error TooManyFactoryDeps();
// 0xf0b4e88f
error TooMuchGas();
// 0x00c5a6a9
error TransactionNotAllowed();
// 0x4c991078
error TxHashMismatch();
// 0x2e311df8
error TxnBodyGasLimitNotEnoughGas();
// 0xfcb9b2e1
error UnallowedImplementation(bytes32 implementationHash);
// 0x8e4a23d6
error Unauthorized(address caller);
// 0xe52478c7
error UndefinedDiamondCutAction();
// 0x6aa39880
error UnexpectedSystemLog(uint256 logKey);
// 0xc352bb73
error UnknownVerifierType();
// 0xf3dd1b9c
error UnsupportedCommitBatchEncoding(uint8 version);
// 0x084a1449
error UnsupportedEncodingVersion();
// 0x14d2ed8a
error UnsupportedExecuteBatchEncoding(uint8 version);
// 0xf338f830
error UnsupportedProofBatchEncoding(uint8 version);
// 0xf093c2e5
error UpgradeBatchNumberIsNotZero();
// 0x47b3b145
error ValidateTxnNotEnoughGas();
// 0x626ade30
error ValueMismatch(uint256 expected, uint256 actual);
// 0xe1022469
error VerifiedBatchesExceedsCommittedBatches();
// 0xae899454
error WithdrawalAlreadyFinalized();
// 0x750b219c
error WithdrawFailed();
// 0xf20c5c2a
error WrappedBaseTokenAlreadyRegistered();
// 0x15e8e429
error WrongMagicValue(uint256 expectedMagicValue, uint256 providedMagicValue);
// 0xd92e233d
error ZeroAddress();
// 0xc84885d4
error ZeroChainId();
// 0x601b6882
error ZKChainLimitReached();
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 // 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 number of bits dedicated to the "patch" portion of the protocol version. /// This also defines the bit starting from which the "minor" part is located. uint256 constant SEMVER_MINOR_OFFSET = 32; /// @dev The number of bits dedicated to the "patch" and "minor" portions of the protocol version. /// This also defines the bit starting from which the "major" part is located. /// Note, that currently, only major version of "0" is supported. uint256 constant SEMVER_MAJOR_OFFSET = 64; /** * @author Matter Labs * @custom:security-contact [email protected] * @notice The library for managing SemVer for the protocol version. */ library SemVer { /// @notice Unpacks the SemVer version from a single uint256 into major, minor and patch components. /// @param _packedProtocolVersion The packed protocol version. /// @return major The major version. /// @return minor The minor version. /// @return patch The patch version. function unpackSemVer( uint96 _packedProtocolVersion ) internal pure returns (uint32 major, uint32 minor, uint32 patch) { patch = uint32(_packedProtocolVersion); minor = uint32(_packedProtocolVersion >> SEMVER_MINOR_OFFSET); major = uint32(_packedProtocolVersion >> SEMVER_MAJOR_OFFSET); } /// @notice Packs the SemVer version from the major, minor and patch components into a single uint96. /// @param _major The major version. /// @param _minor The minor version. /// @param _patch The patch version. /// @return packedProtocolVersion The packed protocol version. function packSemVer( uint32 _major, uint32 _minor, uint32 _patch ) internal pure returns (uint96 packedProtocolVersion) { packedProtocolVersion = uint96(_patch) | (uint96(_minor) << SEMVER_MINOR_OFFSET) | (uint96(_major) << SEMVER_MAJOR_OFFSET); } }
// 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 {L2Log, L2Message, TxStatus} from "../common/Messaging.sol";
import {ICTMDeploymentTracker} from "./ICTMDeploymentTracker.sol";
import {IMessageRoot} from "./IMessageRoot.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 {
/// @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 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 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,
address _chainAssetHandler
) external;
function setChainAssetHandler(address _chainAssetHandler) 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 chainAssetHandler() external view returns (address);
function registerAlreadyDeployedZKChain(uint256 _chainId, address _hyperchain) external;
function registerLegacyChain(uint256 _chainId) external;
function pauseMigration() external;
function unpauseMigration() external;
function forwardedBridgeBurnSetSettlementLayer(
uint256 _chainId,
uint256 _newSettlementLayerChainId
) external returns (address zkChain, address ctm);
function forwardedBridgeMint(
bytes32 _assetId,
uint256 _chainId,
bytes32 _baseTokenAssetId
) external returns (address zkChain, address ctm);
function registerNewZKChain(uint256 _chainId, address _zkChain, bool _checkMaxNumberOfZKChains) external;
function forwardedBridgeRecoverFailedTransfer(uint256 _chainId) external returns (address zkChain, address ctm);
}// 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 {NotInitializedReentrancyGuard, Reentrancy, SlotOccupied} from "./L1ContractErrors.sol";
/**
* @custom:security-contact [email protected]
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* _Since v2.5.0:_ this module is now much more gas efficient, given net gas
* metering changes introduced in the Istanbul hardfork.
*/
abstract contract ReentrancyGuard {
/// @dev Address of lock flag variable.
/// @dev Flag is placed at random memory location to not interfere with Storage contract.
// keccak256("ReentrancyGuard") - 1;
uint256 private constant LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4;
// solhint-disable-next-line max-line-length
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/566a774222707e424896c0c390a84dc3c13bdcb2/contracts/security/ReentrancyGuard.sol
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
modifier reentrancyGuardInitializer() {
_initializeReentrancyGuard();
_;
}
function _initializeReentrancyGuard() private {
uint256 lockSlotOldValue;
// Storing an initial non-zero value makes deployment a bit more
// expensive but in exchange every call to nonReentrant
// will be cheaper.
assembly {
lockSlotOldValue := sload(LOCK_FLAG_ADDRESS)
sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)
}
// Check that storage slot for reentrancy guard is empty to rule out possibility of slot conflict
if (lockSlotOldValue != 0) {
revert SlotOccupied();
}
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
uint256 _status;
assembly {
_status := sload(LOCK_FLAG_ADDRESS)
}
if (_status == 0) {
revert NotInitializedReentrancyGuard();
}
// On the first call to nonReentrant, _NOT_ENTERED will be true
if (_status != _NOT_ENTERED) {
revert Reentrancy();
}
// Any calls to nonReentrant after this point will fail
assembly {
sstore(LOCK_FLAG_ADDRESS, _ENTERED)
}
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
assembly {
sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// 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; /** * @author Matter Labs * @custom:security-contact [email protected] * @notice The library for unchecked math. */ library UncheckedMath { function uncheckedInc(uint256 _number) internal pure returns (uint256) { unchecked { return _number + 1; } } function uncheckedAdd(uint256 _lhs, uint256 _rhs) internal pure returns (uint256) { unchecked { return _lhs + _rhs; } } }
// 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; /// @title The interface of the ZKsync contract, responsible for the main ZKsync logic. /// @author Matter Labs /// @custom:security-contact [email protected] interface IZKChainBase { /// @return Returns facet name. function getName() external view returns (string memory); }
// 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;
/// @notice Part of the configuration parameters of ZKP circuits
struct VerifierParams {
bytes32 recursionNodeLevelVkHash;
bytes32 recursionLeafLevelVkHash;
bytes32 recursionCircuitsSetVksHash;
}
/// @title The interface of the Verifier contract, responsible for the zero knowledge proof verification.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IVerifier {
/// @dev Verifies a zk-SNARK proof.
/// @return A boolean value indicating whether the zk-SNARK proof is valid.
/// Note: The function may revert execution instead of returning false in some cases.
function verify(uint256[] calldata _publicInputs, uint256[] calldata _proof) external view returns (bool);
/// @notice Calculates a keccak256 hash of the runtime loaded verification keys.
/// @return vkHash The keccak256 hash of the loaded verification keys.
function verificationKeyHash() external view returns (bytes32);
}// 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;
}
/// @dev The structure that contains the parameters for the message root
/// @param chainId The chain id of the dependency chain
/// @param blockOrBatchNumber The block number or the batch number where the message root was created
/// For proof based interop it is block number. For commit based interop it is batch number.
/// @param sides The sides of the dynamic incremental merkle tree emitted in the L2ToL1Messenger for precommit based interop
/// For proof and commit based interop, the sides contain a single root.
struct InteropRoot {
uint256 chainId;
uint256 blockOrBatchNumber;
// We are double overloading this. The sides of the dynamic incremental merkle tree normally contains the root, as well as the sides of the tree.
// Second overloading: if the length is 1, we are importing a chainBatchRoot/messageRoot instead of sides.
bytes32[] sides;
}// 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 {VerifierParams} from "../chain-interfaces/IVerifier.sol";
import {PubdataPricingMode} from "../chain-deps/ZKChainStorage.sol";
import {IZKChainBase} from "./IZKChainBase.sol";
/// @title The interface of the Getters Contract that implements functions for getting contract state from outside the blockchain.
/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @dev Most of the methods simply return the values that correspond to the current diamond proxy and possibly
/// not to the ZK Chain as a whole. For example, if the chain is migrated to another settlement layer, the values returned
/// by this facet will correspond to the values stored on this chain and possilbly not the canonical state of the chain.
interface IGetters is IZKChainBase {
/*//////////////////////////////////////////////////////////////
CUSTOM GETTERS
//////////////////////////////////////////////////////////////*/
/// @return The address of the verifier smart contract
function getVerifier() external view returns (address);
/// @return The address of the current admin
function getAdmin() external view returns (address);
/// @return The address of the pending admin
function getPendingAdmin() external view returns (address);
/// @return The address of the bridgehub
function getBridgehub() external view returns (address);
/// @return The address of the state transition
function getChainTypeManager() external view returns (address);
/// @return The chain ID
function getChainId() external view returns (uint256);
/// @return The address of the base token
function getBaseToken() external view returns (address);
/// @return The address of the base token
function getBaseTokenAssetId() external view returns (bytes32);
/// @return The total number of batches that were committed
function getTotalBatchesCommitted() external view returns (uint256);
/// @return The total number of batches that were committed & verified
function getTotalBatchesVerified() external view returns (uint256);
/// @return The total number of batches that were committed & verified & executed
function getTotalBatchesExecuted() external view returns (uint256);
// @return Address of transaction filterer
function getTransactionFilterer() external view returns (address);
/// @return The total number of priority operations that were added to the priority queue, including all processed ones
function getTotalPriorityTxs() external view returns (uint256);
/// @return The start index of the priority tree, i.e. the index of the first priority operation that
/// was included into the priority tree.
function getPriorityTreeStartIndex() external view returns (uint256);
/// @return The root hash of the priority tree
function getPriorityTreeRoot() external view returns (bytes32);
/// @return Whether the priority queue is active, i.e. whether new priority operations are appended to it.
/// Once the chain processes all the transactions that were present in the priority queue, all the L1->L2 related
/// operations will start to get done using the priority tree.
function isPriorityQueueActive() external view returns (bool);
/// @notice The function that returns the first unprocessed priority transaction.
/// @dev Returns zero if and only if no operations were processed from the queue.
/// @dev If all the transactions were processed, it will return the last processed index, so
/// in case exactly *unprocessed* transactions are needed, one should check that getPriorityQueueSize() is greater than 0.
/// @return Index of the oldest priority operation that wasn't processed yet
function getFirstUnprocessedPriorityTx() external view returns (uint256);
/// @return The number of priority operations currently in the queue
function getPriorityQueueSize() external view returns (uint256);
/// @return Whether the address has a validator access
function isValidator(address _address) external view returns (bool);
/// @return merkleRoot Merkle root of the tree with L2 logs for the selected batch
function l2LogsRootHash(uint256 _batchNumber) external view returns (bytes32 merkleRoot);
/// @notice For unfinalized (non executed) batches may change
/// @dev returns zero for non-committed batches
/// @return The hash of committed L2 batch.
function storedBatchHash(uint256 _batchNumber) external view returns (bytes32);
/// @return Bytecode hash of bootloader program.
function getL2BootloaderBytecodeHash() external view returns (bytes32);
/// @return Bytecode hash of default account (bytecode for EOA).
function getL2DefaultAccountBytecodeHash() external view returns (bytes32);
/// @return Bytecode hash of EVM emulator.
function getL2EvmEmulatorBytecodeHash() external view returns (bytes32);
/// @return Verifier parameters.
/// @dev This function is deprecated and will soon be removed.
function getVerifierParams() external view returns (VerifierParams memory);
/// @return Whether the diamond is frozen or not
function isDiamondStorageFrozen() external view returns (bool);
/// @return The current packed protocol version. To access human-readable version, use `getSemverProtocolVersion` function.
function getProtocolVersion() external view returns (uint256);
/// @return The tuple of (major, minor, patch) protocol version.
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);
/// @return The upgrade system contract transaction hash, 0 if the upgrade is not initialized
function getL2SystemContractsUpgradeTxHash() external view returns (bytes32);
/// @return The L2 batch number in which the upgrade transaction was processed.
/// @dev It is equal to 0 in the following two cases:
/// - No upgrade transaction has ever been processed.
/// - The upgrade transaction has been processed and the batch with such transaction has been
/// executed (i.e. finalized).
function getL2SystemContractsUpgradeBatchNumber() external view returns (uint256);
/// @return The maximum number of L2 gas that a user can request for L1 -> L2 transactions
function getPriorityTxMaxGasLimit() external view returns (uint256);
/// @return Whether a withdrawal has been finalized.
/// @param _l2BatchNumber The L2 batch number within which the withdrawal happened.
/// @param _l2MessageIndex The index of the L2->L1 message denoting the withdrawal.
function isEthWithdrawalFinalized(uint256 _l2BatchNumber, uint256 _l2MessageIndex) external view returns (bool);
/// @return The pubdata pricing mode.
function getPubdataPricingMode() external view returns (PubdataPricingMode);
/// @return the baseTokenGasPriceMultiplierNominator, used to compare the baseTokenPrice to ether for L1->L2 transactions
function baseTokenGasPriceMultiplierNominator() external view returns (uint128);
/// @return the baseTokenGasPriceMultiplierDenominator, used to compare the baseTokenPrice to ether for L1->L2 transactions
function baseTokenGasPriceMultiplierDenominator() external view returns (uint128);
/*//////////////////////////////////////////////////////////////
DIAMOND LOUPE
//////////////////////////////////////////////////////////////*/
/// @notice Faсet structure compatible with the EIP-2535 diamond loupe
/// @param addr The address of the facet contract
/// @param selectors The NON-sorted array with selectors associated with facet
struct Facet {
address addr;
bytes4[] selectors;
}
/// @return result All facet addresses and their function selectors
function facets() external view returns (Facet[] memory);
/// @return NON-sorted array with function selectors supported by a specific facet
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory);
/// @return facets NON-sorted array of facet addresses supported on diamond
function facetAddresses() external view returns (address[] memory facets);
/// @return facet The facet address associated with a selector. Zero if the selector is not added to the diamond
function facetAddress(bytes4 _selector) external view returns (address facet);
/// @return Whether the selector can be frozen by the admin or always accessible
function isFunctionFreezable(bytes4 _selector) external view returns (bool);
/// @return isFreezable Whether the facet can be frozen by the admin or always accessible
function isFacetFreezable(address _facet) external view returns (bool isFreezable);
/// @return The address of the current settlement layer.
function getSettlementLayer() external view returns (address);
}// 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 {IMessageVerification} from "./IMessageVerification.sol";
import {IMailboxImpl} from "./IMailboxImpl.sol";
/// @title The interface of the ZKsync Mailbox contract that provides interfaces for L1 <-> L2 interaction.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IMailbox is IMessageVerification, IMailboxImpl {}// 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 {QueueIsEmpty} from "../../common/L1ContractErrors.sol";
/// @notice The structure that contains meta information of the L2 transaction that was requested from L1
/// @dev The weird size of fields was selected specifically to minimize the structure storage size
/// @param canonicalTxHash Hashed L2 transaction data that is needed to process it
/// @param expirationTimestamp Expiration timestamp for this request (must be satisfied before)
/// @param layer2Tip Additional payment to the validator as an incentive to perform the operation
struct PriorityOperation {
bytes32 canonicalTxHash;
uint64 expirationTimestamp;
uint192 layer2Tip;
}
/// @author Matter Labs
/// @custom:security-contact [email protected]
/// @dev The library provides the API to interact with the priority queue container
/// @dev Order of processing operations from queue - FIFO (Fist in - first out)
library PriorityQueue {
using PriorityQueue for Queue;
/// @notice Container that stores priority operations
/// @param data The inner mapping that saves priority operation by its index
/// @param head The pointer to the first unprocessed priority operation, equal to the tail if the queue is empty
/// @param tail The pointer to the free slot
struct Queue {
mapping(uint256 priorityOpId => PriorityOperation priorityOp) data;
uint256 tail;
uint256 head;
}
/// @notice Returns zero if and only if no operations were processed from the queue
/// @return Index of the oldest priority operation that wasn't processed yet
function getFirstUnprocessedPriorityTx(Queue storage _queue) internal view returns (uint256) {
return _queue.head;
}
/// @return The total number of priority operations that were added to the priority queue, including all processed ones
function getTotalPriorityTxs(Queue storage _queue) internal view returns (uint256) {
return _queue.tail;
}
/// @return The total number of unprocessed priority operations in a priority queue
function getSize(Queue storage _queue) internal view returns (uint256) {
return uint256(_queue.tail - _queue.head);
}
/// @return Whether the priority queue contains no operations
function isEmpty(Queue storage _queue) internal view returns (bool) {
return _queue.tail == _queue.head;
}
/// @notice Add the priority operation to the end of the priority queue
function pushBack(Queue storage _queue, PriorityOperation memory _operation) internal {
// Save value into the stack to avoid double reading from the storage
uint256 tail = _queue.tail;
_queue.data[tail] = _operation;
_queue.tail = tail + 1;
}
/// @return The first unprocessed priority operation from the queue
function front(Queue storage _queue) internal view returns (PriorityOperation memory) {
// priority queue is empty
if (_queue.isEmpty()) {
revert QueueIsEmpty();
}
return _queue.data[_queue.head];
}
/// @notice Remove the first unprocessed priority operation from the queue
/// @return priorityOperation that was popped from the priority queue
function popFront(Queue storage _queue) internal returns (PriorityOperation memory priorityOperation) {
// priority queue is empty
if (_queue.isEmpty()) {
revert QueueIsEmpty();
}
// Save value into the stack to avoid double reading from the storage
uint256 head = _queue.head;
priorityOperation = _queue.data[head];
delete _queue.data[head];
_queue.head = head + 1;
}
}// 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 {DynamicIncrementalMerkle} from "../../common/libraries/DynamicIncrementalMerkle.sol";
import {Merkle} from "../../common/libraries/Merkle.sol";
import {PriorityTreeCommitment} from "../../common/Config.sol";
import {InvalidCommitment, InvalidNextLeafIndex, InvalidStartIndex, InvalidUnprocessedIndex, NotHistoricalRoot} from "../L1StateTransitionErrors.sol";
struct PriorityOpsBatchInfo {
bytes32[] leftPath;
bytes32[] rightPath;
bytes32[] itemHashes;
}
bytes32 constant ZERO_LEAF_HASH = keccak256("");
library PriorityTree {
using PriorityTree for Tree;
using DynamicIncrementalMerkle for DynamicIncrementalMerkle.Bytes32PushTree;
struct Tree {
uint256 startIndex; // priority tree started accepting priority ops from this index
uint256 unprocessedIndex; // relative to `startIndex`
mapping(bytes32 => bool) historicalRoots;
DynamicIncrementalMerkle.Bytes32PushTree tree;
}
/// @notice Returns zero if and only if no operations were processed from the tree
/// @return Index of the oldest priority operation that wasn't processed yet
function getFirstUnprocessedPriorityTx(Tree storage _tree) internal view returns (uint256) {
return _tree.startIndex + _tree.unprocessedIndex;
}
/// @return The total number of priority operations that were added to the priority queue, including all processed ones
function getTotalPriorityTxs(Tree storage _tree) internal view returns (uint256) {
return _tree.startIndex + _tree.tree._nextLeafIndex;
}
/// @return The total number of unprocessed priority operations in a priority queue
function getSize(Tree storage _tree) internal view returns (uint256) {
return _tree.tree._nextLeafIndex - _tree.unprocessedIndex;
}
/// @notice Add the priority operation to the end of the priority queue
function push(Tree storage _tree, bytes32 _hash) internal {
(, bytes32 newRoot) = _tree.tree.push(_hash);
_tree.historicalRoots[newRoot] = true;
}
/// @notice Set up the tree
function setup(Tree storage _tree, uint256 _startIndex) internal {
bytes32 initialRoot = _tree.tree.setup(ZERO_LEAF_HASH);
_tree.historicalRoots[initialRoot] = true;
_tree.startIndex = _startIndex;
}
/// @return Returns the tree root.
function getRoot(Tree storage _tree) internal view returns (bytes32) {
return _tree.tree.root();
}
/// @param _root The root to check.
/// @return Returns true if the root is a historical root.
function isHistoricalRoot(Tree storage _tree, bytes32 _root) internal view returns (bool) {
return _tree.historicalRoots[_root];
}
/// @notice Process the priority operations of a batch.
/// @dev Note, that the function below only checks that a certain segment of items is present in the tree.
/// It does not check that e.g. there are no zero items inside the provided `itemHashes`, so in theory proofs
/// that include non-existing priority operations could be created. This function relies on the fact
/// that the `itemHashes` of `_priorityOpsData` are hashes of valid priority transactions.
/// This fact is ensured by the fact the rolling hash of those is sent to the Executor by the bootloader
/// and so assuming that zero knowledge proofs are correct, so is the structure of the `itemHashes`.
function processBatch(Tree storage _tree, PriorityOpsBatchInfo memory _priorityOpsData) internal {
if (_priorityOpsData.itemHashes.length > 0) {
bytes32 expectedRoot = Merkle.calculateRootPaths(
_priorityOpsData.leftPath,
_priorityOpsData.rightPath,
_tree.unprocessedIndex,
_priorityOpsData.itemHashes
);
if (!_tree.historicalRoots[expectedRoot]) {
revert NotHistoricalRoot(expectedRoot);
}
_tree.unprocessedIndex += _priorityOpsData.itemHashes.length;
}
}
/// @notice Allows to skip a certain number of operations.
/// @param _lastUnprocessed The new expected id of the unprocessed transaction.
/// @dev It is used when the corresponding transactions have been processed by priority queue.
function skipUntil(Tree storage _tree, uint256 _lastUnprocessed) internal {
if (_tree.startIndex > _lastUnprocessed) {
// Nothing to do, return
return;
}
uint256 newUnprocessedIndex = _lastUnprocessed - _tree.startIndex;
if (newUnprocessedIndex <= _tree.unprocessedIndex) {
// These transactions were already processed, skip.
return;
}
_tree.unprocessedIndex = newUnprocessedIndex;
}
/// @notice Initialize a chain from a commitment.
function initFromCommitment(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal {
uint256 height = _commitment.sides.length; // Height, including the root node.
if (height == 0) {
revert InvalidCommitment();
}
_tree.startIndex = _commitment.startIndex;
_tree.unprocessedIndex = _commitment.unprocessedIndex;
_tree.tree._nextLeafIndex = _commitment.nextLeafIndex;
_tree.tree._sides = _commitment.sides;
bytes32 zero = ZERO_LEAF_HASH;
_tree.tree._zeros = new bytes32[](height);
for (uint256 i; i < height; ++i) {
_tree.tree._zeros[i] = zero;
zero = Merkle.efficientHash(zero, zero);
}
_tree.historicalRoots[_tree.tree.root()] = true;
}
/// @notice Reinitialize the tree from a commitment on L1.
function l1Reinit(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal {
if (_tree.startIndex != _commitment.startIndex) {
revert InvalidStartIndex(_tree.startIndex, _commitment.startIndex);
}
if (_tree.unprocessedIndex > _commitment.unprocessedIndex) {
revert InvalidUnprocessedIndex(_tree.unprocessedIndex, _commitment.unprocessedIndex);
}
if (_tree.tree._nextLeafIndex < _commitment.nextLeafIndex) {
revert InvalidNextLeafIndex(_tree.tree._nextLeafIndex, _commitment.nextLeafIndex);
}
_tree.unprocessedIndex = _commitment.unprocessedIndex;
}
/// @notice Reinitialize the tree from a commitment on GW.
function checkGWReinit(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal view {
if (_tree.startIndex != _commitment.startIndex) {
revert InvalidStartIndex(_tree.startIndex, _commitment.startIndex);
}
if (_tree.unprocessedIndex > _commitment.unprocessedIndex) {
revert InvalidUnprocessedIndex(_tree.unprocessedIndex, _commitment.unprocessedIndex);
}
if (_tree.tree._nextLeafIndex > _commitment.nextLeafIndex) {
revert InvalidNextLeafIndex(_tree.tree._nextLeafIndex, _commitment.nextLeafIndex);
}
}
/// @notice Returns the commitment to the priority tree.
function getCommitment(Tree storage _tree) internal view returns (PriorityTreeCommitment memory commitment) {
commitment.nextLeafIndex = _tree.tree._nextLeafIndex;
commitment.startIndex = _tree.startIndex;
commitment.unprocessedIndex = _tree.unprocessedIndex;
commitment.sides = _tree.tree._sides;
}
}// 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
pragma solidity 0.8.28;
import {IBridgehub, L2TransactionRequestTwoBridgesInner} 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.28;
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;
function historicalRoot(uint256 _blockNumber) external view returns (bytes32);
}// 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 {L2Log, L2Message} from "../../common/Messaging.sol";
/// @title The interface of the ZKsync MessageVerification contract that can be used to prove L2 message inclusion.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IMessageVerification {
/// @notice Prove that a specific arbitrary-length message was sent in a specific L2 batch/block number.
/// @param _chainId The chain id of the L2 where the message comes from.
/// @param _blockOrBatchNumber The executed L2 batch/block number in which the message appeared.
/// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message.
/// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 batch where the message was sent.
/// @param _proof Merkle proof for inclusion of L2 log that was sent with the message.
/// @return Boolean specifying whether the proof is valid.
function proveL2MessageInclusionShared(
uint256 _chainId,
uint256 _blockOrBatchNumber,
uint256 _index,
L2Message calldata _message,
bytes32[] calldata _proof
) external view returns (bool);
/// @notice Prove that a specific L2 log was sent in a specific L2 batch.
/// @param _chainId The chain id of the L2 where the log comes from.
/// @param _blockOrBatchNumber The executed L2 batch/block number in which the log appeared.
/// @param _index The position of the l2log in the L2 logs Merkle tree.
/// @param _log Information about the sent log.
/// @param _proof Merkle proof for inclusion of the L2 log.
/// @return Whether the proof is correct and L2 log is included in batch.
function proveL2LogInclusionShared(
uint256 _chainId,
uint256 _blockOrBatchNumber,
uint256 _index,
L2Log calldata _log,
bytes32[] calldata _proof
) external view returns (bool);
/// @dev Proves that a certain leaf was included as part of the log merkle tree.
/// @dev Warning: this function does not enforce any additional checks on the structure
/// of the leaf. This means that it can accept intermediate nodes of the Merkle tree as a `_leaf` as
/// well as the default "empty" leaves. It is the responsibility of the caller to ensure that the
/// `_leaf` is a hash of a valid leaf.
/// @param _chainId The chain id of the L2 where the leaf comes from.
/// @param _blockOrBatchNumber The batch/block number of the leaf to be proven.
/// @param _leafProofMask The leaf proof mask.
/// @param _leaf The leaf to be proven.
/// @param _proof The proof.
function proveL2LeafInclusionShared(
uint256 _chainId,
uint256 _blockOrBatchNumber,
uint256 _leafProofMask,
bytes32 _leaf,
bytes32[] calldata _proof
) external view returns (bool);
}// 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 {IZKChainBase} from "./IZKChainBase.sol";
import {BridgehubL2TransactionRequest, L2CanonicalTransaction, L2Log, L2Message, TxStatus} from "../../common/Messaging.sol";
/// @title The interface of the ZKsync Mailbox contract that provides functions for L1 <-> L2 interaction.
/// @author Matter Labs
/// @custom:security-contact [email protected]
interface IMailboxImpl is IZKChainBase {
/// @notice Prove that a specific arbitrary-length message was sent in a specific L2 batch number.
/// @param _batchNumber The executed L2 batch number in which the message appeared.
/// @param _index The position in the L2 logs Merkle tree of the l2Log that was sent with the message.
/// @param _message Information about the sent message: sender address, the message itself, tx index in the L2 batch where the message was sent.
/// @param _proof Merkle proof for inclusion of L2 log that was sent with the message.
/// @return Boolean specifying whether the proof is valid.
function proveL2MessageInclusion(
uint256 _batchNumber,
uint256 _index,
L2Message calldata _message,
bytes32[] calldata _proof
) external view returns (bool);
/// @notice Prove that a specific L2 log was sent in a specific L2 batch.
/// @param _batchNumber The executed L2 batch number in which the log appeared.
/// @param _index The position of the l2log in the L2 logs Merkle tree.
/// @param _log Information about the sent log.
/// @param _proof Merkle proof for inclusion of the L2 log.
/// @return Whether the proof is correct and L2 log is included in batch.
function proveL2LogInclusion(
uint256 _batchNumber,
uint256 _index,
L2Log calldata _log,
bytes32[] calldata _proof
) external view returns (bool);
/// @notice Prove that the L1 -> L2 transaction was processed with the specified status.
/// @param _l2TxHash The L2 canonical transaction hash.
/// @param _l2BatchNumber The L2 batch number where the transaction was processed.
/// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.
/// @param _l2TxNumberInBatch The L2 transaction number in the batch, in which the log was sent.
/// @param _merkleProof The Merkle proof of the processing L1 -> L2 transaction.
/// @param _status The execution status of the L1 -> L2 transaction (true - success & 0 - fail).
/// @return Whether the proof is correct and the transaction was actually executed with provided status.
/// NOTE: It may return `false` for incorrect proof, but it doesn't mean that the L1 -> L2 transaction has an opposite status!
function proveL1ToL2TransactionStatus(
bytes32 _l2TxHash,
uint256 _l2BatchNumber,
uint256 _l2MessageIndex,
uint16 _l2TxNumberInBatch,
bytes32[] calldata _merkleProof,
TxStatus _status
) external view returns (bool);
/// @notice Finalize the withdrawal and release funds.
/// @param _l2BatchNumber The L2 batch number where the withdrawal was processed.
/// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message.
/// @param _l2TxNumberInBatch The L2 transaction number in a batch, in which the log was sent.
/// @param _message The L2 withdraw data, stored in an L2 -> L1 message.
/// @param _merkleProof The Merkle proof of the inclusion L2 -> L1 message about withdrawal initialization.
function finalizeEthWithdrawal(
uint256 _l2BatchNumber,
uint256 _l2MessageIndex,
uint16 _l2TxNumberInBatch,
bytes calldata _message,
bytes32[] calldata _merkleProof
) external;
/// @notice Request execution of L2 transaction from L1.
/// @param _contractL2 The L2 receiver address.
/// @param _l2Value `msg.value` of L2 transaction.
/// @param _calldata The input of the L2 transaction.
/// @param _l2GasLimit Maximum amount of L2 gas that transaction can consume during execution on L2.
/// @param _l2GasPerPubdataByteLimit The maximum amount L2 gas that the operator may charge the user for single byte of pubdata.
/// @param _factoryDeps An array of L2 bytecodes that will be marked as known on L2.
/// @param _refundRecipient The address on L2 that will receive the refund for the transaction.
/// @dev If the L2 deposit finalization transaction fails, the `_refundRecipient` will receive the `_l2Value`.
/// Please note, the contract may change the refund recipient's address to eliminate sending funds to addresses out of control.
/// - If `_refundRecipient` is a contract on L1, the refund will be sent to the aliased `_refundRecipient`.
/// - If `_refundRecipient` is set to `address(0)` and the sender has NO deployed bytecode on L1, the refund will be sent to the `msg.sender` address.
/// - If `_refundRecipient` is set to `address(0)` and the sender has deployed bytecode on L1, the refund will be sent to the aliased `msg.sender` address.
/// @dev The address aliasing of L1 contracts as refund recipient on L2 is necessary to guarantee that the funds are controllable,
/// since address aliasing to the from address for the L2 tx will be applied if the L1 `msg.sender` is a contract.
/// Without address aliasing for L1 contracts as refund recipients they would not be able to make proper L2 tx requests
/// through the Mailbox to use or withdraw the funds from L2, and the funds would be lost.
/// @return canonicalTxHash The hash of the requested L2 transaction. This hash can be used to follow the transaction status.
function requestL2Transaction(
address _contractL2,
uint256 _l2Value,
bytes calldata _calldata,
uint256 _l2GasLimit,
uint256 _l2GasPerPubdataByteLimit,
bytes[] calldata _factoryDeps,
address _refundRecipient
) external payable returns (bytes32 canonicalTxHash);
/// @notice Request execution of L2 transaction through the Bridgehub.
/// @dev Only accessible from L1, this is getting checked in the Bridgehub.
/// @param _request the request for the L2 transaction.
function bridgehubRequestL2Transaction(
BridgehubL2TransactionRequest calldata _request
) external returns (bytes32 canonicalTxHash);
/// @notice The chain's mailbox receives the tx from the Bridgehub on Gateway.
/// @param _canonicalTxHash the canonical transaction hash.
/// @param _expirationTimestamp the expiration timestamp for the transaction.
function bridgehubRequestL2TransactionOnGateway(bytes32 _canonicalTxHash, uint64 _expirationTimestamp) external;
/// @notice Request execution of service L2 transaction from L1.
/// @dev Used for chain configuration. Can be called only by DiamondProxy itself.
/// @param _contractL2 The L2 receiver address.
/// @param _l2Calldata The input of the L2 transaction.
function requestL2ServiceTransaction(
address _contractL2,
bytes calldata _l2Calldata
) external returns (bytes32 canonicalTxHash);
/// @dev On L1 we have to forward to the Gateway's mailbox which sends to the Bridgehub on the Gateway.
/// @param _chainId the chainId of the chain.
/// @param _canonicalTxHash the canonical transaction hash.
/// @param _expirationTimestamp the expiration timestamp.
function requestL2TransactionToGatewayMailbox(
uint256 _chainId,
bytes32 _canonicalTxHash,
uint64 _expirationTimestamp
) external returns (bytes32 canonicalTxHash);
/// @notice Estimates the cost in Ether of requesting execution of an L2 transaction from L1.
/// @param _gasPrice expected L1 gas price at which the user requests the transaction execution.
/// @param _l2GasLimit Maximum amount of L2 gas that transaction can consume during execution on L2.
/// @param _l2GasPerPubdataByteLimit The maximum amount of L2 gas that the operator may charge the user for a single byte of pubdata.
/// @return The estimated ETH spent on L2 gas for the transaction.
function l2TransactionBaseCost(
uint256 _gasPrice,
uint256 _l2GasLimit,
uint256 _l2GasPerPubdataByteLimit
) external view returns (uint256);
/// @dev Proves that a certain leaf was included as part of the log merkle tree.
/// @dev Warning: this function does not enforce any additional checks on the structure
/// of the leaf. This means that it can accept intermediate nodes of the Merkle tree as a `_leaf` as
/// well as the default "empty" leaves. It is the responsibility of the caller to ensure that the
/// `_leaf` is a hash of a valid leaf.
/// @param _batchNumber The batch number of the leaf to be proven.
/// @param _leafProofMask The leaf proof mask.
/// @param _leaf The leaf to be proven.
/// @param _proof The proof.
function proveL2LeafInclusion(
uint256 _batchNumber,
uint256 _leafProofMask,
bytes32 _leaf,
bytes32[] calldata _proof
) external view returns (bool);
/// @notice New priority request event. Emitted when a request is placed into the priority queue.
/// @param txId Serial number of the priority operation.
/// @param txHash keccak256 hash of encoded transaction representation.
/// @param expirationTimestamp Timestamp up to which priority request should be processed.
/// @param transaction The whole transaction structure that is requested to be executed on L2.
/// @param factoryDeps An array of bytecodes that were shown in the L1 public data.
/// Will be marked as known bytecodes in L2.
event NewPriorityRequest(
uint256 txId,
bytes32 txHash,
uint64 expirationTimestamp,
L2CanonicalTransaction transaction,
bytes[] factoryDeps
);
/// @notice New relayed priority request event. It is emitted on a chain that is deployed
/// on top of the gateway when it receives a request relayed via the Bridgehub.
/// @dev IMPORTANT: this event most likely will be removed in the future, so
/// no one should rely on it for indexing purposes.
/// @param txId Serial number of the priority operation.
/// @param txHash keccak256 hash of encoded transaction representation.
/// @param expirationTimestamp Timestamp up to which priority request should be processed.
event NewRelayedPriorityTransaction(uint256 txId, bytes32 txHash, uint64 expirationTimestamp);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {Merkle} from "./Merkle.sol";
import {Arrays} from "@openzeppelin/contracts-v4/utils/Arrays.sol";
/**
* @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.
*
* Each tree is a complete binary tree with the ability to sequentially insert leaves, changing them from a zero to a
* non-zero value and updating its root. This structure allows inserting commitments (or other entries) that are not
* stored, but can be proven to be part of the tree at a later time if the root is kept. See {MerkleProof}.
*
* A tree is defined by the following parameters:
*
* * Depth: The number of levels in the tree, it also defines the maximum number of leaves as 2**depth.
* * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree.
* * Hashing function: A cryptographic hash function used to produce internal nodes.
*
* This is a fork of OpenZeppelin's [`MerkleTree`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/9af280dc4b45ee5bda96ba47ff829b407eaab67e/contracts/utils/structs/MerkleTree.sol)
* library, with the changes to support dynamic tree growth (doubling the size when full).
*/
library DynamicIncrementalMerkle {
/**
* @dev A complete `bytes32` Merkle tree.
*
* The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup.
*
* Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
* directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
* lead to unexpected behavior.
*
* NOTE: The `root` and the updates history is not stored within the tree. Consider using a secondary structure to
* store a list of historical roots from the values returned from {setup} and {push} (e.g. a mapping, {BitMaps} or
* {Checkpoints}).
*
* WARNING: Updating any of the tree's parameters after the first insertion will result in a corrupted tree.
*/
struct Bytes32PushTree {
uint256 _nextLeafIndex;
bytes32[] _sides;
bytes32[] _zeros;
}
/**
* @dev Initialize a {Bytes32PushTree} using {Hashes-Keccak256} to hash internal nodes.
* The capacity of the tree (i.e. number of leaves) is set to `2**levels`.
*
* IMPORTANT: The zero value should be carefully chosen since it will be stored in the tree representing
* empty leaves. It should be a value that is not expected to be part of the tree.
*/
function setup(Bytes32PushTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) {
self._nextLeafIndex = 0;
self._zeros.push(zero);
self._sides.push(bytes32(0));
return bytes32(0);
}
/**
* @dev Resets the tree to a blank state.
* Calling this function on MerkleTree that was already setup and used will reset it to a blank state.
* @param zero The value that represents an empty leaf.
* @return initialRoot The initial root of the tree.
*/
function reset(Bytes32PushTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) {
self._nextLeafIndex = 0;
uint256 length = self._zeros.length;
for (uint256 i = length; 0 < i; --i) {
self._zeros.pop();
}
length = self._sides.length;
for (uint256 i = length; 0 < i; --i) {
self._sides.pop();
}
self._zeros.push(zero);
self._sides.push(bytes32(0));
return bytes32(0);
}
/**
* @dev Insert a new leaf in the tree, and compute the new root. Returns the position of the inserted leaf in the
* tree, and the resulting root.
*
* Hashing the leaf before calling this function is recommended as a protection against
* second pre-image attacks.
*/
function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) {
// Cache read
uint256 levels = self._zeros.length - 1;
// Get leaf index
// solhint-disable-next-line gas-increment-by-one
index = self._nextLeafIndex++;
// Check if tree is full.
if (index == 1 << levels) {
bytes32 zero = self._zeros[levels];
bytes32 newZero = Merkle.efficientHash(zero, zero);
self._zeros.push(newZero);
self._sides.push(bytes32(0));
++levels;
}
// Rebuild branch from leaf to root
uint256 currentIndex = index;
bytes32 currentLevelHash = leaf;
bool updatedSides = false;
for (uint32 i = 0; i < levels; ++i) {
// Reaching the parent node, is currentLevelHash the left child?
bool isLeft = currentIndex % 2 == 0;
// If so, next time we will come from the right, so we need to save it
if (isLeft && !updatedSides) {
Arrays.unsafeAccess(self._sides, i).value = currentLevelHash;
updatedSides = true;
}
// Compute the current node hash by using the hash function
// with either its sibling (side) or the zero value for that level.
currentLevelHash = Merkle.efficientHash(
isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value,
isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash
);
// Update node index
currentIndex >>= 1;
}
Arrays.unsafeAccess(self._sides, levels).value = currentLevelHash;
return (index, currentLevelHash);
}
/**
* @dev Tree's root.
*/
function root(Bytes32PushTree storage self) internal view returns (bytes32) {
return Arrays.unsafeAccess(self._sides, self._sides.length - 1).value;
}
/**
* @dev Tree's height (does not include the root node).
*/
function height(Bytes32PushTree storage self) internal view returns (uint256) {
return self._sides.length - 1;
}
}// 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 {UncheckedMath} from "../../common/libraries/UncheckedMath.sol";
import {MerkleIndexOrHeightMismatch, MerkleIndexOutOfBounds, MerkleNothingToProve, MerklePathEmpty, MerklePathLengthMismatch, MerklePathOutOfBounds} from "../../common/L1ContractErrors.sol";
/// @author Matter Labs
/// @custom:security-contact [email protected]
library Merkle {
using UncheckedMath for uint256;
/// @dev Calculate Merkle root by the provided Merkle proof.
/// NOTE: When using this function, check that the _path length is equal to the tree height to prevent shorter/longer paths attack
/// however, for chains settling on GW the proof includes the GW proof, so the path increases. See Mailbox for more details.
/// @param _path Merkle path from the leaf to the root
/// @param _index Leaf index in the tree
/// @param _itemHash Hash of leaf content
/// @return The Merkle root
function calculateRoot(
bytes32[] calldata _path,
uint256 _index,
bytes32 _itemHash
) internal pure returns (bytes32) {
uint256 pathLength = _path.length;
_validatePathLengthForSingleProof(_index, pathLength);
bytes32 currentHash = _itemHash;
for (uint256 i; i < pathLength; i = i.uncheckedInc()) {
currentHash = (_index % 2 == 0)
? efficientHash(currentHash, _path[i])
: efficientHash(_path[i], currentHash);
_index /= 2;
}
return currentHash;
}
/// @dev Calculate Merkle root by the provided Merkle proof.
/// @dev NOTE: When using this function, check that the _path length is appropriate to prevent shorter/longer paths attack
/// @param _path Merkle path from the leaf to the root
/// @param _index Leaf index in the tree.
/// @dev NOTE the tree can be joined. In this case the second tree's leaves indexes increase by the number of leaves in the first tree.
/// @param _itemHash Hash of leaf content
/// @return The Merkle root
function calculateRootMemory(
bytes32[] memory _path,
uint256 _index,
bytes32 _itemHash
) internal pure returns (bytes32) {
uint256 pathLength = _path.length;
_validatePathLengthForSingleProof(_index, pathLength);
bytes32 currentHash = _itemHash;
for (uint256 i; i < pathLength; i = i.uncheckedInc()) {
currentHash = (_index % 2 == 0)
? efficientHash(currentHash, _path[i])
: efficientHash(_path[i], currentHash);
_index /= 2;
}
return currentHash;
}
/// @dev Calculate Merkle root by the provided Merkle proof for a range of elements
/// NOTE: When using this function, check that the _startPath and _endPath lengths are equal to the tree height to prevent shorter/longer paths attack
/// @param _startPath Merkle path from the first element of the range to the root
/// @param _endPath Merkle path from the last element of the range to the root
/// @param _startIndex Index of the first element of the range in the tree
/// @param _itemHashes Hashes of the elements in the range
/// @return The Merkle root
function calculateRootPaths(
bytes32[] memory _startPath,
bytes32[] memory _endPath,
uint256 _startIndex,
bytes32[] memory _itemHashes
) internal pure returns (bytes32) {
uint256 pathLength = _startPath.length;
if (pathLength != _endPath.length) {
revert MerklePathLengthMismatch(pathLength, _endPath.length);
}
if (pathLength >= 256) {
revert MerklePathOutOfBounds();
}
uint256 levelLen = _itemHashes.length;
// Edge case: we want to be able to prove an element in a single-node tree.
if (pathLength == 0 && (_startIndex != 0 || levelLen != 1)) {
revert MerklePathEmpty();
}
if (levelLen == 0) {
revert MerkleNothingToProve();
}
if (_startIndex + levelLen > (1 << pathLength)) {
revert MerkleIndexOrHeightMismatch();
}
bytes32[] memory itemHashes = _itemHashes;
for (uint256 level; level < pathLength; level = level.uncheckedInc()) {
uint256 parity = _startIndex % 2;
// We get an extra element on the next level if on the current level elements either
// start on an odd index (`parity == 1`) or end on an even index (`levelLen % 2 == 1`)
uint256 nextLevelLen = levelLen / 2 + (parity | (levelLen % 2));
for (uint256 i; i < nextLevelLen; i = i.uncheckedInc()) {
bytes32 lhs = (i == 0 && parity == 1) ? _startPath[level] : itemHashes[2 * i - parity];
bytes32 rhs = (i == nextLevelLen - 1 && (levelLen - parity) % 2 == 1)
? _endPath[level]
: itemHashes[2 * i + 1 - parity];
itemHashes[i] = efficientHash(lhs, rhs);
}
levelLen = nextLevelLen;
_startIndex /= 2;
}
return itemHashes[0];
}
/// @dev Keccak hash of the concatenation of two 32-byte words
function efficientHash(bytes32 _lhs, bytes32 _rhs) internal pure returns (bytes32 result) {
assembly {
mstore(0x00, _lhs)
mstore(0x20, _rhs)
result := keccak256(0x00, 0x40)
}
}
function _validatePathLengthForSingleProof(uint256 _index, uint256 _pathLength) private pure {
if (_pathLength >= 256) {
revert MerklePathOutOfBounds();
}
if (_index >= (1 << _pathLength)) {
revert MerkleIndexOutOfBounds();
}
}
}// 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);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
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);
function L1_CHAIN_ID() external view returns (uint256);
/// @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 pragma solidity 0.8.28; /// @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.0) (utils/Arrays.sol)
pragma solidity ^0.8.0;
import "./StorageSlot.sol";
import "./math/Math.sol";
/**
* @dev Collection of functions related to array types.
*/
library Arrays {
using StorageSlot for bytes32;
/**
* @dev Searches a sorted `array` and returns the first index that contains
* a value greater or equal to `element`. If no such index exists (i.e. all
* values in the array are strictly less than `element`), the array length is
* returned. Time complexity O(log n).
*
* `array` is expected to be sorted in ascending order, and to contain no
* repeated elements.
*/
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
if (array.length == 0) {
return 0;
}
uint256 low = 0;
uint256 high = array.length;
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds down (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getAddressSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getBytes32Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.
/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
}
return slot.getUint256Slot();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}{
"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/",
"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": 9999999
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"_bridgehub","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminZero","type":"error"},{"inputs":[],"name":"ChainAlreadyLive","type":"error"},{"inputs":[],"name":"GenesisBatchCommitmentZero","type":"error"},{"inputs":[],"name":"GenesisBatchHashZero","type":"error"},{"inputs":[],"name":"GenesisIndexStorageZero","type":"error"},{"inputs":[],"name":"GenesisUpgradeZero","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"HashMismatch","type":"error"},{"inputs":[{"internalType":"bytes32","name":"forceDeploymentHash","type":"bytes32"},{"internalType":"bytes32","name":"initialForceDeploymentHash","type":"bytes32"}],"name":"InitialForceDeploymentMismatch","type":"error"},{"inputs":[],"name":"MigrationsNotPaused","type":"error"},{"inputs":[{"internalType":"uint256","name":"protocolVersion","type":"uint256"},{"internalType":"uint256","name":"currentProtocolVersion","type":"uint256"}],"name":"OutdatedProtocolVersion","type":"error"},{"inputs":[],"name":"SlotOccupied","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_zkChain","type":"address"},{"components":[{"internalType":"uint256","name":"txType","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPerPubdataByteLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"paymaster","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256[4]","name":"reserved","type":"uint256[4]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256[]","name":"factoryDeps","type":"uint256[]"},{"internalType":"bytes","name":"paymasterInput","type":"bytes"},{"internalType":"bytes","name":"reservedDynamic","type":"bytes"}],"indexed":false,"internalType":"struct L2CanonicalTransaction","name":"_l2Transaction","type":"tuple"},{"indexed":true,"internalType":"uint256","name":"_protocolVersion","type":"uint256"}],"name":"GenesisUpgrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"genesisUpgrade","type":"address"},{"indexed":false,"internalType":"bytes32","name":"genesisBatchHash","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"genesisIndexRepeatedStorageChanges","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"genesisBatchCommitment","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"indexed":false,"internalType":"struct Diamond.DiamondCutData","name":"newInitialCut","type":"tuple"},{"indexed":false,"internalType":"bytes32","name":"newInitialCutHash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"forceDeploymentsData","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"forceDeploymentHash","type":"bytes32"}],"name":"NewChainCreationParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldProtocolVersion","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newProtocolVersion","type":"uint256"}],"name":"NewProtocolVersion","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldServerNotifier","type":"address"},{"indexed":true,"internalType":"address","name":"newServerNotifier","type":"address"}],"name":"NewServerNotifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"protocolVersion","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"indexed":false,"internalType":"struct Diamond.DiamondCutData","name":"diamondCutData","type":"tuple"}],"name":"NewUpgradeCutData","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"protocolVersion","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"upgradeCutHash","type":"bytes32"}],"name":"NewUpgradeCutHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValidatorTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newValidatorTimelock","type":"address"}],"name":"NewValidatorTimelock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValidatorTimelockPostV29","type":"address"},{"indexed":true,"internalType":"address","name":"newvalidatorTimelockPostV29","type":"address"}],"name":"NewValidatorTimelockPostV29","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_zkChainContract","type":"address"}],"name":"NewZKChain","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"protocolVersion","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"UpdateProtocolVersionDeadline","type":"event"},{"inputs":[],"name":"BRIDGE_HUB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"components":[{"internalType":"enum PubdataPricingMode","name":"pubdataPricingMode","type":"uint8"},{"internalType":"uint32","name":"batchOverheadL1Gas","type":"uint32"},{"internalType":"uint32","name":"maxPubdataPerBatch","type":"uint32"},{"internalType":"uint32","name":"maxL2GasPerBatch","type":"uint32"},{"internalType":"uint32","name":"priorityTxMaxPubdata","type":"uint32"},{"internalType":"uint64","name":"minimalL2GasPrice","type":"uint64"}],"internalType":"struct FeeParams","name":"_newFeeParams","type":"tuple"}],"name":"changeFeeParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes32","name":"_baseTokenAssetId","type":"bytes32"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes","name":"_initData","type":"bytes"},{"internalType":"bytes[]","name":"_factoryDeps","type":"bytes[]"}],"name":"createNewChain","outputs":[{"internalType":"address","name":"zkChainAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"_diamondCut","type":"tuple"}],"name":"executeUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"forwardedBridgeBurn","outputs":[{"internalType":"bytes","name":"ctmForwardedBridgeMintData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bytes","name":"_ctmData","type":"bytes"}],"name":"forwardedBridgeMint","outputs":[{"internalType":"address","name":"chainAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"forwardedBridgeRecoverFailedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"freezeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getChainAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getHyperchain","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getProtocolVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSemverProtocolVersion","outputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getZKChain","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"getZKChainLegacy","outputs":[{"internalType":"address","name":"chainAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialCutHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialForceDeploymentHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"validatorTimelock","type":"address"},{"components":[{"internalType":"address","name":"genesisUpgrade","type":"address"},{"internalType":"bytes32","name":"genesisBatchHash","type":"bytes32"},{"internalType":"uint64","name":"genesisIndexRepeatedStorageChanges","type":"uint64"},{"internalType":"bytes32","name":"genesisBatchCommitment","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"diamondCut","type":"tuple"},{"internalType":"bytes","name":"forceDeploymentsData","type":"bytes"}],"internalType":"struct ChainCreationParams","name":"chainCreationParams","type":"tuple"},{"internalType":"uint256","name":"protocolVersion","type":"uint256"},{"internalType":"address","name":"serverNotifier","type":"address"}],"internalType":"struct ChainTypeManagerInitializeData","name":"_initializeData","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1GenesisUpgrade","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":[],"name":"protocolVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolVersion","type":"uint256"}],"name":"protocolVersionDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolVersion","type":"uint256"}],"name":"protocolVersionIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_newLastBatch","type":"uint256"}],"name":"revertBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serverNotifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"genesisUpgrade","type":"address"},{"internalType":"bytes32","name":"genesisBatchHash","type":"bytes32"},{"internalType":"uint64","name":"genesisIndexRepeatedStorageChanges","type":"uint64"},{"internalType":"bytes32","name":"genesisBatchCommitment","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"diamondCut","type":"tuple"},{"internalType":"bytes","name":"forceDeploymentsData","type":"bytes"}],"internalType":"struct ChainCreationParams","name":"_chainCreationParams","type":"tuple"}],"name":"setChainCreationParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_validatorTimelock","type":"address"}],"name":"setLegacyValidatorTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"_cutData","type":"tuple"},{"internalType":"uint256","name":"_oldProtocolVersion","type":"uint256"},{"internalType":"uint256","name":"_oldProtocolVersionDeadline","type":"uint256"},{"internalType":"uint256","name":"_newProtocolVersion","type":"uint256"}],"name":"setNewVersionUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPendingAdmin","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"bool","name":"_zkPorterIsAvailable","type":"bool"}],"name":"setPorterAvailability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_maxGasLimit","type":"uint256"}],"name":"setPriorityTxMaxGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolVersion","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"setProtocolVersionDeadline","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_serverNotifier","type":"address"}],"name":"setServerNotifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint128","name":"_nominator","type":"uint128"},{"internalType":"uint128","name":"_denominator","type":"uint128"}],"name":"setTokenMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"_cutData","type":"tuple"},{"internalType":"uint256","name":"_oldProtocolVersion","type":"uint256"}],"name":"setUpgradeDiamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_validator","type":"address"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_validatorTimelockPostV29","type":"address"}],"name":"setValidatorTimelockPostV29","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"storedBatchZero","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"unfreezeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_oldProtocolVersion","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"facet","type":"address"},{"internalType":"enum Diamond.Action","name":"action","type":"uint8"},{"internalType":"bool","name":"isFreezable","type":"bool"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct Diamond.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"initAddress","type":"address"},{"internalType":"bytes","name":"initCalldata","type":"bytes"}],"internalType":"struct Diamond.DiamondCutData","name":"_diamondCut","type":"tuple"}],"name":"upgradeChainFromVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"protocolVersion","type":"uint256"}],"name":"upgradeCutHash","outputs":[{"internalType":"bytes32","name":"cutHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorTimelock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorTimelockPostV29","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a060405234801561000f575f5ffd5b5060405161508738038061508783398101604081905261002e91610157565b610036610051565b6001600160a01b03811660805261004b61009b565b50610184565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf48054600190915580156100985760405163df3a8fdd60e01b815260040160405180910390fd5b50565b5f54610100900460ff16156101065760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614610155575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f60208284031215610167575f5ffd5b81516001600160a01b038116811461017d575f5ffd5b9392505050565b608051614eb36101d45f395f818161046901528181610a780152818161110a015281816112370152818161163e0152818161169b01528181611aaa01528181611ceb0152611f8b0152614eb35ff3fe608060405234801561000f575f5ffd5b506004361061030f575f3560e01c80639b016b8b1161019d578063e66c8c44116100e8578063f13ea17811610093578063f5c1182c1161006e578063f5c1182c146106f0578063f851a4401461071f578063f85894c51461073f575f5ffd5b8063f13ea1781461069e578063f2fde38b146106be578063f4943a20146106d1575f5ffd5b8063ea9f186a116100c3578063ea9f186a14610658578063ec3d5f881461066b578063ef9955bc1461067e575f5ffd5b8063e66c8c4414610614578063e680c4c114610632578063e8a71ca914610645575f5ffd5b8063d2ef1b0e11610148578063dfa3ae2011610123578063dfa3ae20146105d0578063e30c3978146105e3578063e34a329a14610601575f5ffd5b8063d2ef1b0e14610582578063dead6f7f1461058b578063def9d6af1461059e575f5ffd5b8063b784610711610178578063b784610714610547578063ba2389471461055c578063cf347e171461056f575f5ffd5b80639b016b8b1461050e578063aad7426214610521578063accdd16c14610534575f5ffd5b806352c9eacb1161025d57806379ba50971161020857806388c7c5d2116101e357806388c7c5d2146104ca5780638da5cb5b146104dd57806398461504146104fb575f5ffd5b806379ba50971461049c5780637ebba672146104a457806384e9e6bc146104b7575f5ffd5b80635d4edca7116102385780635d4edca71461046457806361f91b2e1461048b578063715018a614610494575f5ffd5b806352c9eacb1461042957806353ce20611461044857806357e6246b1461045b575f5ffd5b80632e522851116102bd5780634caa740f116102985780634caa740f146103f05780634dd18bf51461040357806351d218f714610416575f5ffd5b80632e52285114610385578063301e7765146103985780633437949a146103d0575f5ffd5b806318717dc1116102ed57806318717dc114610343578063250045f0146103565780632ae9c60014610369575f5ffd5b8063027f12e1146103135780630dbad27e146103285780630e18b6811461033b575b5f5ffd5b6103266103213660046126e8565b61075f565b005b610326610336366004612723565b6107d9565b610326610856565b61032661035136600461277c565b610989565b6103266103643660046127db565b6109f0565b610372609d5481565b6040519081526020015b60405180910390f35b6103266103933660046127f6565b610a6e565b6103ab6103a6366004612846565b610c68565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037c565b609c546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b6103ab6103fe366004612846565b610ce4565b6103266104113660046127db565b610cf7565b610326610424366004612846565b610de6565b610372610437366004612846565b60a06020525f908152604090205481565b61032661045636600461285d565b610e4d565b610372609b5481565b6103ab7f000000000000000000000000000000000000000000000000000000000000000081565b61037260a35481565b610326610ebb565b610326610ece565b6103266104b236600461289c565b610f83565b6103266104c53660046127db565b611002565b6103ab6104d8366004612913565b6110f1565b60335473ffffffffffffffffffffffffffffffffffffffff166103ab565b6103266105093660046129d9565b61131f565b61032661051c366004612a1b565b6113ad565b61032661052f36600461285d565b6113be565b610326610542366004612846565b6113d4565b610326610555366004612a55565b5050505050565b61037261056a366004612846565b611429565b61032661057d366004612aba565b61149f565b610372609a5481565b6103ab610599366004612846565b61150e565b6105c06105ac366004612846565b5f908152609e602052604090205442111590565b604051901515815260200161037c565b6103266105de3660046127db565b611546565b60655473ffffffffffffffffffffffffffffffffffffffff166103ab565b61032661060f366004612af9565b6115c4565b609f5473ffffffffffffffffffffffffffffffffffffffff166103ab565b6103ab610640366004612846565b61160d565b6103ab610653366004612b3d565b611698565b610326610666366004612b85565b611805565b61032661067936600461285d565b611970565b60a5546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b60a4546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b6103266106cc3660046127db565b6119bb565b6103726106df366004612846565b609e6020525f908152604090205481565b6106f8611a6b565b6040805163ffffffff9485168152928416602084015292169181019190915260600161037c565b60a1546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b61075261074d366004612b3d565b611aa6565b60405161037c9190612c08565b610767611d9b565b6107708261160d565b73ffffffffffffffffffffffffffffffffffffffff166364bf8d66826040518263ffffffff1660e01b81526004016107a89190612c44565b5f604051808303815f87803b1580156107bf575f5ffd5b505af11580156107d1573d5f5f3e3d5ffd5b505050505050565b6107e1611d9b565b6107ea8361160d565b73ffffffffffffffffffffffffffffffffffffffff1663fc57565f83836040518363ffffffff1660e01b815260040161082492919061301b565b5f604051808303815f87803b15801561083b575f5ffd5b505af115801561084d573d5f5f3e3d5ffd5b50505050505050565b60a25473ffffffffffffffffffffffffffffffffffffffff163381146108af576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60a1805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560a280549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b610991611d9b565b61099a8261160d565b6040517f1cc5d103000000000000000000000000000000000000000000000000000000008152821515600482015273ffffffffffffffffffffffffffffffffffffffff9190911690631cc5d103906024016107a8565b6109f8611d9b565b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5a1b0d8808a8dca64c1f7c230dce7a09f7f9a1c26507e190e03dcd382e69018e905f90a35050565b610a76611d9b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632a6411146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b039190613033565b610b39576040517f4e98b35600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84604051602001610b4b919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120609d545f88815260a090945291909220829055909150610ba18585611e1c565b610bcb837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611e1c565b609d839055604051839082907f4235104f56661fe2e9d2f2a460b42766581bc45ce366c6a30a9f86c8a2b371a7905f90a3604051829086907f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d4905f90a3827ff99295383247eabb6bee8798669fa768502f8843d3be0e82a0aa81d7b6c4f60c87604051610c58919061304e565b60405180910390a2505050505050565b5f610c728261160d565b73ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cde919061306b565b92915050565b5f610cf0609783611e6c565b9392505050565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590610d37575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15610d70576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b60a2805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b610dee611d9b565b610df78161160d565b73ffffffffffffffffffffffffffffffffffffffff1663173389456040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e3b575f5ffd5b505af1158015610555573d5f5f3e3d5ffd5b610e55611d9b565b5f610e5f8361160d565b6040517f7ca4eff700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820181905260248201859052919250637ca4eff790604401610824565b610ec3611d9b565b610ecc5f611e89565b565b606554339073ffffffffffffffffffffffffffffffffffffffff168114610f77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016108a6565b610f8081611e89565b50565b610f8b611d9b565b610f948361160d565b6040517f235d9eb50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff80851660048301528316602482015273ffffffffffffffffffffffffffffffffffffffff919091169063235d9eb590604401610824565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590611042575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1561107b576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b60a4805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907ff1bf439d66c9b504465c611d5dc8b1783c659a56ef1cc8cce45ef25f8d776271905f90a35050565b5f3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611163576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80611171868801886131e5565b915091506111818a8a8a85611eba565b92505f816040516020016111959190612c08565b60405160208183030381529060405280519060200120905060a35481146111f65760a3546040517fc866ff2c0000000000000000000000000000000000000000000000000000000081526108a6918391600401918252602082015260400190565b508273ffffffffffffffffffffffffffffffffffffffff16632878fe74609c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cbe836126040518163ffffffff1660e01b8152600401602060405180830381865afa15801561129e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c2919061306b565b8489896040518663ffffffff1660e01b81526004016112e5959493929190613240565b5f604051808303815f87803b1580156112fc575f5ffd5b505af115801561130e573d5f5f3e3d5ffd5b505050505050979650505050505050565b611327611d9b565b5f82604051602001611339919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f86815260a0909252918120829055909250829184917f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d491a3505050565b6113b5611d9b565b610f80816120fe565b6113c6611d9b565b6113d08282611e1c565b5050565b6113dc611d9b565b6113e58161160d565b73ffffffffffffffffffffffffffffffffffffffff166327ae4c166040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e3b575f5ffd5b5f6114338261160d565b73ffffffffffffffffffffffffffffffffffffffff166333ce93fe6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561147b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cde9190613312565b6114a7611d9b565b6114b08361160d565b6040517f4623c91d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283151560248301529190911690634623c91d90604401610824565b5f5f61151983610ce4565b905073ffffffffffffffffffffffffffffffffffffffff81161561153d5792915050565b610cf08361160d565b61154e611d9b565b60a5805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5acf5609801e97f7381592d19507a255c163e54bc5d4a80bec80b90e9587b1b6905f90a35050565b6115cc611d9b565b6115d58261160d565b73ffffffffffffffffffffffffffffffffffffffff1663a9f6d941826040518263ffffffff1660e01b81526004016107a8919061304e565b6040517fe680c4c1000000000000000000000000000000000000000000000000000000008152600481018290525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e680c4c190602401602060405180830381865afa158015610cba573d5f5f3e3d5ffd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370d8af876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611702573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611726919061306b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461178c576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80808061179c86880188613329565b9350935093509350609d5482146117ed57609d546040517f681150be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018390526044016108a6565b6117f988858584611eba565b98975050505050505050565b61180d6124f9565b5f61181b60208301836127db565b73ffffffffffffffffffffffffffffffffffffffff1603611868576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61187d61187860208301836127db565b611e89565b6060810135609d8190556118b1907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611e1c565b6118c160408201602083016127db565b60a580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561191660a08201608083016127db565b60a480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055610f8061196b6040830183613388565b6120fe565b611978611d9b565b6119818261160d565b73ffffffffffffffffffffffffffffffffffffffff1663be6f11cf826040518263ffffffff1660e01b81526004016107a891815260200190565b6119c3611d9b565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611a2660335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f5f5f611a9b611a7c609d54612559565b63ffffffff604082901c169167ffffffffffffffff602083901c169190565b925092509250909192565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370d8af876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b11573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b35919061306b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b9b576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80611ba9848601866133c4565b909250905073ffffffffffffffffffffffffffffffffffffffff8216611bfb576040517fb325f76700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611c058761160d565b73ffffffffffffffffffffffffffffffffffffffff166333ce93fe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c719190613312565b9050609d548114611cbc57609d546040517f681150be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108a6565b6040517fe52db4ca000000000000000000000000000000000000000000000000000000008152600481018890527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e52db4ca90602401602060405180830381865afa158015611d45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d699190613312565b609d54604051611d809291869186906020016133fb565b60405160208183030381529060405293505050509392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108a6565b5f828152609e6020526040908190208290555182907fe324f73c212a1daf595f28bb1f7324cf37dedcfb1f8e07f122bd87daa927ceed90611e609084815260200190565b60405180910390a25050565b5f808080611e7a86866125fa565b909450925050505b9250929050565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610f8081612632565b5f80611ec58661160d565b73ffffffffffffffffffffffffffffffffffffffff1614611f12576040517f78d2ed0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82806020019051810190611f2791906134a5565b83516020850120609b54919250908114611f7b57609b546040517f0b08d5be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108a6565b506060633675035760e01b875f1b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff165f1b3073ffffffffffffffffffffffffffffffffffffffff165f1b609d545f1b8973ffffffffffffffffffffffffffffffffffffffff165f1b60a55f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165f1b8c609a548a604001516040516020016120559a999897969594939291906136b8565b60405160208183030381529060405290508082604001819052505f5f5f1b4684604051612081906126c5565b61208c929190613734565b8190604051809103905ff59050801580156120a9573d5f5f3e3d5ffd5b5090508093508373ffffffffffffffffffffffffffffffffffffffff16887ff83c256407747903308213919067f883f683c5cde6a64ebbf25096b8bb555ddc60405160405180910390a3505050949350505050565b5f61210c60208301836127db565b73ffffffffffffffffffffffffffffffffffffffff1603612159576040517f3a1a858900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020810135612194576040517f7940c83f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6121a560608301604084016138b7565b67ffffffffffffffff16036121e6576040517fb4fc683500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810135612221576040517f6d4a7df800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61222e60208201826127db565b609c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905560408051610120810182525f8082526020848101359083015291818101906122a190606086019086016138b7565b67ffffffffffffffff1681526020015f81526020017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f1b81526020015f5f1b81526020015f5f1b81526020015f8152602001836060013581525090508060405160200161238291905f6101208201905067ffffffffffffffff83511682526020830151602083015267ffffffffffffffff6040840151166040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609a555f6123c960808401846138d0565b6040516020016123d9919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609b81905590505f61242460a0850185613902565b604051602001612435929190613963565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209182012060a381905591507f78533eeda9f2d7a68099b21fd160302020d3e480e3646d52e2098122b8fff34f906124a0908601866127db565b60208601356124b560608801604089016138b7565b60608801356124c760808a018a6138d0565b876124d560a08c018c613902565b896040516124eb99989796959493929190613976565b60405180910390a150505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4805460019091558015610f80576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6bffffffffffffffffffffffff8211156125f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016108a6565b5090565b5f8181526002830160205260408120548190806126275761261b85856126a8565b92505f9150611e829050565b600192509050611e82565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f610cf083835f8181526001830160205260408120541515610cf0565b61148b806139f383390190565b5f60c082840312156126e2575f5ffd5b50919050565b5f5f60e083850312156126f9575f5ffd5b8235915061270a84602085016126d2565b90509250929050565b5f606082840312156126e2575f5ffd5b5f5f5f60608486031215612735575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115612759575f5ffd5b61276586828701612713565b9150509250925092565b8015158114610f80575f5ffd5b5f5f6040838503121561278d575f5ffd5b82359150602083013561279f8161276f565b809150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f80575f5ffd5b80356127d6816127aa565b919050565b5f602082840312156127eb575f5ffd5b8135610cf0816127aa565b5f5f5f5f60808587031215612809575f5ffd5b843567ffffffffffffffff81111561281f575f5ffd5b61282b87828801612713565b97602087013597506040870135966060013595509350505050565b5f60208284031215612856575f5ffd5b5035919050565b5f5f6040838503121561286e575f5ffd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff811681146127d6575f5ffd5b5f5f5f606084860312156128ae575f5ffd5b833592506128be6020850161287d565b91506128cc6040850161287d565b90509250925092565b5f5f83601f8401126128e5575f5ffd5b50813567ffffffffffffffff8111156128fc575f5ffd5b602083019150836020828501011115611e82575f5ffd5b5f5f5f5f5f5f5f60a0888a031215612929575f5ffd5b87359650602088013595506040880135612942816127aa565b9450606088013567ffffffffffffffff81111561295d575f5ffd5b6129698a828b016128d5565b909550935050608088013567ffffffffffffffff811115612988575f5ffd5b8801601f81018a13612998575f5ffd5b803567ffffffffffffffff8111156129ae575f5ffd5b8a60208260051b84010111156129c2575f5ffd5b602082019350809250505092959891949750929550565b5f5f604083850312156129ea575f5ffd5b823567ffffffffffffffff811115612a00575f5ffd5b612a0c85828601612713565b95602094909401359450505050565b5f60208284031215612a2b575f5ffd5b813567ffffffffffffffff811115612a41575f5ffd5b612a4d848285016126d2565b949350505050565b5f5f5f5f5f60808688031215612a69575f5ffd5b85359450602086013593506040860135612a82816127aa565b9250606086013567ffffffffffffffff811115612a9d575f5ffd5b612aa9888289016128d5565b969995985093965092949392505050565b5f5f5f60608486031215612acc575f5ffd5b833592506020840135612ade816127aa565b91506040840135612aee8161276f565b809150509250925092565b5f5f60408385031215612b0a575f5ffd5b82359150602083013567ffffffffffffffff811115612b27575f5ffd5b612b3385828601612713565b9150509250929050565b5f5f5f60408486031215612b4f575f5ffd5b83359250602084013567ffffffffffffffff811115612b6c575f5ffd5b612b78868287016128d5565b9497909650939450505050565b5f60208284031215612b95575f5ffd5b813567ffffffffffffffff811115612bab575f5ffd5b820160a08185031215610cf0575f5ffd5b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f610cf06020830184612bbc565b803563ffffffff811681146127d6575f5ffd5b803567ffffffffffffffff811681146127d6575f5ffd5b60c08101823560028110801590612c59575f5ffd5b50825263ffffffff612c6d60208501612c1a565b16602083015263ffffffff612c8460408501612c1a565b16604083015263ffffffff612c9b60608501612c1a565b166060830152612cad60808401612c1a565b63ffffffff166080830152612cc460a08401612c2d565b67ffffffffffffffff811660a08401525092915050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d0e575f5ffd5b830160208101925035905067ffffffffffffffff811115612d2d575f5ffd5b8060051b3603821315611e82575f5ffd5b60038110610f80575f5ffd5b60038110612d7f577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610f80575f5ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612de3575f5ffd5b830160208101925035905067ffffffffffffffff811115612e02575f5ffd5b803603821315611e82575f5ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f60608301612e668384612cdb565b606086528281845260808701905060808260051b8801019350825f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81853603015b84821015612fc4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a88030184528235818112612ee3575f5ffd5b8601608088018135612ef4816127aa565b73ffffffffffffffffffffffffffffffffffffffff1689526020820135612f1a81612d3e565b612f2760208b0182612d4a565b506040820135612f368161276f565b151560408a0152612f4a6060830183612cdb565b608060608c0152918290529091505f60a08a015b83821015612fa8578235612f7181612d83565b7fffffffff000000000000000000000000000000000000000000000000000000001681526020928301926001929092019101612f5e565b9950505060209485019493909301925060019190910190612ea7565b505050505050612fd6602084016127cb565b73ffffffffffffffffffffffffffffffffffffffff166020850152612ffe6040840184612db0565b8583036040870152613011838284612e10565b9695505050505050565b828152604060208201525f612a4d6040830184612e57565b5f60208284031215613043575f5ffd5b8151610cf08161276f565b602081525f610cf06020830184612e57565b80516127d6816127aa565b5f6020828403121561307b575f5ffd5b8151610cf0816127aa565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156130d6576130d6613086565b60405290565b6040516080810167ffffffffffffffff811182821017156130d6576130d6613086565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561314657613146613086565b604052919050565b5f67ffffffffffffffff82111561316757613167613086565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126131a2575f5ffd5b81356131b56131b08261314e565b6130ff565b8181528460208386010111156131c9575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156131f6575f5ffd5b823567ffffffffffffffff81111561320c575f5ffd5b61321885828601613193565b925050602083013567ffffffffffffffff811115613234575f5ffd5b612b3385828601613193565b73ffffffffffffffffffffffffffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152608060408201525f61328a6080830186612bbc565b8281036060840152838152602080820190600586901b830101865f5b87811015613302577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030184526132df828a612db0565b6132ea858284612e10565b602096870196909550939093019250506001016132a6565b50909a9950505050505050505050565b5f60208284031215613322575f5ffd5b5051919050565b5f5f5f5f6080858703121561333c575f5ffd5b84359350602085013561334e816127aa565b925060408501359150606085013567ffffffffffffffff811115613370575f5ffd5b61337c87828801613193565b91505092959194509250565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126133ba575f5ffd5b9190910192915050565b5f5f604083850312156133d5575f5ffd5b82356133e0816127aa565b9150602083013567ffffffffffffffff811115613234575f5ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152826040820152608060608201525f6130116080830184612bbc565b5f67ffffffffffffffff82111561344e5761344e613086565b5060051b60200190565b5f82601f830112613467575f5ffd5b81516134756131b08261314e565b818152846020838601011115613489575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f602082840312156134b5575f5ffd5b815167ffffffffffffffff8111156134cb575f5ffd5b8201606081850312156134dc575f5ffd5b6134e46130b3565b815167ffffffffffffffff8111156134fa575f5ffd5b8201601f8101861361350a575f5ffd5b80516135186131b082613435565b8082825260208201915060208360051b850101925088831115613539575f5ffd5b602084015b8381101561366d57805167ffffffffffffffff81111561355c575f5ffd5b85016080818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561358f575f5ffd5b6135976130dc565b60208201516135a5816127aa565b815260408201516135b581612d3e565b602082015260608201516135c88161276f565b6040820152608082015167ffffffffffffffff8111156135e6575f5ffd5b6020818401019250508b601f8301126135fd575f5ffd5b815161360b6131b082613435565b8082825260208201915060208360051b86010192508e83111561362c575f5ffd5b6020850194505b8285101561365757845161364681612d83565b825260209485019490910190613633565b606084015250508452506020928301920161353e565b5084525061368091505060208301613060565b6020820152604082015167ffffffffffffffff81111561369e575f5ffd5b6136aa86828501613458565b604083015250949350505050565b7fffffffff000000000000000000000000000000000000000000000000000000008b1681528960048201528860248201528760448201528660648201528560848201528460a48201528360c48201528260e48201525f8251806020850161010485015e5f920161010401918252509a9950505050505050505050565b828152604060208201525f60a0820183516060604085015281815180845260c08601915060c08160051b87010193506020830192505f5b8181101561385a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4087860301835283516080860173ffffffffffffffffffffffffffffffffffffffff825116875260208201516137cc6020890182612d4a565b50604082015115156040880152606082015191506080606088015280825180835260a0890191506020840193505f92505b80831015613842577fffffffff0000000000000000000000000000000000000000000000000000000084511682526020820191506020840193506001830192506137fd565b5096505050602093840193929092019160010161376b565b50505050602084015173ffffffffffffffffffffffffffffffffffffffff16606084015260408401518382037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00160808501526130118282612bbc565b5f602082840312156138c7575f5ffd5b610cf082612c2d565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126133ba575f5ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613935575f5ffd5b83018035915067ffffffffffffffff82111561394f575f5ffd5b602001915036819003821315611e82575f5ffd5b602081525f612a4d602083018486612e10565b73ffffffffffffffffffffffffffffffffffffffff8a16815288602082015267ffffffffffffffff8816604082015286606082015261010060808201525f6139c2610100830188612e57565b8660a084015282810360c08401526139db818688612e10565b9150508260e08301529a995050505050505050505056fe608060405234801561000f575f5ffd5b5060405161148b38038061148b83398101604081905261002e91610e3c565b4682146100675760405162461bcd60e51b8152602060048201526002602482015261383960f11b60448201526064015b60405180910390fd5b61007081610077565b50506111c6565b80516020820151604083015182515f5b818110156101d5575f8582815181106100a2576100a2610fdb565b60200260200101516020015190505f8683815181106100c3576100c3610fdb565b60200260200101515f015190505f8784815181106100e3576100e3610fdb565b60200260200101516040015190505f88858151811061010457610104610fdb565b602002602001015160600151905080515f0361013357604051630a6fef7160e41b815260040160405180910390fd5b5f84600281111561014657610146610fef565b0361015b57610156838284610222565b6101bb565b600184600281111561016f5761016f610fef565b0361017f5761015683828461034a565b600284600281111561019357610193610fef565b036101a2576101568382610457565b60405163e52478c760e01b815260040160405180910390fd5b505050506101ce8161055560201b60201c565b9050610087565b506101e0838361055b565b7f87b829356b3403d36217eff1f66ee48eacd0a69015153aba4f0de29fe5340c3084848460405161021393929190611031565b60405180910390a15050505050565b5f51602061146b5f395f51905f526001600160a01b0384163b5f03610265576040516310d76a3760e31b81526001600160a01b038516600482015260240161005e565b61026e8461069c565b82515f5b81811015610342575f85828151811061028d5761028d610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250901561032d57805160405163158947f360e31b81526001600160e01b0319841660048201526001600160a01b03909116602482015260440161005e565b610338888388610741565b5050600101610272565b505050505050565b5f51602061146b5f395f51905f526001600160a01b0384163b5f0361038d576040516310d76a3760e31b81526001600160a01b038516600482015260240161005e565b82515f5b81811015610342575f8582815181106103ac576103ac610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff161515918101919091529092509061042d57604051630d600dc360e21b815260040160405180910390fd5b805161043990836108e6565b6104428861069c565b61044d888388610741565b5050600101610391565b5f51602061146b5f395f51905f526001600160a01b038316156104985760405163333e8bef60e11b81526001600160a01b038416600482015260240161005e565b81515f5b8181101561054e575f8482815181106104b7576104b7610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff1615159181019190915290925090610538576040516328b52c5b60e21b815260040160405180910390fd5b805161054490836108e6565b505060010161049c565b5050505050565b60010190565b6001600160a01b03821661058d578051156105895760405163c21b1ab760e01b815260040160405180910390fd5b5050565b5f5f836001600160a01b0316836040516105a79190611147565b5f60405180830381855af49150503d805f81146105df576040519150601f19603f3d011682016040523d82523d5f602084013e6105e4565b606091505b50915091508161061b57600481511015610613578060405163f7a01e4d60e01b815260040161005e919061115d565b805160208201fd5b805160201461063f578060405163f7a01e4d60e01b815260040161005e919061115d565b7f33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a25f1b818060200190518101906106769190611176565b14610696578060405163f7a01e4d60e01b815260040161005e919061115d565b50505050565b6001600160a01b0381165f9081525f51602061144b5f395f51905f5260205260408120545f51602061146b5f395f51905f529181900361073c5760028201546106e490610acc565b6001600160a01b0384165f81815260018581016020908152604083208201805461ffff191661ffff96909616959095179094556002860180549182018155825292902090910180546001600160a01b03191690911790555b505050565b6001600160a01b0383165f9081525f51602061144b5f395f51905f5260205260408120545f51602061146b5f395f51905f52919061077e90610acc565b905061ffff81161561081d576001600160a01b0385165f9081526001830160205260408120805482906107b3576107b3610fdb565b5f918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03198116835290859052604090912054909150600160b01b900460ff1615158415151461081b5760405163d3b6535b60e01b815260040160405180910390fd5b505b604080516060810182526001600160a01b0396871680825261ffff93841660208084019182529615158385019081526001600160e01b031989165f90815287895285812094518554935192519b166001600160b01b031990931692909217600160a01b91909616029490941760ff60b01b1916600160b01b981515989098029790971790559481526001918201835293842080549182018155845292206008830401805463ffffffff60079094166004026101000a938402191660e09290921c92909202179055565b6001600160e01b031981165f9081525f51602061146b5f395f51905f5260208181526040808420546001600160a01b03871685525f51602061144b5f395f51905f529092528320549192600160a01b90910461ffff16916109499060019061118d565b9050808214610a43576001600160a01b0385165f908152600184016020526040812080548390811061097d5761097d610fdb565b5f91825260208083206008830401546001600160a01b038a168452600188019091526040909220805460079092166004026101000a90920460e01b9250829190859081106109cd576109cd610fdb565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c0217905550610a0a83610acc60201b60201c565b6001600160e01b03199091165f908152602085905260409020805461ffff92909216600160a01b0261ffff60a01b199092169190911790555b6001600160a01b0385165f9081526001840160205260409020805480610a6b57610a6b6111b2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319861682528490526040812080546001600160b81b031916905581900361054e5761054e85610b32565b5f61ffff821115610b2e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b606482015260840161005e565b5090565b6001600160a01b0381165f9081525f51602061144b5f395f51905f52602052604081206001908101547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d545f51602061146b5f395f51905f529361ffff90921692610b9c9161118d565b9050808214610c4e575f836002018281548110610bbb57610bbb610fdb565b5f918252602090912001546002850180546001600160a01b039092169250829185908110610beb57610beb610fdb565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055610c1c83610acc565b6001600160a01b03919091165f9081526001858101602052604090912001805461ffff191661ffff9092169190911790555b82600201805480610c6157610c616111b2565b5f8281526020902081015f1990810180546001600160a01b031916905501905550505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715610cbd57610cbd610c87565b60405290565b604051608081016001600160401b0381118282101715610cbd57610cbd610c87565b604051601f8201601f191681016001600160401b0381118282101715610d0d57610d0d610c87565b604052919050565b5f6001600160401b03821115610d2d57610d2d610c87565b5060051b60200190565b80516001600160a01b0381168114610d4d575f5ffd5b919050565b5f82601f830112610d61575f5ffd5b8151610d74610d6f82610d15565b610ce5565b8082825260208201915060208360051b860101925085831115610d95575f5ffd5b602085015b83811015610dc75780516001600160e01b031981168114610db9575f5ffd5b835260209283019201610d9a565b5095945050505050565b5f82601f830112610de0575f5ffd5b81516001600160401b03811115610df957610df9610c87565b610e0c601f8201601f1916602001610ce5565b818152846020838601011115610e20575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f60408385031215610e4d575f5ffd5b825160208401519092506001600160401b03811115610e6a575f5ffd5b830160608186031215610e7b575f5ffd5b610e83610c9b565b81516001600160401b03811115610e98575f5ffd5b8201601f81018713610ea8575f5ffd5b8051610eb6610d6f82610d15565b8082825260208201915060208360051b850101925089831115610ed7575f5ffd5b602084015b83811015610f8d5780516001600160401b03811115610ef9575f5ffd5b85016080818d03601f19011215610f0e575f5ffd5b610f16610cc3565b610f2260208301610d37565b8152604082015160038110610f35575f5ffd5b602082015260608201518015158114610f4c575f5ffd5b604082015260808201516001600160401b03811115610f69575f5ffd5b610f788e602083860101610d52565b60608301525084525060209283019201610edc565b50845250610fa091505060208301610d37565b602082015260408201516001600160401b03811115610fbd575f5ffd5b610fc987828501610dd1565b60408301525080925050509250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f606082016060835280865180835260808501915060808160051b8601019250602088015f5b8281101561111857868503607f19018452815180516001600160a01b03168652602081015160808701906003811061109d57634e487b7160e01b5f52602160045260245ffd5b80602089015250604082015115156040880152606082015191506080606088015280825180835260a0890191506020840193505f92505b808310156111005783516001600160e01b031916825260209384019360019390930192909101906110d4565b50965050506020938401939190910190600101611057565b5050506001600160a01b038616602085015250828103604084015261113d8185611003565b9695505050505050565b5f82518060208501845e5f920191825250919050565b602081525f61116f6020830184611003565b9392505050565b5f60208284031215611186575f5ffd5b5051919050565b818103818111156111ac57634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603160045260245ffd5b610278806111d35f395ff3fe60806040527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b600436101580610033575036155b61009e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f557400000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b5f80357fffffffff0000000000000000000000000000000000000000000000000000000016815260208281526040918290208251606081018452905473ffffffffffffffffffffffffffffffffffffffff811680835274010000000000000000000000000000000000000000820461ffff1693830193909352760100000000000000000000000000000000000000000000900460ff16151592810192909252806101a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f46000000000000000000000000000000000000000000000000000000000000006044820152606401610095565b600383015460ff1615806101ba57508160400151155b610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f71310000000000000000000000000000000000000000000000000000000000006044820152606401610095565b604051365f82375f5f3683855af43d805f843e81801561023e578184f35b8184fdfea264697066735822122003dea0923a2d888969d5a8361432ef4d7cadb69970e0d9fd6baf728e0eef05fb64736f6c634300081c0033c8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131cc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ba264697066735822122022f1c500017c619636a8ad2191ae4a7d164c70a8fbc0956872bbf8f759fa852064736f6c634300081c0033000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce
Deployed Bytecode
0x608060405234801561000f575f5ffd5b506004361061030f575f3560e01c80639b016b8b1161019d578063e66c8c44116100e8578063f13ea17811610093578063f5c1182c1161006e578063f5c1182c146106f0578063f851a4401461071f578063f85894c51461073f575f5ffd5b8063f13ea1781461069e578063f2fde38b146106be578063f4943a20146106d1575f5ffd5b8063ea9f186a116100c3578063ea9f186a14610658578063ec3d5f881461066b578063ef9955bc1461067e575f5ffd5b8063e66c8c4414610614578063e680c4c114610632578063e8a71ca914610645575f5ffd5b8063d2ef1b0e11610148578063dfa3ae2011610123578063dfa3ae20146105d0578063e30c3978146105e3578063e34a329a14610601575f5ffd5b8063d2ef1b0e14610582578063dead6f7f1461058b578063def9d6af1461059e575f5ffd5b8063b784610711610178578063b784610714610547578063ba2389471461055c578063cf347e171461056f575f5ffd5b80639b016b8b1461050e578063aad7426214610521578063accdd16c14610534575f5ffd5b806352c9eacb1161025d57806379ba50971161020857806388c7c5d2116101e357806388c7c5d2146104ca5780638da5cb5b146104dd57806398461504146104fb575f5ffd5b806379ba50971461049c5780637ebba672146104a457806384e9e6bc146104b7575f5ffd5b80635d4edca7116102385780635d4edca71461046457806361f91b2e1461048b578063715018a614610494575f5ffd5b806352c9eacb1461042957806353ce20611461044857806357e6246b1461045b575f5ffd5b80632e522851116102bd5780634caa740f116102985780634caa740f146103f05780634dd18bf51461040357806351d218f714610416575f5ffd5b80632e52285114610385578063301e7765146103985780633437949a146103d0575f5ffd5b806318717dc1116102ed57806318717dc114610343578063250045f0146103565780632ae9c60014610369575f5ffd5b8063027f12e1146103135780630dbad27e146103285780630e18b6811461033b575b5f5ffd5b6103266103213660046126e8565b61075f565b005b610326610336366004612723565b6107d9565b610326610856565b61032661035136600461277c565b610989565b6103266103643660046127db565b6109f0565b610372609d5481565b6040519081526020015b60405180910390f35b6103266103933660046127f6565b610a6e565b6103ab6103a6366004612846565b610c68565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037c565b609c546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b6103ab6103fe366004612846565b610ce4565b6103266104113660046127db565b610cf7565b610326610424366004612846565b610de6565b610372610437366004612846565b60a06020525f908152604090205481565b61032661045636600461285d565b610e4d565b610372609b5481565b6103ab7f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce81565b61037260a35481565b610326610ebb565b610326610ece565b6103266104b236600461289c565b610f83565b6103266104c53660046127db565b611002565b6103ab6104d8366004612913565b6110f1565b60335473ffffffffffffffffffffffffffffffffffffffff166103ab565b6103266105093660046129d9565b61131f565b61032661051c366004612a1b565b6113ad565b61032661052f36600461285d565b6113be565b610326610542366004612846565b6113d4565b610326610555366004612a55565b5050505050565b61037261056a366004612846565b611429565b61032661057d366004612aba565b61149f565b610372609a5481565b6103ab610599366004612846565b61150e565b6105c06105ac366004612846565b5f908152609e602052604090205442111590565b604051901515815260200161037c565b6103266105de3660046127db565b611546565b60655473ffffffffffffffffffffffffffffffffffffffff166103ab565b61032661060f366004612af9565b6115c4565b609f5473ffffffffffffffffffffffffffffffffffffffff166103ab565b6103ab610640366004612846565b61160d565b6103ab610653366004612b3d565b611698565b610326610666366004612b85565b611805565b61032661067936600461285d565b611970565b60a5546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b60a4546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b6103266106cc3660046127db565b6119bb565b6103726106df366004612846565b609e6020525f908152604090205481565b6106f8611a6b565b6040805163ffffffff9485168152928416602084015292169181019190915260600161037c565b60a1546103ab9073ffffffffffffffffffffffffffffffffffffffff1681565b61075261074d366004612b3d565b611aa6565b60405161037c9190612c08565b610767611d9b565b6107708261160d565b73ffffffffffffffffffffffffffffffffffffffff166364bf8d66826040518263ffffffff1660e01b81526004016107a89190612c44565b5f604051808303815f87803b1580156107bf575f5ffd5b505af11580156107d1573d5f5f3e3d5ffd5b505050505050565b6107e1611d9b565b6107ea8361160d565b73ffffffffffffffffffffffffffffffffffffffff1663fc57565f83836040518363ffffffff1660e01b815260040161082492919061301b565b5f604051808303815f87803b15801561083b575f5ffd5b505af115801561084d573d5f5f3e3d5ffd5b50505050505050565b60a25473ffffffffffffffffffffffffffffffffffffffff163381146108af576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60a1805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560a280549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b610991611d9b565b61099a8261160d565b6040517f1cc5d103000000000000000000000000000000000000000000000000000000008152821515600482015273ffffffffffffffffffffffffffffffffffffffff9190911690631cc5d103906024016107a8565b6109f8611d9b565b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5a1b0d8808a8dca64c1f7c230dce7a09f7f9a1c26507e190e03dcd382e69018e905f90a35050565b610a76611d9b565b7f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff16632a6411146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b039190613033565b610b39576040517f4e98b35600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84604051602001610b4b919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120609d545f88815260a090945291909220829055909150610ba18585611e1c565b610bcb837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611e1c565b609d839055604051839082907f4235104f56661fe2e9d2f2a460b42766581bc45ce366c6a30a9f86c8a2b371a7905f90a3604051829086907f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d4905f90a3827ff99295383247eabb6bee8798669fa768502f8843d3be0e82a0aa81d7b6c4f60c87604051610c58919061304e565b60405180910390a2505050505050565b5f610c728261160d565b73ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cde919061306b565b92915050565b5f610cf0609783611e6c565b9392505050565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590610d37575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15610d70576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b60a2805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b610dee611d9b565b610df78161160d565b73ffffffffffffffffffffffffffffffffffffffff1663173389456040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e3b575f5ffd5b505af1158015610555573d5f5f3e3d5ffd5b610e55611d9b565b5f610e5f8361160d565b6040517f7ca4eff700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820181905260248201859052919250637ca4eff790604401610824565b610ec3611d9b565b610ecc5f611e89565b565b606554339073ffffffffffffffffffffffffffffffffffffffff168114610f77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084016108a6565b610f8081611e89565b50565b610f8b611d9b565b610f948361160d565b6040517f235d9eb50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff80851660048301528316602482015273ffffffffffffffffffffffffffffffffffffffff919091169063235d9eb590604401610824565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590611042575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1561107b576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b60a4805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907ff1bf439d66c9b504465c611d5dc8b1783c659a56ef1cc8cce45ef25f8d776271905f90a35050565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce1614611163576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80611171868801886131e5565b915091506111818a8a8a85611eba565b92505f816040516020016111959190612c08565b60405160208183030381529060405280519060200120905060a35481146111f65760a3546040517fc866ff2c0000000000000000000000000000000000000000000000000000000081526108a6918391600401918252602082015260400190565b508273ffffffffffffffffffffffffffffffffffffffff16632878fe74609c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff1663cbe836126040518163ffffffff1660e01b8152600401602060405180830381865afa15801561129e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c2919061306b565b8489896040518663ffffffff1660e01b81526004016112e5959493929190613240565b5f604051808303815f87803b1580156112fc575f5ffd5b505af115801561130e573d5f5f3e3d5ffd5b505050505050979650505050505050565b611327611d9b565b5f82604051602001611339919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f86815260a0909252918120829055909250829184917f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d491a3505050565b6113b5611d9b565b610f80816120fe565b6113c6611d9b565b6113d08282611e1c565b5050565b6113dc611d9b565b6113e58161160d565b73ffffffffffffffffffffffffffffffffffffffff166327ae4c166040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e3b575f5ffd5b5f6114338261160d565b73ffffffffffffffffffffffffffffffffffffffff166333ce93fe6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561147b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cde9190613312565b6114a7611d9b565b6114b08361160d565b6040517f4623c91d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283151560248301529190911690634623c91d90604401610824565b5f5f61151983610ce4565b905073ffffffffffffffffffffffffffffffffffffffff81161561153d5792915050565b610cf08361160d565b61154e611d9b565b60a5805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5acf5609801e97f7381592d19507a255c163e54bc5d4a80bec80b90e9587b1b6905f90a35050565b6115cc611d9b565b6115d58261160d565b73ffffffffffffffffffffffffffffffffffffffff1663a9f6d941826040518263ffffffff1660e01b81526004016107a8919061304e565b6040517fe680c4c1000000000000000000000000000000000000000000000000000000008152600481018290525f907f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff169063e680c4c190602401602060405180830381865afa158015610cba573d5f5f3e3d5ffd5b5f7f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff166370d8af876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611702573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611726919061306b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461178c576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80808061179c86880188613329565b9350935093509350609d5482146117ed57609d546040517f681150be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018390526044016108a6565b6117f988858584611eba565b98975050505050505050565b61180d6124f9565b5f61181b60208301836127db565b73ffffffffffffffffffffffffffffffffffffffff1603611868576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61187d61187860208301836127db565b611e89565b6060810135609d8190556118b1907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611e1c565b6118c160408201602083016127db565b60a580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561191660a08201608083016127db565b60a480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055610f8061196b6040830183613388565b6120fe565b611978611d9b565b6119818261160d565b73ffffffffffffffffffffffffffffffffffffffff1663be6f11cf826040518263ffffffff1660e01b81526004016107a891815260200190565b6119c3611d9b565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611a2660335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f5f5f611a9b611a7c609d54612559565b63ffffffff604082901c169167ffffffffffffffff602083901c169190565b925092509250909192565b60607f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff166370d8af876040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b11573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b35919061306b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b9b576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108a6565b5f80611ba9848601866133c4565b909250905073ffffffffffffffffffffffffffffffffffffffff8216611bfb576040517fb325f76700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611c058761160d565b73ffffffffffffffffffffffffffffffffffffffff166333ce93fe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c719190613312565b9050609d548114611cbc57609d546040517f681150be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108a6565b6040517fe52db4ca000000000000000000000000000000000000000000000000000000008152600481018890527f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff169063e52db4ca90602401602060405180830381865afa158015611d45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d699190613312565b609d54604051611d809291869186906020016133fb565b60405160208183030381529060405293505050509392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108a6565b5f828152609e6020526040908190208290555182907fe324f73c212a1daf595f28bb1f7324cf37dedcfb1f8e07f122bd87daa927ceed90611e609084815260200190565b60405180910390a25050565b5f808080611e7a86866125fa565b909450925050505b9250929050565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610f8081612632565b5f80611ec58661160d565b73ffffffffffffffffffffffffffffffffffffffff1614611f12576040517f78d2ed0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82806020019051810190611f2791906134a5565b83516020850120609b54919250908114611f7b57609b546040517f0b08d5be0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108a6565b506060633675035760e01b875f1b7f000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce73ffffffffffffffffffffffffffffffffffffffff165f1b3073ffffffffffffffffffffffffffffffffffffffff165f1b609d545f1b8973ffffffffffffffffffffffffffffffffffffffff165f1b60a55f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165f1b8c609a548a604001516040516020016120559a999897969594939291906136b8565b60405160208183030381529060405290508082604001819052505f5f5f1b4684604051612081906126c5565b61208c929190613734565b8190604051809103905ff59050801580156120a9573d5f5f3e3d5ffd5b5090508093508373ffffffffffffffffffffffffffffffffffffffff16887ff83c256407747903308213919067f883f683c5cde6a64ebbf25096b8bb555ddc60405160405180910390a3505050949350505050565b5f61210c60208301836127db565b73ffffffffffffffffffffffffffffffffffffffff1603612159576040517f3a1a858900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020810135612194576040517f7940c83f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6121a560608301604084016138b7565b67ffffffffffffffff16036121e6576040517fb4fc683500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810135612221576040517f6d4a7df800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61222e60208201826127db565b609c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905560408051610120810182525f8082526020848101359083015291818101906122a190606086019086016138b7565b67ffffffffffffffff1681526020015f81526020017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f1b81526020015f5f1b81526020015f5f1b81526020015f8152602001836060013581525090508060405160200161238291905f6101208201905067ffffffffffffffff83511682526020830151602083015267ffffffffffffffff6040840151166040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010083015161010083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609a555f6123c960808401846138d0565b6040516020016123d9919061304e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609b81905590505f61242460a0850185613902565b604051602001612435929190613963565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209182012060a381905591507f78533eeda9f2d7a68099b21fd160302020d3e480e3646d52e2098122b8fff34f906124a0908601866127db565b60208601356124b560608801604089016138b7565b60608801356124c760808a018a6138d0565b876124d560a08c018c613902565b896040516124eb99989796959493929190613976565b60405180910390a150505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4805460019091558015610f80576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6bffffffffffffffffffffffff8211156125f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016108a6565b5090565b5f8181526002830160205260408120548190806126275761261b85856126a8565b92505f9150611e829050565b600192509050611e82565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f610cf083835f8181526001830160205260408120541515610cf0565b61148b806139f383390190565b5f60c082840312156126e2575f5ffd5b50919050565b5f5f60e083850312156126f9575f5ffd5b8235915061270a84602085016126d2565b90509250929050565b5f606082840312156126e2575f5ffd5b5f5f5f60608486031215612735575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115612759575f5ffd5b61276586828701612713565b9150509250925092565b8015158114610f80575f5ffd5b5f5f6040838503121561278d575f5ffd5b82359150602083013561279f8161276f565b809150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f80575f5ffd5b80356127d6816127aa565b919050565b5f602082840312156127eb575f5ffd5b8135610cf0816127aa565b5f5f5f5f60808587031215612809575f5ffd5b843567ffffffffffffffff81111561281f575f5ffd5b61282b87828801612713565b97602087013597506040870135966060013595509350505050565b5f60208284031215612856575f5ffd5b5035919050565b5f5f6040838503121561286e575f5ffd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff811681146127d6575f5ffd5b5f5f5f606084860312156128ae575f5ffd5b833592506128be6020850161287d565b91506128cc6040850161287d565b90509250925092565b5f5f83601f8401126128e5575f5ffd5b50813567ffffffffffffffff8111156128fc575f5ffd5b602083019150836020828501011115611e82575f5ffd5b5f5f5f5f5f5f5f60a0888a031215612929575f5ffd5b87359650602088013595506040880135612942816127aa565b9450606088013567ffffffffffffffff81111561295d575f5ffd5b6129698a828b016128d5565b909550935050608088013567ffffffffffffffff811115612988575f5ffd5b8801601f81018a13612998575f5ffd5b803567ffffffffffffffff8111156129ae575f5ffd5b8a60208260051b84010111156129c2575f5ffd5b602082019350809250505092959891949750929550565b5f5f604083850312156129ea575f5ffd5b823567ffffffffffffffff811115612a00575f5ffd5b612a0c85828601612713565b95602094909401359450505050565b5f60208284031215612a2b575f5ffd5b813567ffffffffffffffff811115612a41575f5ffd5b612a4d848285016126d2565b949350505050565b5f5f5f5f5f60808688031215612a69575f5ffd5b85359450602086013593506040860135612a82816127aa565b9250606086013567ffffffffffffffff811115612a9d575f5ffd5b612aa9888289016128d5565b969995985093965092949392505050565b5f5f5f60608486031215612acc575f5ffd5b833592506020840135612ade816127aa565b91506040840135612aee8161276f565b809150509250925092565b5f5f60408385031215612b0a575f5ffd5b82359150602083013567ffffffffffffffff811115612b27575f5ffd5b612b3385828601612713565b9150509250929050565b5f5f5f60408486031215612b4f575f5ffd5b83359250602084013567ffffffffffffffff811115612b6c575f5ffd5b612b78868287016128d5565b9497909650939450505050565b5f60208284031215612b95575f5ffd5b813567ffffffffffffffff811115612bab575f5ffd5b820160a08185031215610cf0575f5ffd5b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f610cf06020830184612bbc565b803563ffffffff811681146127d6575f5ffd5b803567ffffffffffffffff811681146127d6575f5ffd5b60c08101823560028110801590612c59575f5ffd5b50825263ffffffff612c6d60208501612c1a565b16602083015263ffffffff612c8460408501612c1a565b16604083015263ffffffff612c9b60608501612c1a565b166060830152612cad60808401612c1a565b63ffffffff166080830152612cc460a08401612c2d565b67ffffffffffffffff811660a08401525092915050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d0e575f5ffd5b830160208101925035905067ffffffffffffffff811115612d2d575f5ffd5b8060051b3603821315611e82575f5ffd5b60038110610f80575f5ffd5b60038110612d7f577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610f80575f5ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612de3575f5ffd5b830160208101925035905067ffffffffffffffff811115612e02575f5ffd5b803603821315611e82575f5ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f60608301612e668384612cdb565b606086528281845260808701905060808260051b8801019350825f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81853603015b84821015612fc4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a88030184528235818112612ee3575f5ffd5b8601608088018135612ef4816127aa565b73ffffffffffffffffffffffffffffffffffffffff1689526020820135612f1a81612d3e565b612f2760208b0182612d4a565b506040820135612f368161276f565b151560408a0152612f4a6060830183612cdb565b608060608c0152918290529091505f60a08a015b83821015612fa8578235612f7181612d83565b7fffffffff000000000000000000000000000000000000000000000000000000001681526020928301926001929092019101612f5e565b9950505060209485019493909301925060019190910190612ea7565b505050505050612fd6602084016127cb565b73ffffffffffffffffffffffffffffffffffffffff166020850152612ffe6040840184612db0565b8583036040870152613011838284612e10565b9695505050505050565b828152604060208201525f612a4d6040830184612e57565b5f60208284031215613043575f5ffd5b8151610cf08161276f565b602081525f610cf06020830184612e57565b80516127d6816127aa565b5f6020828403121561307b575f5ffd5b8151610cf0816127aa565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156130d6576130d6613086565b60405290565b6040516080810167ffffffffffffffff811182821017156130d6576130d6613086565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561314657613146613086565b604052919050565b5f67ffffffffffffffff82111561316757613167613086565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126131a2575f5ffd5b81356131b56131b08261314e565b6130ff565b8181528460208386010111156131c9575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f604083850312156131f6575f5ffd5b823567ffffffffffffffff81111561320c575f5ffd5b61321885828601613193565b925050602083013567ffffffffffffffff811115613234575f5ffd5b612b3385828601613193565b73ffffffffffffffffffffffffffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152608060408201525f61328a6080830186612bbc565b8281036060840152838152602080820190600586901b830101865f5b87811015613302577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030184526132df828a612db0565b6132ea858284612e10565b602096870196909550939093019250506001016132a6565b50909a9950505050505050505050565b5f60208284031215613322575f5ffd5b5051919050565b5f5f5f5f6080858703121561333c575f5ffd5b84359350602085013561334e816127aa565b925060408501359150606085013567ffffffffffffffff811115613370575f5ffd5b61337c87828801613193565b91505092959194509250565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126133ba575f5ffd5b9190910192915050565b5f5f604083850312156133d5575f5ffd5b82356133e0816127aa565b9150602083013567ffffffffffffffff811115613234575f5ffd5b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152826040820152608060608201525f6130116080830184612bbc565b5f67ffffffffffffffff82111561344e5761344e613086565b5060051b60200190565b5f82601f830112613467575f5ffd5b81516134756131b08261314e565b818152846020838601011115613489575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f602082840312156134b5575f5ffd5b815167ffffffffffffffff8111156134cb575f5ffd5b8201606081850312156134dc575f5ffd5b6134e46130b3565b815167ffffffffffffffff8111156134fa575f5ffd5b8201601f8101861361350a575f5ffd5b80516135186131b082613435565b8082825260208201915060208360051b850101925088831115613539575f5ffd5b602084015b8381101561366d57805167ffffffffffffffff81111561355c575f5ffd5b85016080818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561358f575f5ffd5b6135976130dc565b60208201516135a5816127aa565b815260408201516135b581612d3e565b602082015260608201516135c88161276f565b6040820152608082015167ffffffffffffffff8111156135e6575f5ffd5b6020818401019250508b601f8301126135fd575f5ffd5b815161360b6131b082613435565b8082825260208201915060208360051b86010192508e83111561362c575f5ffd5b6020850194505b8285101561365757845161364681612d83565b825260209485019490910190613633565b606084015250508452506020928301920161353e565b5084525061368091505060208301613060565b6020820152604082015167ffffffffffffffff81111561369e575f5ffd5b6136aa86828501613458565b604083015250949350505050565b7fffffffff000000000000000000000000000000000000000000000000000000008b1681528960048201528860248201528760448201528660648201528560848201528460a48201528360c48201528260e48201525f8251806020850161010485015e5f920161010401918252509a9950505050505050505050565b828152604060208201525f60a0820183516060604085015281815180845260c08601915060c08160051b87010193506020830192505f5b8181101561385a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4087860301835283516080860173ffffffffffffffffffffffffffffffffffffffff825116875260208201516137cc6020890182612d4a565b50604082015115156040880152606082015191506080606088015280825180835260a0890191506020840193505f92505b80831015613842577fffffffff0000000000000000000000000000000000000000000000000000000084511682526020820191506020840193506001830192506137fd565b5096505050602093840193929092019160010161376b565b50505050602084015173ffffffffffffffffffffffffffffffffffffffff16606084015260408401518382037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00160808501526130118282612bbc565b5f602082840312156138c7575f5ffd5b610cf082612c2d565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126133ba575f5ffd5b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613935575f5ffd5b83018035915067ffffffffffffffff82111561394f575f5ffd5b602001915036819003821315611e82575f5ffd5b602081525f612a4d602083018486612e10565b73ffffffffffffffffffffffffffffffffffffffff8a16815288602082015267ffffffffffffffff8816604082015286606082015261010060808201525f6139c2610100830188612e57565b8660a084015282810360c08401526139db818688612e10565b9150508260e08301529a995050505050505050505056fe608060405234801561000f575f5ffd5b5060405161148b38038061148b83398101604081905261002e91610e3c565b4682146100675760405162461bcd60e51b8152602060048201526002602482015261383960f11b60448201526064015b60405180910390fd5b61007081610077565b50506111c6565b80516020820151604083015182515f5b818110156101d5575f8582815181106100a2576100a2610fdb565b60200260200101516020015190505f8683815181106100c3576100c3610fdb565b60200260200101515f015190505f8784815181106100e3576100e3610fdb565b60200260200101516040015190505f88858151811061010457610104610fdb565b602002602001015160600151905080515f0361013357604051630a6fef7160e41b815260040160405180910390fd5b5f84600281111561014657610146610fef565b0361015b57610156838284610222565b6101bb565b600184600281111561016f5761016f610fef565b0361017f5761015683828461034a565b600284600281111561019357610193610fef565b036101a2576101568382610457565b60405163e52478c760e01b815260040160405180910390fd5b505050506101ce8161055560201b60201c565b9050610087565b506101e0838361055b565b7f87b829356b3403d36217eff1f66ee48eacd0a69015153aba4f0de29fe5340c3084848460405161021393929190611031565b60405180910390a15050505050565b5f51602061146b5f395f51905f526001600160a01b0384163b5f03610265576040516310d76a3760e31b81526001600160a01b038516600482015260240161005e565b61026e8461069c565b82515f5b81811015610342575f85828151811061028d5761028d610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250901561032d57805160405163158947f360e31b81526001600160e01b0319841660048201526001600160a01b03909116602482015260440161005e565b610338888388610741565b5050600101610272565b505050505050565b5f51602061146b5f395f51905f526001600160a01b0384163b5f0361038d576040516310d76a3760e31b81526001600160a01b038516600482015260240161005e565b82515f5b81811015610342575f8582815181106103ac576103ac610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff161515918101919091529092509061042d57604051630d600dc360e21b815260040160405180910390fd5b805161043990836108e6565b6104428861069c565b61044d888388610741565b5050600101610391565b5f51602061146b5f395f51905f526001600160a01b038316156104985760405163333e8bef60e11b81526001600160a01b038416600482015260240161005e565b81515f5b8181101561054e575f8482815181106104b7576104b7610fdb565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff1615159181019190915290925090610538576040516328b52c5b60e21b815260040160405180910390fd5b805161054490836108e6565b505060010161049c565b5050505050565b60010190565b6001600160a01b03821661058d578051156105895760405163c21b1ab760e01b815260040160405180910390fd5b5050565b5f5f836001600160a01b0316836040516105a79190611147565b5f60405180830381855af49150503d805f81146105df576040519150601f19603f3d011682016040523d82523d5f602084013e6105e4565b606091505b50915091508161061b57600481511015610613578060405163f7a01e4d60e01b815260040161005e919061115d565b805160208201fd5b805160201461063f578060405163f7a01e4d60e01b815260040161005e919061115d565b7f33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a25f1b818060200190518101906106769190611176565b14610696578060405163f7a01e4d60e01b815260040161005e919061115d565b50505050565b6001600160a01b0381165f9081525f51602061144b5f395f51905f5260205260408120545f51602061146b5f395f51905f529181900361073c5760028201546106e490610acc565b6001600160a01b0384165f81815260018581016020908152604083208201805461ffff191661ffff96909616959095179094556002860180549182018155825292902090910180546001600160a01b03191690911790555b505050565b6001600160a01b0383165f9081525f51602061144b5f395f51905f5260205260408120545f51602061146b5f395f51905f52919061077e90610acc565b905061ffff81161561081d576001600160a01b0385165f9081526001830160205260408120805482906107b3576107b3610fdb565b5f918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03198116835290859052604090912054909150600160b01b900460ff1615158415151461081b5760405163d3b6535b60e01b815260040160405180910390fd5b505b604080516060810182526001600160a01b0396871680825261ffff93841660208084019182529615158385019081526001600160e01b031989165f90815287895285812094518554935192519b166001600160b01b031990931692909217600160a01b91909616029490941760ff60b01b1916600160b01b981515989098029790971790559481526001918201835293842080549182018155845292206008830401805463ffffffff60079094166004026101000a938402191660e09290921c92909202179055565b6001600160e01b031981165f9081525f51602061146b5f395f51905f5260208181526040808420546001600160a01b03871685525f51602061144b5f395f51905f529092528320549192600160a01b90910461ffff16916109499060019061118d565b9050808214610a43576001600160a01b0385165f908152600184016020526040812080548390811061097d5761097d610fdb565b5f91825260208083206008830401546001600160a01b038a168452600188019091526040909220805460079092166004026101000a90920460e01b9250829190859081106109cd576109cd610fdb565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c0217905550610a0a83610acc60201b60201c565b6001600160e01b03199091165f908152602085905260409020805461ffff92909216600160a01b0261ffff60a01b199092169190911790555b6001600160a01b0385165f9081526001840160205260409020805480610a6b57610a6b6111b2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319861682528490526040812080546001600160b81b031916905581900361054e5761054e85610b32565b5f61ffff821115610b2e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b606482015260840161005e565b5090565b6001600160a01b0381165f9081525f51602061144b5f395f51905f52602052604081206001908101547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d545f51602061146b5f395f51905f529361ffff90921692610b9c9161118d565b9050808214610c4e575f836002018281548110610bbb57610bbb610fdb565b5f918252602090912001546002850180546001600160a01b039092169250829185908110610beb57610beb610fdb565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055610c1c83610acc565b6001600160a01b03919091165f9081526001858101602052604090912001805461ffff191661ffff9092169190911790555b82600201805480610c6157610c616111b2565b5f8281526020902081015f1990810180546001600160a01b031916905501905550505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715610cbd57610cbd610c87565b60405290565b604051608081016001600160401b0381118282101715610cbd57610cbd610c87565b604051601f8201601f191681016001600160401b0381118282101715610d0d57610d0d610c87565b604052919050565b5f6001600160401b03821115610d2d57610d2d610c87565b5060051b60200190565b80516001600160a01b0381168114610d4d575f5ffd5b919050565b5f82601f830112610d61575f5ffd5b8151610d74610d6f82610d15565b610ce5565b8082825260208201915060208360051b860101925085831115610d95575f5ffd5b602085015b83811015610dc75780516001600160e01b031981168114610db9575f5ffd5b835260209283019201610d9a565b5095945050505050565b5f82601f830112610de0575f5ffd5b81516001600160401b03811115610df957610df9610c87565b610e0c601f8201601f1916602001610ce5565b818152846020838601011115610e20575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f60408385031215610e4d575f5ffd5b825160208401519092506001600160401b03811115610e6a575f5ffd5b830160608186031215610e7b575f5ffd5b610e83610c9b565b81516001600160401b03811115610e98575f5ffd5b8201601f81018713610ea8575f5ffd5b8051610eb6610d6f82610d15565b8082825260208201915060208360051b850101925089831115610ed7575f5ffd5b602084015b83811015610f8d5780516001600160401b03811115610ef9575f5ffd5b85016080818d03601f19011215610f0e575f5ffd5b610f16610cc3565b610f2260208301610d37565b8152604082015160038110610f35575f5ffd5b602082015260608201518015158114610f4c575f5ffd5b604082015260808201516001600160401b03811115610f69575f5ffd5b610f788e602083860101610d52565b60608301525084525060209283019201610edc565b50845250610fa091505060208301610d37565b602082015260408201516001600160401b03811115610fbd575f5ffd5b610fc987828501610dd1565b60408301525080925050509250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f606082016060835280865180835260808501915060808160051b8601019250602088015f5b8281101561111857868503607f19018452815180516001600160a01b03168652602081015160808701906003811061109d57634e487b7160e01b5f52602160045260245ffd5b80602089015250604082015115156040880152606082015191506080606088015280825180835260a0890191506020840193505f92505b808310156111005783516001600160e01b031916825260209384019360019390930192909101906110d4565b50965050506020938401939190910190600101611057565b5050506001600160a01b038616602085015250828103604084015261113d8185611003565b9695505050505050565b5f82518060208501845e5f920191825250919050565b602081525f61116f6020830184611003565b9392505050565b5f60208284031215611186575f5ffd5b5051919050565b818103818111156111ac57634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603160045260245ffd5b610278806111d35f395ff3fe60806040527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b600436101580610033575036155b61009e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f557400000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b5f80357fffffffff0000000000000000000000000000000000000000000000000000000016815260208281526040918290208251606081018452905473ffffffffffffffffffffffffffffffffffffffff811680835274010000000000000000000000000000000000000000820461ffff1693830193909352760100000000000000000000000000000000000000000000900460ff16151592810192909252806101a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f46000000000000000000000000000000000000000000000000000000000000006044820152606401610095565b600383015460ff1615806101ba57508160400151155b610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f71310000000000000000000000000000000000000000000000000000000000006044820152606401610095565b604051365f82375f5f3683855af43d805f843e81801561023e578184f35b8184fdfea264697066735822122003dea0923a2d888969d5a8361432ef4d7cadb69970e0d9fd6baf728e0eef05fb64736f6c634300081c0033c8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131cc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ba264697066735822122022f1c500017c619636a8ad2191ae4a7d164c70a8fbc0956872bbf8f759fa852064736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce
-----Decoded View---------------
Arg [0] : _bridgehub (address): 0x236D1c3Ff32Bd0Ca26b72Af287E895627c0478cE
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000236d1c3ff32bd0ca26b72af287e895627c0478ce
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.