Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21087218 | 100 days ago | Contract Creation | 0 ETH |
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:
StateTransitionManager
Compiler Version
v0.8.24+commit.e11b9ed9
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.24; 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 {IDefaultUpgrade} from "../upgrades/IDefaultUpgrade.sol"; import {IDiamondInit} from "./chain-interfaces/IDiamondInit.sol"; import {IExecutor} from "./chain-interfaces/IExecutor.sol"; import {IStateTransitionManager, StateTransitionManagerInitializeData, ChainCreationParams} from "./IStateTransitionManager.sol"; import {ISystemContext} from "./l2-deps/ISystemContext.sol"; import {IZkSyncHyperchain} from "./chain-interfaces/IZkSyncHyperchain.sol"; import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol"; import {L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, L2_FORCE_DEPLOYER_ADDR} from "../common/L2ContractAddresses.sol"; import {L2CanonicalTransaction} from "../common/Messaging.sol"; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol"; import {ProposedUpgrade} from "../upgrades/BaseZkSyncUpgrade.sol"; import {ReentrancyGuard} from "../common/ReentrancyGuard.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, L2_TO_L1_LOG_SERIALIZE_SIZE, DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY_STRING_KECCAK, SYSTEM_UPGRADE_L2_TX_TYPE, PRIORITY_TX_MAX_GAS_LIMIT} from "../common/Config.sol"; import {VerifierParams} from "./chain-interfaces/IVerifier.sol"; import {Unauthorized, ZeroAddress, HashMismatch, HyperchainLimitReached, GenesisUpgradeZero, GenesisBatchHashZero, GenesisIndexStorageZero, GenesisBatchCommitmentZero} from "../common/L1ContractErrors.sol"; import {SemVer} from "../common/libraries/SemVer.sol"; /// @title State Transition Manager contract /// @author Matter Labs /// @custom:security-contact [email protected] contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Ownable2StepUpgradeable { using EnumerableMap for EnumerableMap.UintToAddressMap; /// @notice Address of the bridgehub address public immutable BRIDGE_HUB; /// @notice The total number of hyperchains can be created/connected to this STM. /// This is the temporary security measure. uint256 public immutable MAX_NUMBER_OF_HYPERCHAINS; /// @notice The map from chainId => hyperchain contract EnumerableMap.UintToAddressMap internal hyperchainMap; /// @dev The batch zero hash, calculated at initialization bytes32 public storedBatchZero; /// @dev The stored cutData for diamond cut bytes32 public initialCutHash; /// @dev The genesisUpgrade contract address, used to setChainId address public genesisUpgrade; /// @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, used to setChainId address public 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 Contract is expected to be used as proxy implementation. /// @dev Initialize the implementation to prevent Parity hack. constructor(address _bridgehub, uint256 _maxNumberOfHyperchains) reentrancyGuardInitializer { BRIDGE_HUB = _bridgehub; MAX_NUMBER_OF_HYPERCHAINS = _maxNumberOfHyperchains; // 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); } /// @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); } _; } /// @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 Returns all the registered hyperchain addresses function getAllHyperchains() public view override returns (address[] memory chainAddresses) { uint256[] memory keys = hyperchainMap.keys(); chainAddresses = new address[](keys.length); uint256 keysLength = keys.length; for (uint256 i = 0; i < keysLength; ++i) { chainAddresses[i] = hyperchainMap.get(keys[i]); } } /// @notice Returns all the registered hyperchain chainIDs function getAllHyperchainChainIDs() public view override returns (uint256[] memory) { return hyperchainMap.keys(); } /// @notice Returns the address of the hyperchain with the corresponding chainID function getHyperchain(uint256 _chainId) public view override returns (address chainAddress) { // slither-disable-next-line unused-return (, chainAddress) = hyperchainMap.tryGet(_chainId); } /// @notice Returns the address of the hyperchain admin with the corresponding chainID function getChainAdmin(uint256 _chainId) external view override returns (address) { return IZkSyncHyperchain(hyperchainMap.get(_chainId)).getAdmin(); } /// @dev initialize function initialize( StateTransitionManagerInitializeData calldata _initializeData ) external reentrancyGuardInitializer { if (_initializeData.owner == address(0)) { revert ZeroAddress(); } _transferOwnership(_initializeData.owner); protocolVersion = _initializeData.protocolVersion; protocolVersionDeadline[_initializeData.protocolVersion] = type(uint256).max; validatorTimelock = _initializeData.validatorTimelock; _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(); } genesisUpgrade = _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, timestamp: 0, commitment: _chainCreationParams.genesisBatchCommitment }); storedBatchZero = keccak256(abi.encode(batchZero)); bytes32 newInitialCutHash = keccak256(abi.encode(_chainCreationParams.diamondCut)); initialCutHash = newInitialCutHash; emit NewChainCreationParams({ genesisUpgrade: _chainCreationParams.genesisUpgrade, genesisBatchHash: _chainCreationParams.genesisBatchHash, genesisIndexRepeatedStorageChanges: _chainCreationParams.genesisIndexRepeatedStorageChanges, genesisBatchCommitment: _chainCreationParams.genesisBatchCommitment, newInitialCutHash: newInitialCutHash }); } /// @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 set validatorTimelock. Cannot do it during initialization, as validatorTimelock is deployed after STM function setValidatorTimelock(address _validatorTimelock) external onlyOwnerOrAdmin { address oldValidatorTimelock = validatorTimelock; validatorTimelock = _validatorTimelock; emit NewValidatorTimelock(oldValidatorTimelock, _validatorTimelock); } /// @dev set New Version with upgrade from old version function setNewVersionUpgrade( Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion, uint256 _oldProtocolVersionDeadline, uint256 _newProtocolVersion ) external onlyOwner { bytes32 newCutHash = keccak256(abi.encode(_cutData)); uint256 previousProtocolVersion = protocolVersion; upgradeCutHash[_oldProtocolVersion] = newCutHash; protocolVersionDeadline[_oldProtocolVersion] = _oldProtocolVersionDeadline; protocolVersionDeadline[_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 function protocolVersionIsActive(uint256 _protocolVersion) external view override returns (bool) { return block.timestamp <= protocolVersionDeadline[_protocolVersion]; } /// @dev set the protocol version timestamp function setProtocolVersionDeadline(uint256 _protocolVersion, uint256 _timestamp) external onlyOwner { protocolVersionDeadline[_protocolVersion] = _timestamp; } /// @dev set upgrade for some protocolVersion 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 function freezeChain(uint256 _chainId) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).freezeDiamond(); } /// @dev freezes the specified chain function unfreezeChain(uint256 _chainId) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).unfreezeDiamond(); } /// @dev reverts batches on the specified chain function revertBatches(uint256 _chainId, uint256 _newLastBatch) external onlyOwnerOrAdmin { IZkSyncHyperchain(hyperchainMap.get(_chainId)).revertBatches(_newLastBatch); } /// @dev execute predefined upgrade function upgradeChainFromVersion( uint256 _chainId, uint256 _oldProtocolVersion, Diamond.DiamondCutData calldata _diamondCut ) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).upgradeChainFromVersion(_oldProtocolVersion, _diamondCut); } /// @dev executes upgrade on chain function executeUpgrade(uint256 _chainId, Diamond.DiamondCutData calldata _diamondCut) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).executeUpgrade(_diamondCut); } /// @dev setPriorityTxMaxGasLimit for the specified chain function setPriorityTxMaxGasLimit(uint256 _chainId, uint256 _maxGasLimit) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).setPriorityTxMaxGasLimit(_maxGasLimit); } /// @dev setTokenMultiplier for the specified chain function setTokenMultiplier(uint256 _chainId, uint128 _nominator, uint128 _denominator) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).setTokenMultiplier(_nominator, _denominator); } /// @dev changeFeeParams for the specified chain function changeFeeParams(uint256 _chainId, FeeParams calldata _newFeeParams) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).changeFeeParams(_newFeeParams); } /// @dev setValidator for the specified chain function setValidator(uint256 _chainId, address _validator, bool _active) external onlyOwnerOrAdmin { IZkSyncHyperchain(hyperchainMap.get(_chainId)).setValidator(_validator, _active); } /// @dev setPorterAvailability for the specified chain function setPorterAvailability(uint256 _chainId, bool _zkPorterIsAvailable) external onlyOwner { IZkSyncHyperchain(hyperchainMap.get(_chainId)).setPorterAvailability(_zkPorterIsAvailable); } /// registration /// @dev we have to set the chainId at genesis, as blockhashzero is the same for all chains with the same chainId function _setChainIdUpgrade(uint256 _chainId, address _chainContract) internal { bytes memory systemContextCalldata = abi.encodeCall(ISystemContext.setChainId, (_chainId)); uint256[] memory uintEmptyArray; bytes[] memory bytesEmptyArray; uint256 cachedProtocolVersion = protocolVersion; // slither-disable-next-line unused-return (, uint32 minorVersion, ) = SemVer.unpackSemVer(SafeCast.toUint96(cachedProtocolVersion)); L2CanonicalTransaction memory l2ProtocolUpgradeTx = L2CanonicalTransaction({ txType: SYSTEM_UPGRADE_L2_TX_TYPE, from: uint256(uint160(L2_FORCE_DEPLOYER_ADDR)), to: uint256(uint160(L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR)), gasLimit: PRIORITY_TX_MAX_GAS_LIMIT, gasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, maxFeePerGas: uint256(0), maxPriorityFeePerGas: uint256(0), paymaster: uint256(0), // Note, that the `minor` of the protocol version is used as "nonce" for system upgrade transactions nonce: uint256(minorVersion), value: 0, reserved: [uint256(0), 0, 0, 0], data: systemContextCalldata, signature: new bytes(0), factoryDeps: uintEmptyArray, paymasterInput: new bytes(0), reservedDynamic: new bytes(0) }); ProposedUpgrade memory proposedUpgrade = ProposedUpgrade({ l2ProtocolUpgradeTx: l2ProtocolUpgradeTx, factoryDeps: bytesEmptyArray, bootloaderHash: bytes32(0), defaultAccountHash: bytes32(0), verifier: address(0), verifierParams: VerifierParams({ recursionNodeLevelVkHash: bytes32(0), recursionLeafLevelVkHash: bytes32(0), recursionCircuitsSetVksHash: bytes32(0) }), l1ContractsUpgradeCalldata: new bytes(0), postUpgradeCalldata: new bytes(0), upgradeTimestamp: 0, newProtocolVersion: cachedProtocolVersion }); Diamond.FacetCut[] memory emptyArray; Diamond.DiamondCutData memory cutData = Diamond.DiamondCutData({ facetCuts: emptyArray, initAddress: genesisUpgrade, initCalldata: abi.encodeCall(IDefaultUpgrade.upgrade, (proposedUpgrade)) }); IAdmin(_chainContract).executeUpgrade(cutData); emit SetChainIdUpgrade(_chainContract, l2ProtocolUpgradeTx, cachedProtocolVersion); } /// @dev used to register already deployed hyperchain contracts /// @param _chainId the chain's id /// @param _hyperchain the chain's contract address function registerAlreadyDeployedHyperchain(uint256 _chainId, address _hyperchain) external onlyOwner { if (_hyperchain == address(0)) { revert ZeroAddress(); } _registerNewHyperchain(_chainId, _hyperchain); } /// @notice called by Bridgehub when a chain registers /// @param _chainId the chain's id /// @param _baseToken the base token address used to pay for gas fees /// @param _sharedBridge the shared bridge address, used as base token bridge /// @param _admin the chain's admin address /// @param _diamondCut the diamond cut data that initializes the chains Diamond Proxy function createNewChain( uint256 _chainId, address _baseToken, address _sharedBridge, address _admin, bytes calldata _diamondCut ) external onlyBridgehub { if (getHyperchain(_chainId) != address(0)) { // Hyperchain already registered return; } // check not registered 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 // 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(validatorTimelock))), bytes32(uint256(uint160(_baseToken))), bytes32(uint256(uint160(_sharedBridge))), storedBatchZero, diamondCut.initCalldata ); diamondCut.initCalldata = initData; // deploy hyperchainContract // slither-disable-next-line reentrancy-no-eth DiamondProxy hyperchainContract = new DiamondProxy{salt: bytes32(0)}(block.chainid, diamondCut); // save data address hyperchainAddress = address(hyperchainContract); _registerNewHyperchain(_chainId, hyperchainAddress); // set chainId in VM _setChainIdUpgrade(_chainId, hyperchainAddress); } /// @dev This internal function is used to register a new hyperchain in the system. function _registerNewHyperchain(uint256 _chainId, address _hyperchain) internal { // slither-disable-next-line unused-return hyperchainMap.set(_chainId, _hyperchain); if (hyperchainMap.length() > MAX_NUMBER_OF_HYPERCHAINS) { revert HyperchainLimitReached(); } emit NewHyperchain(_chainId, _hyperchain); } }
// 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 // 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 // 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 // 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/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); } } }
// 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 // 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.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; /// @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; // TODO: change constant to the real root hash of empty Merkle tree (SMA-184) bytes32 constant DEFAULT_L2_LOGS_TREE_ROOT_HASH = bytes32(0); /// @dev Denotes the type of the ZKsync transaction that came from L1. uint256 constant PRIORITY_OPERATION_L2_TX_TYPE = 255; /// @dev Denotes the type of the ZKsync transaction that is used for system upgrades. uint256 constant SYSTEM_UPGRADE_L2_TX_TYPE = 254; /// @dev The maximal allowed difference between protocol minor versions in an upgrade. The 100 gap is needed /// in case a protocol version has been tested on testnet, but then not launched on mainnet, e.g. /// due to a bug found. /// We are allowed to jump at most 100 minor versions at a time. The major version is always expected to be 0. uint256 constant MAX_ALLOWED_MINOR_VERSION_DELTA = 100; /// @dev The amount of time in seconds the validator has to process the priority transaction /// NOTE: The constant is set to zero for the Alpha release period uint256 constant PRIORITY_EXPIRATION = 0 days; /// @dev Timestamp - seconds since unix epoch. uint256 constant COMMIT_TIMESTAMP_NOT_OLDER = 3 days; /// @dev Maximum available error between real commit batch timestamp and analog used in the verifier (in seconds) /// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 12 seconds) uint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 1 hours; /// @dev Shift to apply to verify public input before verifying. uint256 constant PUBLIC_INPUT_SHIFT = 32; /// @dev The maximum number of L2 gas that a user can request for an L2 transaction uint256 constant MAX_GAS_PER_TRANSACTION = 80_000_000; /// @dev Even though the price for 1 byte of pubdata is 16 L1 gas, we have a slightly increased /// value. uint256 constant L1_GAS_PER_PUBDATA_BYTE = 17; /// @dev The intrinsic cost of the L1->l2 transaction in computational L2 gas uint256 constant L1_TX_INTRINSIC_L2_GAS = 167_157; /// @dev The intrinsic cost of the L1->l2 transaction in pubdata uint256 constant L1_TX_INTRINSIC_PUBDATA = 88; /// @dev The minimal base price for L1 transaction uint256 constant L1_TX_MIN_L2_GAS_BASE = 173_484; /// @dev The number of L2 gas the transaction starts costing more with each 544 bytes of encoding uint256 constant L1_TX_DELTA_544_ENCODING_BYTES = 1656; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64; /// @dev The number of pubdata an L1->L2 transaction requires with each new factory dependency uint256 constant MAX_NEW_FACTORY_DEPS = 32; /// @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; address constant ETH_TOKEN_ADDRESS = address(1); 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));
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0x1ff9d522 error AddressAlreadyUsed(address addr); // 0x86bb51b8 error AddressHasNoCode(address); // 0x1eee5481 error AddressTooLow(address); // 0x6afd6c20 error BadReturnData(); // 0x6ef9a972 error BaseTokenGasPriceDenominatorNotSet(); // 0x55ad3fd3 error BatchHashMismatch(bytes32 expected, bytes32 actual); // 0x2078a6a0 error BatchNotExecuted(uint256 batchNumber); // 0xbd4455ff error BatchNumberMismatch(uint256 expectedBatchNumber, uint256 providedBatchNumber); // 0xafd53e2f error BlobHashCommitmentError(uint256 index, bool blobHashEmpty, bool blobCommitmentEmpty); // 0x6cf12312 error BridgeHubAlreadyRegistered(); // 0xcf102c5a error CalldataLengthTooBig(); // 0xe85392f9 error CanOnlyProcessOneBatch(); // 0x00c6ead2 error CantExecuteUnprovenBatches(); // 0xe18cb383 error CantRevertExecutedBatch(); // 0x78d2ed02 error ChainAlreadyLive(); // 0x8f620a06 error ChainIdTooBig(); // 0xf7a01e4d error DelegateCallFailed(bytes returnData); // 0x0a8ed92c error DenominatorIsZero(); // 0xc7c9660f error DepositDoesNotExist(); // 0xad2fa98e error DepositExists(); // 0x79cacff1 error DepositFailed(); // 0xae08e4af error DepositIncorrectAmount(uint256 expectedAmt, uint256 providedAmt); // 0x0e7ee319 error DiamondAlreadyFrozen(); // 0x682dabb4 error DiamondFreezeIncorrectState(); // 0xa7151b9a error DiamondNotFrozen(); // 0xfc7ab1d3 error EmptyBlobVersionHash(uint256 index); // 0x95b66fe9 error EmptyDeposit(); // 0xac4a3f98 error FacetExists(bytes4 selector, address); // 0x79e12cc3 error FacetIsFrozen(bytes4 func); // 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); // 0xb615c2b1 error HyperchainLimitReached(); // 0x826fb11e error InsufficientChainBalance(); // 0x356680b7 error InsufficientFunds(); // 0x7a47c9a2 error InvalidChainId(); // 0x4fbe5dba error InvalidDelay(); // 0x0af806e0 error InvalidHash(); // 0xc1780bd6 error InvalidLogSender(address sender, uint256 logKey); // 0xd8e9405c error InvalidNumberOfBlobs(uint256 expected, uint256 numCommitments, uint256 numHashes); // 0x09bde339 error InvalidProof(); // 0x5428eae7 error InvalidProtocolVersion(); // 0x53e6d04d error InvalidPubdataCommitmentsSize(); // 0x5513177c error InvalidPubdataHash(bytes32 expectedHash, bytes32 provided); // 0x9094af7e error InvalidPubdataLength(); // 0xc5d09071 error InvalidPubdataMode(); // 0x6f1cf752 error InvalidPubdataPricingMode(); // 0x12ba286f error InvalidSelector(bytes4 func); // 0x5cb29523 error InvalidTxType(uint256 txType); // 0x5f1aa154 error InvalidUpgradeTxn(UpgradeTxVerifyParam); // 0xaa7feadc error InvalidValue(); // 0xa4f62e33 error L2BridgeNotDeployed(uint256 chainId); // 0xff8811ff error L2BridgeNotSet(uint256 chainId); // 0xcb5e4247 error L2BytecodeHashMismatch(bytes32 expected, bytes32 provided); // 0xfb5c22e6 error L2TimestampTooBig(); // 0xd2c011d6 error L2UpgradeNonceNotEqualToNewProtocolVersion(uint256 nonce, uint256 protocolVersion); // 0x97e1359e error L2WithdrawalMessageWrongLength(uint256 messageLen); // 0x32eb8b2f error LegacyMethodIsSupportedOnlyForEra(); // 0xe37d2c02 error LengthIsNotDivisibleBy32(uint256 length); // 0x1b6825bb error LogAlreadyProcessed(uint8); // 0x43e266b0 error MalformedBytecode(BytecodeError); // 0x59170bf0 error MalformedCalldata(); // 0x16509b9a error MalformedMessage(); // 0x9bb54c35 error MerkleIndexOutOfBounds(); // 0x8e23ac1a error MerklePathEmpty(); // 0x1c500385 error MerklePathOutOfBounds(); // 0xfa44b527 error MissingSystemLogs(uint256 expected, uint256 actual); // 0x4a094431 error MsgValueMismatch(uint256 expectedMsgValue, uint256 providedMsgValue); // 0xb385a3da error MsgValueTooLow(uint256 required, uint256 provided); // 0x72ea85ad error NewProtocolMajorVersionNotZero(); // 0x79cc2d22 error NoCallsProvided(); // 0xa6fef710 error NoFunctionsForDiamondCut(); // 0xcab098d8 error NoFundsTransferred(); // 0x92290acc error NonEmptyBlobVersionHash(uint256 index); // 0xc21b1ab7 error NonEmptyCalldata(); // 0x536ec84b error NonEmptyMsgValue(); // 0xd018e08e error NonIncreasingTimestamp(); // 0x0105f9c0 error NonSequentialBatch(); // 0x4ef79e5a error NonZeroAddress(address); // 0xdd629f86 error NotEnoughGas(); // 0xdd7e3621 error NotInitializedReentrancyGuard(); // 0xf3ed9dfa error OnlyEraSupported(); // 0x1a21feed error OperationExists(); // 0xeda2fbb1 error OperationMustBePending(); // 0xe1c1ff37 error OperationMustBeReady(); // 0xd7f50a9d error PatchCantSetUpgradeTxn(); // 0x962fd7d0 error PatchUpgradeCantSetBootloader(); // 0x559cc34e error PatchUpgradeCantSetDefaultAccount(); // 0x8d5851de error PointEvalCallFailed(bytes); // 0x4daa985d error PointEvalFailed(bytes); // 0x9b48e060 error PreviousOperationNotExecuted(); // 0x5c598b60 error PreviousProtocolMajorVersionNotZero(); // 0xa0f47245 error PreviousUpgradeNotCleaned(); // 0x101ba748 error PreviousUpgradeNotFinalized(bytes32 txHash); // 0xd5a99014 error PriorityOperationsRollingHashMismatch(); // 0x1a4d284a error PriorityTxPubdataExceedsMaxPubDataPerBatch(); // 0xa461f651 error ProtocolIdMismatch(uint256 expectedProtocolVersion, uint256 providedProtocolId); // 0x64f94ec2 error ProtocolIdNotGreater(); // 0xd328c12a error ProtocolVersionMinorDeltaTooBig(uint256 limit, uint256 proposed); // 0x88d7b498 error ProtocolVersionTooSmall(); // 0x53dee67b error PubdataCommitmentsEmpty(); // 0x7734c31a error PubdataCommitmentsTooBig(); // 0x959f26fb error PubdataGreaterThanLimit(uint256 limit, uint256 length); // 0x2a4a14df error PubdataPerBatchIsLessThanTxn(); // 0x63c36549 error QueueIsEmpty(); // 0xab143c06 error Reentrancy(); // 0x667d17de error RemoveFunctionFacetAddressNotZero(address facet); // 0xa2d4b16c error RemoveFunctionFacetAddressZero(); // 0x3580370c error ReplaceFunctionFacetAddressZero(); // 0xdab52f4b error RevertedBatchBeforeNewBatch(); // 0x9a67c1cb error RevertedBatchNotAfterNewLastBatch(); // 0xd3b6535b error SelectorsMustAllHaveSameFreezability(); // 0x7774d2f9 error SharedBridgeValueNotSet(SharedBridgeKey); // 0xc1d9246c error SharedBridgeBalanceMismatch(); // 0x856d5b77 error SharedBridgeNotSet(); // 0xcac5fc40 error SharedBridgeValueAlreadySet(SharedBridgeKey); // 0xdf3a8fdd error SlotOccupied(); // 0xd0bc70cf error STMAlreadyRegistered(); // 0x09865e10 error STMNotRegistered(); // 0xae43b424 error SystemLogsSizeTooBig(); // 0x08753982 error TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp); // 0x2d50c33b error TimestampError(); // 0x4f4b634e error TokenAlreadyRegistered(address token); // 0xddef98d7 error TokenNotRegistered(address token); // 0x06439c6b error TokenNotSupported(address token); // 0x23830e28 error TokensWithFeesNotSupported(); // 0xf640f0e5 error TooManyBlobs(); // 0x76da24b9 error TooManyFactoryDeps(); // 0xf0b4e88f error TooMuchGas(); // 0x00c5a6a9 error TransactionNotAllowed(); // 0x4c991078 error TxHashMismatch(); // 0x2e311df8 error TxnBodyGasLimitNotEnoughGas(); // 0x8e4a23d6 error Unauthorized(address caller); // 0xe52478c7 error UndefinedDiamondCutAction(); // 0x07218375 error UnexpectedNumberOfFactoryDeps(); // 0x6aa39880 error UnexpectedSystemLog(uint256 logKey); // 0xf093c2e5 error UpgradeBatchNumberIsNotZero(); // 0x47b3b145 error ValidateTxnNotEnoughGas(); // 0x626ade30 error ValueMismatch(uint256 expected, uint256 actual); // 0xe1022469 error VerifiedBatchesExceedsCommittedBatches(); // 0x2dbdba00 error VerifyProofCommittedVerifiedMismatch(); // 0xae899454 error WithdrawalAlreadyFinalized(); // 0x27fcd9d1 error WithdrawalFailed(); // 0x750b219c error WithdrawFailed(); // 0x15e8e429 error WrongMagicValue(uint256 expectedMagicValue, uint256 providedMagicValue); // 0xd92e233d error ZeroAddress(); // 0x669567ea error ZeroBalance(); // 0xc84885d4 error ZeroChainId(); 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 formal address of the initial program of the system: the bootloader address constant L2_BOOTLOADER_ADDRESS = address(0x8001); /// @dev The address of the known code storage system contract address constant L2_KNOWN_CODE_STORAGE_SYSTEM_CONTRACT_ADDR = address(0x8004); /// @dev The address of the L2 deployer system contract. address constant L2_DEPLOYER_SYSTEM_CONTRACT_ADDR = address(0x8006); /// @dev The special reserved L2 address. It is located in the system contracts space but doesn't have deployed /// bytecode. /// @dev The L2 deployer system contract allows changing bytecodes on any address if the `msg.sender` is this address. /// @dev So, whenever the governor wants to redeploy system contracts, it just initiates the L1 upgrade call deployer /// system contract /// via the L1 -> L2 transaction with `sender == L2_FORCE_DEPLOYER_ADDR`. For more details see the /// `diamond-initializers` contracts. address constant L2_FORCE_DEPLOYER_ADDR = address(0x8007); /// @dev The address of the special smart contract that can send arbitrary length message as an L2 log address constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = address(0x8008); /// @dev The address of the eth token system contract address constant L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR = address(0x800a); /// @dev The address of the context system contract address constant L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR = address(0x800b); /// @dev The address of the pubdata chunk publisher contract address constant L2_PUBDATA_CHUNK_PUBLISHER_ADDR = address(0x8011);
// 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 {BytecodeError, MalformedBytecode, LengthIsNotDivisibleBy32} from "../L1ContractErrors.sol"; /** * @author Matter Labs * @custom:security-contact [email protected] * @notice Helper library for working with L2 contracts on L1. */ library L2ContractHelper { /// @dev The prefix used to create CREATE2 addresses. bytes32 private constant CREATE2_PREFIX = keccak256("zksyncCreate2"); /// @notice Validate the bytecode format and calculate its hash. /// @param _bytecode The bytecode to hash. /// @return hashedBytecode The 32-byte hash of the bytecode. /// Note: The function reverts the execution if the bytecode has non expected format: /// - Bytecode bytes length is not a multiple of 32 /// - Bytecode bytes length is not less than 2^21 bytes (2^16 words) /// - Bytecode words length is not odd function hashL2Bytecode(bytes memory _bytecode) internal pure returns (bytes32 hashedBytecode) { // Note that the length of the bytecode must be provided in 32-byte words. if (_bytecode.length % 32 != 0) { revert LengthIsNotDivisibleBy32(_bytecode.length); } uint256 bytecodeLenInWords = _bytecode.length / 32; // bytecode length must be less than 2^16 words if (bytecodeLenInWords >= 2 ** 16) { revert MalformedBytecode(BytecodeError.NumberOfWords); } // bytecode length in words must be odd if (bytecodeLenInWords % 2 == 0) { revert MalformedBytecode(BytecodeError.WordsMustBeOdd); } hashedBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248))); // Setting the length hashedBytecode = hashedBytecode | bytes32(bytecodeLenInWords << 224); } /// @notice Validates the format of the given bytecode hash. /// @dev Due to the specification of the L2 bytecode hash, not every 32 bytes could be a legit bytecode hash. /// @dev The function reverts on invalid bytecode hash format. /// @param _bytecodeHash The hash of the bytecode to validate. function validateBytecodeHash(bytes32 _bytecodeHash) internal pure { uint8 version = uint8(_bytecodeHash[0]); // Incorrectly formatted bytecodeHash if (version != 1 || _bytecodeHash[1] != bytes1(0)) { revert MalformedBytecode(BytecodeError.Version); } // Code length in words must be odd if (bytecodeLen(_bytecodeHash) % 2 == 0) { revert MalformedBytecode(BytecodeError.WordsMustBeOdd); } } /// @notice Returns the length of the bytecode associated with the given hash. /// @param _bytecodeHash The hash of the bytecode. /// @return codeLengthInWords The length of the bytecode in words. function bytecodeLen(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInWords) { codeLengthInWords = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3])); } /// @notice Computes the create2 address for a Layer 2 contract. /// @param _sender The address of the sender. /// @param _salt The salt value to use in the create2 address computation. /// @param _bytecodeHash The contract bytecode hash. /// @param _constructorInputHash The hash of the constructor input data. /// @return The create2 address of the contract. /// NOTE: L2 create2 derivation is different from L1 derivation! function computeCreate2Address( address _sender, bytes32 _salt, bytes32 _bytecodeHash, bytes32 _constructorInputHash ) internal pure returns (address) { bytes32 senderBytes = bytes32(uint256(uint160(_sender))); bytes32 data = keccak256( // solhint-disable-next-line func-named-parameters bytes.concat(CREATE2_PREFIX, senderBytes, _salt, _bytecodeHash, _constructorInputHash) ); return address(uint160(uint256(data))); } }
// 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; /** * @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; /// @dev The enum that represents the transaction execution status /// @param Failure The transaction execution failed /// @param Success The transaction execution succeeded enum TxStatus { Failure, Success } /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter /// All other values are not used but are reserved for the future /// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address. /// This field is required formally but does not have any special meaning /// @param txNumberInBatch The L2 transaction number in a Batch, in which the log was sent /// @param sender The L2 address which sent the log /// @param key The 32 bytes of information that was sent in the log /// @param value The 32 bytes of information that was sent in the log // Both `key` and `value` are arbitrary 32-bytes selected by the log sender struct L2Log { uint8 l2ShardId; bool isService; uint16 txNumberInBatch; address sender; bytes32 key; bytes32 value; } /// @dev An arbitrary length message passed from L2 /// @notice Under the hood it is `L2Log` sent from the special system L2 contract /// @param txNumberInBatch The L2 transaction number in a Batch, in which the message was sent /// @param sender The address of the L2 account from which the message was passed /// @param data An arbitrary length message struct L2Message { uint16 txNumberInBatch; address sender; bytes data; } /// @dev Internal structure that contains the parameters for the writePriorityOp /// internal function. /// @param txId The id of the priority transaction. /// @param l2GasPrice The gas price for the l2 priority operation. /// @param expirationTimestamp The timestamp by which the priority operation must be processed by the operator. /// @param request The external calldata request for the priority operation. struct WritePriorityOpParams { uint256 txId; uint256 l2GasPrice; uint64 expirationTimestamp; BridgehubL2TransactionRequest request; } /// @dev Structure that includes all fields of the L2 transaction /// @dev The hash of this structure is the "canonical L2 transaction hash" and can /// be used as a unique identifier of a tx /// @param txType The tx type number, depending on which the L2 transaction can be /// interpreted differently /// @param from The sender's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param to The recipient's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param gasLimit The L2 gas limit for L2 transaction. Analog to the `gasLimit` on an /// L1 transactions /// @param gasPerPubdataByteLimit Maximum number of L2 gas that will cost one byte of pubdata /// (every piece of data that will be stored on L1 as calldata) /// @param maxFeePerGas The absolute maximum sender willing to pay per unit of L2 gas to get /// the transaction included in a Batch. Analog to the EIP-1559 `maxFeePerGas` on an L1 transactions /// @param maxPriorityFeePerGas The additional fee that is paid directly to the validator /// to incentivize them to include the transaction in a Batch. Analog to the EIP-1559 /// `maxPriorityFeePerGas` on an L1 transactions /// @param paymaster The address of the EIP-4337 paymaster, that will pay fees for the /// transaction. `uint256` type for possible address format changes and maintaining backward compatibility /// @param nonce The nonce of the transaction. For L1->L2 transactions it is the priority /// operation Id /// @param value The value to pass with the transaction /// @param reserved The fixed-length fields for usage in a future extension of transaction /// formats /// @param data The calldata that is transmitted for the transaction call /// @param signature An abstract set of bytes that are used for transaction authorization /// @param factoryDeps The set of L2 bytecode hashes whose preimages were shown on L1 /// @param paymasterInput The arbitrary-length data that is used as a calldata to the paymaster pre-call /// @param reservedDynamic The arbitrary-length field for usage in a future extension of transaction formats struct L2CanonicalTransaction { uint256 txType; uint256 from; uint256 to; uint256 gasLimit; uint256 gasPerPubdataByteLimit; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; uint256 paymaster; uint256 nonce; uint256 value; // In the future, we might want to add some // new fields to the struct. The `txData` struct // is to be passed to account and any changes to its structure // would mean a breaking change to these accounts. To prevent this, // we should keep some fields as "reserved" // It is also recommended that their length is fixed, since // it would allow easier proof integration (in case we will need // some special circuit for preprocessing transactions) uint256[4] reserved; bytes data; bytes signature; uint256[] factoryDeps; bytes paymasterInput; // Reserved dynamic type for the future use-case. Using it should be avoided, // But it is still here, just in case we want to enable some additional functionality bytes reservedDynamic; } /// @param sender The sender's address. /// @param contractAddressL2 The address of the contract on L2 to call. /// @param valueToMint The amount of base token that should be minted on L2 as the result of this transaction. /// @param l2Value The msg.value of the L2 transaction. /// @param l2Calldata The calldata for the L2 transaction. /// @param l2GasLimit The limit of the L2 gas for the L2 transaction /// @param l2GasPerPubdataByteLimit The price for a single pubdata byte in L2 gas. /// @param factoryDeps The array of L2 bytecodes that the tx depends on. /// @param refundRecipient The recipient of the refund for the transaction on L2. If the transaction fails, then /// this address will receive the `l2Value`. // solhint-disable-next-line gas-struct-packing struct BridgehubL2TransactionRequest { address sender; address contractL2; uint256 mintValue; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; }
// SPDX-License-Identifier: MIT // 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 {SlotOccupied, NotInitializedReentrancyGuard, Reentrancy} 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 pragma solidity 0.8.24; // 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 pragma solidity 0.8.24; import {ZkSyncHyperchainStorage} from "../ZkSyncHyperchainStorage.sol"; import {ReentrancyGuard} from "../../../common/ReentrancyGuard.sol"; import {Unauthorized} from "../../../common/L1ContractErrors.sol"; /// @title Base contract containing functions accessible to the other facets. /// @author Matter Labs /// @custom:security-contact [email protected] contract ZkSyncHyperchainBase is ReentrancyGuard { // slither-disable-next-line uninitialized-state ZkSyncHyperchainStorage internal s; /// @notice Checks that the message sender is an active admin modifier onlyAdmin() { if (msg.sender != s.admin) { revert Unauthorized(msg.sender); } _; } /// @notice Checks if validator is active modifier onlyValidator() { if (!s.validators[msg.sender]) { revert Unauthorized(msg.sender); } _; } modifier onlyStateTransitionManager() { if (msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyBridgehub() { if (msg.sender != s.bridgehub) { revert Unauthorized(msg.sender); } _; } modifier onlyAdminOrStateTransitionManager() { if (msg.sender != s.admin && msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyValidatorOrStateTransitionManager() { if (!s.validators[msg.sender] && msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyBaseTokenBridge() { if (msg.sender != s.baseTokenBridge) { revert Unauthorized(msg.sender); } _; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IVerifier, VerifierParams} from "../chain-interfaces/IVerifier.sol"; import {PriorityQueue} from "../../state-transition/libraries/PriorityQueue.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 hyperchain 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 ZkSyncHyperchainStorage { /// @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 STM 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 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. FeeParams feeParams; /// @dev Address of the blob versioned hash getter smart contract used for EIP-4844 versioned hashes. address blobVersionedHashRetriever; /// @dev The chainId of the chain uint256 chainId; /// @dev The address of the bridgehub address bridgehub; /// @dev The address of the StateTransitionManager address stateTransitionManager; /// @dev The address of the baseToken contract. Eth is address(1) address baseToken; /// @dev The address of the baseTokenbridge. Eth also uses the shared bridge address 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; }
// 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 {IZkSyncHyperchainBase} from "../chain-interfaces/IZkSyncHyperchainBase.sol"; import {Diamond} from "../libraries/Diamond.sol"; import {FeeParams, PubdataPricingMode} from "../chain-deps/ZkSyncHyperchainStorage.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 IZkSyncHyperchainBase { /// @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 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 current admin 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 Both the admin and the STM can unfreeze Diamond Proxy function unfreezeDiamond() 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 ValidiumModeStatusUpdate(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 contract is frozen. event Freeze(); /// @notice Emitted when the contract is unfrozen. event Unfreeze(); }
// 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/ZkSyncHyperchainStorage.sol"; /// @param chainId the id of the chain /// @param bridgehub the address of the bridgehub contract /// @param stateTransitionManager 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 baseToken address of the base token of the chain /// @param baseTokenBridge address of the L1 shared bridge contract /// @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 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 /// @param blobVersionedHashRetriever Address of contract used to pull the blob versioned hash for a transaction. // solhint-disable-next-line gas-struct-packing struct InitializeData { uint256 chainId; address bridgehub; address stateTransitionManager; uint256 protocolVersion; address admin; address validatorTimelock; address baseToken; address baseTokenBridge; bytes32 storedBatchZero; IVerifier verifier; VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; uint256 priorityTxMaxGasLimit; FeeParams feeParams; address blobVersionedHashRetriever; } /// @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 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 /// @param blobVersionedHashRetriever Address of contract used to pull the blob versioned hash for a transaction. struct InitializeDataNewChain { IVerifier verifier; VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; uint256 priorityTxMaxGasLimit; FeeParams feeParams; address blobVersionedHashRetriever; } 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 {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.sol"; /// @dev Enum used by L2 System Contracts to differentiate logs. enum SystemLogKey { L2_TO_L1_LOGS_TREE_ROOT_KEY, TOTAL_L2_TO_L1_PUBDATA_KEY, STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, NUMBER_OF_LAYER_1_TXS_KEY, BLOB_ONE_HASH_KEY, BLOB_TWO_HASH_KEY, BLOB_THREE_HASH_KEY, BLOB_FOUR_HASH_KEY, BLOB_FIVE_HASH_KEY, BLOB_SIX_HASH_KEY, EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY } /// @dev Enum used to determine the source of pubdata. At first we will support calldata and blobs but this can be extended. enum PubdataSource { Calldata, Blob } struct LogProcessingOutput { uint256 numberOfLayer1Txs; bytes32 chainedPriorityTxsHash; bytes32 previousBatchHash; bytes32 pubdataHash; bytes32 stateDiffHash; bytes32 l2LogsTreeRoot; uint256 packedBatchAndL2BlockTimestamp; bytes32[] blobHashes; } /// @dev Total number of bytes in a blob. Blob = 4096 field elements * 31 bytes per field element /// @dev EIP-4844 defines it as 131_072 but we use 4096 * 31 within our circuits to always fit within a field element /// @dev Our circuits will prove that a EIP-4844 blob and our internal blob are the same. uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Offset used to pull Address From Log. Equal to 4 (bytes for isService) uint256 constant L2_LOG_ADDRESS_OFFSET = 4; /// @dev Offset used to pull Key From Log. Equal to 4 (bytes for isService) + 20 (bytes for address) uint256 constant L2_LOG_KEY_OFFSET = 24; /// @dev Offset used to pull Value From Log. Equal to 4 (bytes for isService) + 20 (bytes for address) + 32 (bytes for key) uint256 constant L2_LOG_VALUE_OFFSET = 56; /// @dev BLS Modulus value defined in EIP-4844 and the magic value returned from a successful call to the /// point evaluation precompile uint256 constant BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513; /// @dev Packed pubdata commitments. /// @dev Format: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes)) = 144 bytes uint256 constant PUBDATA_COMMITMENT_SIZE = 144; /// @dev Offset in pubdata commitment of blobs for claimed value uint256 constant PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET = 16; /// @dev Offset in pubdata commitment of blobs for kzg commitment uint256 constant PUBDATA_COMMITMENT_COMMITMENT_OFFSET = 48; /// @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 IZkSyncHyperchainBase { /// @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 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 pubdataCommitments 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 pubdataCommitments; } /// @notice Recursive proof input data (individual commitments are constructed onchain) struct ProofInput { uint256[] recursiveAggregationInput; uint256[] serializedProof; } /// @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 _lastCommittedBatchData Stored data of the last committed batch. /// @param _newBatchesData Data of the new batches to be committed. function commitBatches( StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external; /// @notice same as `commitBatches` but with the chainId so ValidatorTimelock can sort the inputs. function commitBatchesSharedBridge( uint256 _chainId, StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external; /// @notice Batches commitment verification. /// @dev Only verifies batch commitments without any other processing. /// @param _prevBatch Stored data of the last committed batch. /// @param _committedBatches Stored data of the committed batches. /// @param _proof The zero knowledge proof. function proveBatches( StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) external; /// @notice same as `proveBatches` but with the chainId so ValidatorTimelock can sort the inputs. function proveBatchesSharedBridge( uint256 _chainId, StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) 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 _batchesData Data of the batches to be executed. function executeBatches(StoredBatchInfo[] calldata _batchesData) external; /// @notice same as `executeBatches` but with the chainId so ValidatorTimelock can sort the inputs. function executeBatchesSharedBridge(uint256 _chainId, StoredBatchInfo[] calldata _batchesData) external; /// @notice Reverts unexecuted batches /// @param _newLastBatch batch number after which batches should be reverted /// NOTE: Doesn't delete the stored data about batches, but only decreases /// counters that are responsible for the number of batches function revertBatches(uint256 _newLastBatch) external; /// @notice same as `revertBatches` but with the chainId so ValidatorTimelock can sort the inputs. function revertBatchesSharedBridge(uint256 _chainId, 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); }
// 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 {PriorityOperation} from "../libraries/PriorityQueue.sol"; import {VerifierParams} from "../chain-interfaces/IVerifier.sol"; import {PubdataPricingMode} from "../chain-deps/ZkSyncHyperchainStorage.sol"; import {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.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] interface IGetters is IZkSyncHyperchainBase { /*////////////////////////////////////////////////////////////// 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 getStateTransitionManager() external view returns (address); /// @return The address of the base token function getBaseToken() external view returns (address); /// @return The address of the base token bridge function getBaseTokenBridge() external view returns (address); /// @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 The total number of priority operations that were added to the priority queue, including all processed ones function getTotalPriorityTxs() external view returns (uint256); /// @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 The first unprocessed priority operation from the queue function priorityQueueFrontOperation() external view returns (PriorityOperation memory); /// @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 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); }
// 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 {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.sol"; import {L2CanonicalTransaction, L2Log, L2Message, TxStatus, BridgehubL2TransactionRequest} from "../../common/Messaging.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 IZkSyncHyperchainBase { /// @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 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 memory _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); function bridgehubRequestL2Transaction( BridgehubL2TransactionRequest calldata _request ) 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); /// @notice transfer Eth to shared bridge as part of migration process function transferEthToSharedBridge() external; /// @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 ); }
// 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, uint256[] calldata _recursiveAggregationInput ) 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 pure 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 {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 IZkSyncHyperchain 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 // 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 IZkSyncHyperchainBase { /// @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; import {Diamond} from "./libraries/Diamond.sol"; import {L2CanonicalTransaction} from "../common/Messaging.sol"; import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol"; /// @notice Struct that holds all data needed for initializing STM 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 struct StateTransitionManagerInitializeData { address owner; address validatorTimelock; ChainCreationParams chainCreationParams; uint256 protocolVersion; } /// @notice The struct that contains the fields that define how a new chain should be created /// within this STM. /// @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; } interface IStateTransitionManager { /// @dev Emitted when a new Hyperchain is added event NewHyperchain(uint256 indexed _chainId, address indexed _hyperchainContract); /// @dev emitted when an chain registers and a SetChainIdUpgrade happens event SetChainIdUpgrade( address indexed _hyperchain, 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 chain creation parameters changed event NewChainCreationParams( address genesisUpgrade, bytes32 genesisBatchHash, uint64 genesisIndexRepeatedStorageChanges, bytes32 genesisBatchCommitment, bytes32 newInitialCutHash ); /// @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); function BRIDGE_HUB() external view returns (address); function setPendingAdmin(address _newPendingAdmin) external; function acceptAdmin() external; function getAllHyperchains() external view returns (address[] memory); function getAllHyperchainChainIDs() external view returns (uint256[] memory); function getHyperchain(uint256 _chainId) external view returns (address); function storedBatchZero() external view returns (bytes32); function initialCutHash() external view returns (bytes32); function genesisUpgrade() 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 initialize(StateTransitionManagerInitializeData calldata _initializeData) external; function setValidatorTimelock(address _validatorTimelock) external; function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external; function getChainAdmin(uint256 _chainId) external view returns (address); function createNewChain( uint256 _chainId, address _baseToken, address _sharedBridge, address _admin, bytes calldata _diamondCut ) external; function registerAlreadyDeployedHyperchain(uint256 _chainId, address _hyperchain) external; 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); }
// 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; interface ISystemContext { function setChainId(uint256 _newChainId) 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 {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol"; import {UncheckedMath} from "../../common/libraries/UncheckedMath.sol"; import {NoFunctionsForDiamondCut, UndefinedDiamondCutAction, AddressHasNoCode, FacetExists, RemoveFunctionFacetAddressZero, SelectorsMustAllHaveSameFreezability, NonEmptyCalldata, ReplaceFunctionFacetAddressZero, RemoveFunctionFacetAddressNotZero, DelegateCallFailed} 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 // 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 {Math} from "@openzeppelin/contracts-v4/utils/math/Math.sol"; import {L2CanonicalTransaction} from "../../common/Messaging.sol"; import {TX_SLOT_OVERHEAD_L2_GAS, MEMORY_OVERHEAD_GAS, L1_TX_INTRINSIC_L2_GAS, L1_TX_DELTA_544_ENCODING_BYTES, L1_TX_DELTA_FACTORY_DEPS_L2_GAS, L1_TX_MIN_L2_GAS_BASE, L1_TX_INTRINSIC_PUBDATA, L1_TX_DELTA_FACTORY_DEPS_PUBDATA} from "../../common/Config.sol"; import {TooMuchGas, InvalidUpgradeTxn, UpgradeTxVerifyParam, PubdataGreaterThanLimit, ValidateTxnNotEnoughGas, TxnBodyGasLimitNotEnoughGas} from "../../common/L1ContractErrors.sol"; /// @title ZKsync Library for validating L1 -> L2 transactions /// @author Matter Labs /// @custom:security-contact [email protected] library TransactionValidator { /// @dev Used to validate key properties of an L1->L2 transaction /// @param _transaction The transaction to validate /// @param _encoded The abi encoded bytes of the transaction /// @param _priorityTxMaxGasLimit The max gas limit, generally provided from Storage.sol /// @param _priorityTxMaxPubdata The maximal amount of pubdata that a single L1->L2 transaction can emit function validateL1ToL2Transaction( L2CanonicalTransaction memory _transaction, bytes memory _encoded, uint256 _priorityTxMaxGasLimit, uint256 _priorityTxMaxPubdata ) internal pure { uint256 l2GasForTxBody = getTransactionBodyGasLimit(_transaction.gasLimit, _encoded.length); // Ensuring that the transaction is provable if (l2GasForTxBody > _priorityTxMaxGasLimit) { revert TooMuchGas(); } // Ensuring that the transaction cannot output more pubdata than is processable if (l2GasForTxBody / _transaction.gasPerPubdataByteLimit > _priorityTxMaxPubdata) { revert PubdataGreaterThanLimit(_priorityTxMaxPubdata, l2GasForTxBody / _transaction.gasPerPubdataByteLimit); } // Ensuring that the transaction covers the minimal costs for its processing: // hashing its content, publishing the factory dependencies, etc. if ( getMinimalPriorityTransactionGasLimit( _encoded.length, _transaction.factoryDeps.length, _transaction.gasPerPubdataByteLimit ) > l2GasForTxBody ) { revert ValidateTxnNotEnoughGas(); } } /// @dev Used to validate upgrade transactions /// @param _transaction The transaction to validate function validateUpgradeTransaction(L2CanonicalTransaction memory _transaction) internal pure { // Restrict from to be within system contract range (0...2^16 - 1) if (_transaction.from > type(uint16).max) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.From); } if (_transaction.to > type(uint160).max) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.To); } if (_transaction.paymaster != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Paymaster); } if (_transaction.value != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Value); } if (_transaction.maxFeePerGas != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.MaxFeePerGas); } if (_transaction.maxPriorityFeePerGas != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.MaxPriorityFeePerGas); } if (_transaction.reserved[0] != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Reserved0); } if (_transaction.reserved[1] > type(uint160).max) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Reserved1); } if (_transaction.reserved[2] != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Reserved2); } if (_transaction.reserved[3] != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Reserved3); } if (_transaction.signature.length != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.Signature); } if (_transaction.paymasterInput.length != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.PaymasterInput); } if (_transaction.reservedDynamic.length != 0) { revert InvalidUpgradeTxn(UpgradeTxVerifyParam.ReservedDynamic); } } /// @dev Calculates the approximate minimum gas limit required for executing a priority transaction. /// @param _encodingLength The length of the priority transaction encoding in bytes. /// @param _numberOfFactoryDependencies The number of new factory dependencies that will be added. /// @param _l2GasPricePerPubdata The L2 gas price for publishing the priority transaction on L2. /// @return The minimum gas limit required to execute the priority transaction. /// Note: The calculation includes the main cost of the priority transaction, however, in reality, the operator can spend a little more gas on overheads. function getMinimalPriorityTransactionGasLimit( uint256 _encodingLength, uint256 _numberOfFactoryDependencies, uint256 _l2GasPricePerPubdata ) internal pure returns (uint256) { uint256 costForComputation; { // Adding the intrinsic cost for the transaction, i.e. auxiliary prices which cannot be easily accounted for costForComputation = L1_TX_INTRINSIC_L2_GAS; // Taking into account the hashing costs that depend on the length of the transaction // Note that L1_TX_DELTA_544_ENCODING_BYTES is the delta in the price for every 544 bytes of // the transaction's encoding. It is taken as LCM between 136 and 32 (the length for each keccak256 round // and the size of each new encoding word). costForComputation += Math.ceilDiv(_encodingLength * L1_TX_DELTA_544_ENCODING_BYTES, 544); // Taking into the account the additional costs of providing new factory dependencies costForComputation += _numberOfFactoryDependencies * L1_TX_DELTA_FACTORY_DEPS_L2_GAS; // There is a minimal amount of computational L2 gas that the transaction should cover costForComputation = Math.max(costForComputation, L1_TX_MIN_L2_GAS_BASE); } uint256 costForPubdata = 0; { // Adding the intrinsic cost for the transaction, i.e. auxiliary prices which cannot be easily accounted for costForPubdata = L1_TX_INTRINSIC_PUBDATA * _l2GasPricePerPubdata; // Taking into the account the additional costs of providing new factory dependencies costForPubdata += _numberOfFactoryDependencies * L1_TX_DELTA_FACTORY_DEPS_PUBDATA * _l2GasPricePerPubdata; } return costForComputation + costForPubdata; } /// @notice Based on the full L2 gas limit (that includes the batch overhead) and other /// properties of the transaction, returns the l2GasLimit for the body of the transaction (the actual execution). /// @param _totalGasLimit The L2 gas limit that includes both the overhead for processing the batch /// and the L2 gas needed to process the transaction itself (i.e. the actual l2GasLimit that will be used for the transaction). /// @param _encodingLength The length of the ABI-encoding of the transaction. function getTransactionBodyGasLimit( uint256 _totalGasLimit, uint256 _encodingLength ) internal pure returns (uint256 txBodyGasLimit) { uint256 overhead = getOverheadForTransaction(_encodingLength); // provided gas limit doesn't cover transaction overhead if (_totalGasLimit < overhead) { revert TxnBodyGasLimitNotEnoughGas(); } unchecked { // We enforce the fact that `_totalGasLimit >= overhead` explicitly above. txBodyGasLimit = _totalGasLimit - overhead; } } /// @notice Based on the total L2 gas limit and several other parameters of the transaction /// returns the part of the L2 gas that will be spent on the batch's overhead. /// @dev The details of how this function works can be checked in the documentation /// of the fee model of ZKsync. The appropriate comments are also present /// in the Rust implementation description of function `get_maximal_allowed_overhead`. /// @param _encodingLength The length of the binary encoding of the transaction in bytes function getOverheadForTransaction( uint256 _encodingLength ) internal pure returns (uint256 batchOverheadForTransaction) { // The overhead from taking up the transaction's slot batchOverheadForTransaction = TX_SLOT_OVERHEAD_L2_GAS; // The overhead for occupying the bootloader memory can be derived from encoded_len uint256 overheadForLength = MEMORY_OVERHEAD_GAS * _encodingLength; batchOverheadForTransaction = Math.max(batchOverheadForTransaction, overheadForLength); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol"; import {ZkSyncHyperchainBase} from "../state-transition/chain-deps/facets/ZkSyncHyperchainBase.sol"; import {VerifierParams} from "../state-transition/chain-interfaces/IVerifier.sol"; import {IVerifier} from "../state-transition/chain-interfaces/IVerifier.sol"; import {L2ContractHelper} from "../common/libraries/L2ContractHelper.sol"; import {TransactionValidator} from "../state-transition/libraries/TransactionValidator.sol"; import {MAX_NEW_FACTORY_DEPS, SYSTEM_UPGRADE_L2_TX_TYPE, MAX_ALLOWED_MINOR_VERSION_DELTA} from "../common/Config.sol"; import {L2CanonicalTransaction} from "../common/Messaging.sol"; import {ProtocolVersionMinorDeltaTooBig, TimeNotReached, InvalidTxType, L2UpgradeNonceNotEqualToNewProtocolVersion, TooManyFactoryDeps, UnexpectedNumberOfFactoryDeps, ProtocolVersionTooSmall, PreviousUpgradeNotFinalized, PreviousUpgradeNotCleaned, L2BytecodeHashMismatch, PatchCantSetUpgradeTxn, PreviousProtocolMajorVersionNotZero, NewProtocolMajorVersionNotZero, PatchUpgradeCantSetDefaultAccount, PatchUpgradeCantSetBootloader} from "./ZkSyncUpgradeErrors.sol"; import {SemVer} from "../common/libraries/SemVer.sol"; /// @notice The struct that represents the upgrade proposal. /// @param l2ProtocolUpgradeTx The system upgrade transaction. /// @param factoryDeps The list of factory deps for the l2ProtocolUpgradeTx. /// @param bootloaderHash The hash of the new bootloader bytecode. If zero, it will not be updated. /// @param defaultAccountHash The hash of the new default account bytecode. If zero, it will not be updated. /// @param verifier The address of the new verifier. If zero, the verifier will not be updated. /// @param verifierParams The new verifier params. If all of its fields are 0, the params will not be updated. /// @param l1ContractsUpgradeCalldata Custom calldata for L1 contracts upgrade, it may be interpreted differently /// in each upgrade. Usually empty. /// @param postUpgradeCalldata Custom calldata for post upgrade hook, it may be interpreted differently in each /// upgrade. Usually empty. /// @param upgradeTimestamp The timestamp after which the upgrade can be executed. /// @param newProtocolVersion The new version number for the protocol after this upgrade. Should be greater than /// the previous protocol version. struct ProposedUpgrade { L2CanonicalTransaction l2ProtocolUpgradeTx; bytes[] factoryDeps; bytes32 bootloaderHash; bytes32 defaultAccountHash; address verifier; VerifierParams verifierParams; bytes l1ContractsUpgradeCalldata; bytes postUpgradeCalldata; uint256 upgradeTimestamp; uint256 newProtocolVersion; } /// @author Matter Labs /// @custom:security-contact [email protected] /// @notice Interface to which all the upgrade implementations should adhere abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { /// @notice Changes the protocol version event NewProtocolVersion(uint256 indexed previousProtocolVersion, uint256 indexed newProtocolVersion); /// @notice Сhanges to the bytecode that is used in L2 as a bootloader (start program) event NewL2BootloaderBytecodeHash(bytes32 indexed previousBytecodeHash, bytes32 indexed newBytecodeHash); /// @notice Сhanges to the bytecode that is used in L2 as a default account event NewL2DefaultAccountBytecodeHash(bytes32 indexed previousBytecodeHash, bytes32 indexed newBytecodeHash); /// @notice Verifier address changed event NewVerifier(address indexed oldVerifier, address indexed newVerifier); /// @notice Verifier parameters changed event NewVerifierParams(VerifierParams oldVerifierParams, VerifierParams newVerifierParams); /// @notice Notifies about complete upgrade event UpgradeComplete(uint256 indexed newProtocolVersion, bytes32 indexed l2UpgradeTxHash, ProposedUpgrade upgrade); /// @notice The main function that will be provided by the upgrade proxy /// @dev This is a virtual function and should be overridden by custom upgrade implementations. /// @param _proposedUpgrade The upgrade to be executed. /// @return txHash The hash of the L2 system contract upgrade transaction. function upgrade(ProposedUpgrade calldata _proposedUpgrade) public virtual returns (bytes32 txHash) { // Note that due to commitment delay, the timestamp of the L2 upgrade batch may be earlier than the timestamp // of the L1 block at which the upgrade occurred. This means that using timestamp as a signifier of "upgraded" // on the L2 side would be inaccurate. The effects of this "back-dating" of L2 upgrade batches will be reduced // as the permitted delay window is reduced in the future. if (block.timestamp < _proposedUpgrade.upgradeTimestamp) { revert TimeNotReached(_proposedUpgrade.upgradeTimestamp, block.timestamp); } (uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion); _upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata); _upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams); _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, isPatchOnly); txHash = _setL2SystemContractUpgrade( _proposedUpgrade.l2ProtocolUpgradeTx, _proposedUpgrade.factoryDeps, newMinorVersion, isPatchOnly ); _postUpgrade(_proposedUpgrade.postUpgradeCalldata); emit UpgradeComplete(_proposedUpgrade.newProtocolVersion, txHash, _proposedUpgrade); } /// @notice Change default account bytecode hash, that is used on L2 /// @param _l2DefaultAccountBytecodeHash The hash of default account L2 bytecode /// @param _patchOnly Whether only the patch part of the protocol version semver has changed function _setL2DefaultAccountBytecodeHash(bytes32 _l2DefaultAccountBytecodeHash, bool _patchOnly) private { if (_l2DefaultAccountBytecodeHash == bytes32(0)) { return; } if (_patchOnly) { revert PatchUpgradeCantSetDefaultAccount(); } L2ContractHelper.validateBytecodeHash(_l2DefaultAccountBytecodeHash); // Save previous value into the stack to put it into the event later bytes32 previousDefaultAccountBytecodeHash = s.l2DefaultAccountBytecodeHash; // Change the default account bytecode hash s.l2DefaultAccountBytecodeHash = _l2DefaultAccountBytecodeHash; emit NewL2DefaultAccountBytecodeHash(previousDefaultAccountBytecodeHash, _l2DefaultAccountBytecodeHash); } /// @notice Change bootloader bytecode hash, that is used on L2 /// @param _l2BootloaderBytecodeHash The hash of bootloader L2 bytecode /// @param _patchOnly Whether only the patch part of the protocol version semver has changed function _setL2BootloaderBytecodeHash(bytes32 _l2BootloaderBytecodeHash, bool _patchOnly) private { if (_l2BootloaderBytecodeHash == bytes32(0)) { return; } if (_patchOnly) { revert PatchUpgradeCantSetBootloader(); } L2ContractHelper.validateBytecodeHash(_l2BootloaderBytecodeHash); // Save previous value into the stack to put it into the event later bytes32 previousBootloaderBytecodeHash = s.l2BootloaderBytecodeHash; // Change the bootloader bytecode hash s.l2BootloaderBytecodeHash = _l2BootloaderBytecodeHash; emit NewL2BootloaderBytecodeHash(previousBootloaderBytecodeHash, _l2BootloaderBytecodeHash); } /// @notice Change the address of the verifier smart contract /// @param _newVerifier Verifier smart contract address function _setVerifier(IVerifier _newVerifier) private { // An upgrade to the verifier must be done carefully to ensure there aren't batches in the committed state // during the transition. If verifier is upgraded, it will immediately be used to prove all committed batches. // Batches committed expecting the old verifier will fail. Ensure all committed batches are finalized before the // verifier is upgraded. if (_newVerifier == IVerifier(address(0))) { return; } IVerifier oldVerifier = s.verifier; s.verifier = _newVerifier; emit NewVerifier(address(oldVerifier), address(_newVerifier)); } /// @notice Change the verifier parameters /// @param _newVerifierParams New parameters for the verifier function _setVerifierParams(VerifierParams calldata _newVerifierParams) private { // An upgrade to the verifier params must be done carefully to ensure there aren't batches in the committed state // during the transition. If verifier is upgraded, it will immediately be used to prove all committed batches. // Batches committed expecting the old verifier params will fail. Ensure all committed batches are finalized before the // verifier is upgraded. if ( _newVerifierParams.recursionNodeLevelVkHash == bytes32(0) && _newVerifierParams.recursionLeafLevelVkHash == bytes32(0) && _newVerifierParams.recursionCircuitsSetVksHash == bytes32(0) ) { return; } VerifierParams memory oldVerifierParams = s.__DEPRECATED_verifierParams; s.__DEPRECATED_verifierParams = _newVerifierParams; emit NewVerifierParams(oldVerifierParams, _newVerifierParams); } /// @notice Updates the verifier and the verifier params /// @param _newVerifier The address of the new verifier. If 0, the verifier will not be updated. /// @param _verifierParams The new verifier params. If all of the fields are 0, the params will not be updated. function _upgradeVerifier(address _newVerifier, VerifierParams calldata _verifierParams) internal { _setVerifier(IVerifier(_newVerifier)); _setVerifierParams(_verifierParams); } /// @notice Updates the bootloader hash and the hash of the default account /// @param _bootloaderHash The hash of the new bootloader bytecode. If zero, it will not be updated. /// @param _defaultAccountHash The hash of the new default account bytecode. If zero, it will not be updated. /// @param _patchOnly Whether only the patch part of the protocol version semver has changed. function _setBaseSystemContracts(bytes32 _bootloaderHash, bytes32 _defaultAccountHash, bool _patchOnly) internal { _setL2BootloaderBytecodeHash(_bootloaderHash, _patchOnly); _setL2DefaultAccountBytecodeHash(_defaultAccountHash, _patchOnly); } /// @notice Sets the hash of the L2 system contract upgrade transaction for the next batch to be committed /// @dev If the transaction is noop (i.e. its type is 0) it does nothing and returns 0. /// @param _l2ProtocolUpgradeTx The L2 system contract upgrade transaction. /// @param _factoryDeps The factory dependencies that are used by the transaction. /// @param _newMinorProtocolVersion The new minor protocol version. It must be used as the `nonce` field /// of the `_l2ProtocolUpgradeTx`. /// @param _patchOnly Whether only the patch part of the protocol version semver has changed. /// @return System contracts upgrade transaction hash. Zero if no upgrade transaction is set. function _setL2SystemContractUpgrade( L2CanonicalTransaction calldata _l2ProtocolUpgradeTx, bytes[] calldata _factoryDeps, uint32 _newMinorProtocolVersion, bool _patchOnly ) internal returns (bytes32) { // If the type is 0, it is considered as noop and so will not be required to be executed. if (_l2ProtocolUpgradeTx.txType == 0) { return bytes32(0); } if (_l2ProtocolUpgradeTx.txType != SYSTEM_UPGRADE_L2_TX_TYPE) { revert InvalidTxType(_l2ProtocolUpgradeTx.txType); } if (_patchOnly) { revert PatchCantSetUpgradeTxn(); } bytes memory encodedTransaction = abi.encode(_l2ProtocolUpgradeTx); TransactionValidator.validateL1ToL2Transaction( _l2ProtocolUpgradeTx, encodedTransaction, s.priorityTxMaxGasLimit, s.feeParams.priorityTxMaxPubdata ); TransactionValidator.validateUpgradeTransaction(_l2ProtocolUpgradeTx); // We want the hashes of l2 system upgrade transactions to be unique. // This is why we require that the `nonce` field is unique to each upgrade. if (_l2ProtocolUpgradeTx.nonce != _newMinorProtocolVersion) { revert L2UpgradeNonceNotEqualToNewProtocolVersion(_l2ProtocolUpgradeTx.nonce, _newMinorProtocolVersion); } _verifyFactoryDeps(_factoryDeps, _l2ProtocolUpgradeTx.factoryDeps); bytes32 l2ProtocolUpgradeTxHash = keccak256(encodedTransaction); s.l2SystemContractsUpgradeTxHash = l2ProtocolUpgradeTxHash; return l2ProtocolUpgradeTxHash; } /// @notice Verifies that the factory deps correspond to the proper hashes /// @param _factoryDeps The list of factory deps /// @param _expectedHashes The list of expected bytecode hashes function _verifyFactoryDeps(bytes[] calldata _factoryDeps, uint256[] calldata _expectedHashes) private pure { if (_factoryDeps.length != _expectedHashes.length) { revert UnexpectedNumberOfFactoryDeps(); } if (_factoryDeps.length > MAX_NEW_FACTORY_DEPS) { revert TooManyFactoryDeps(); } uint256 length = _factoryDeps.length; for (uint256 i = 0; i < length; ++i) { bytes32 bytecodeHash = L2ContractHelper.hashL2Bytecode(_factoryDeps[i]); if (bytecodeHash != bytes32(_expectedHashes[i])) { revert L2BytecodeHashMismatch(bytecodeHash, bytes32(_expectedHashes[i])); } } } /// @notice Changes the protocol version /// @param _newProtocolVersion The new protocol version function _setNewProtocolVersion( uint256 _newProtocolVersion ) internal virtual returns (uint32 newMinorVersion, bool patchOnly) { uint256 previousProtocolVersion = s.protocolVersion; if (_newProtocolVersion <= previousProtocolVersion) { revert ProtocolVersionTooSmall(); } // slither-disable-next-line unused-return (uint32 previousMajorVersion, uint32 previousMinorVersion, ) = SemVer.unpackSemVer( SafeCast.toUint96(previousProtocolVersion) ); if (previousMajorVersion != 0) { revert PreviousProtocolMajorVersionNotZero(); } uint32 newMajorVersion; // slither-disable-next-line unused-return (newMajorVersion, newMinorVersion, ) = SemVer.unpackSemVer(SafeCast.toUint96(_newProtocolVersion)); if (newMajorVersion != 0) { revert NewProtocolMajorVersionNotZero(); } // Since `_newProtocolVersion > previousProtocolVersion`, and both old and new major version is 0, // the difference between minor versions is >= 0. uint256 minorDelta = newMinorVersion - previousMinorVersion; if (minorDelta == 0) { patchOnly = true; } // While this is implicitly enforced by other checks above, we still double check just in case if (minorDelta > MAX_ALLOWED_MINOR_VERSION_DELTA) { revert ProtocolVersionMinorDeltaTooBig(MAX_ALLOWED_MINOR_VERSION_DELTA, minorDelta); } // If the minor version changes also, we need to ensure that the previous upgrade has been finalized. // In case the minor version does not change, we permit to keep the old upgrade transaction in the system, but it // must be ensured in the other parts of the upgrade that the upgrade transaction is not overridden. if (!patchOnly) { // If the previous upgrade had an L2 system upgrade transaction, we require that it is finalized. // Note it is important to keep this check, as otherwise hyperchains might skip upgrades by overwriting if (s.l2SystemContractsUpgradeTxHash != bytes32(0)) { revert PreviousUpgradeNotFinalized(s.l2SystemContractsUpgradeTxHash); } if (s.l2SystemContractsUpgradeBatchNumber != 0) { revert PreviousUpgradeNotCleaned(); } } s.protocolVersion = _newProtocolVersion; emit NewProtocolVersion(previousProtocolVersion, _newProtocolVersion); } /// @notice Placeholder function for custom logic for upgrading L1 contract. /// Typically this function will never be used. /// @param _customCallDataForUpgrade Custom data for an upgrade, which may be interpreted differently for each /// upgrade. function _upgradeL1Contract(bytes calldata _customCallDataForUpgrade) internal virtual {} /// @notice placeholder function for custom logic for post-upgrade logic. /// Typically this function will never be used. /// @param _customCallDataForUpgrade Custom data for an upgrade, which may be interpreted differently for each /// upgrade. function _postUpgrade(bytes calldata _customCallDataForUpgrade) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {ProposedUpgrade} from "./BaseZkSyncUpgrade.sol"; interface IDefaultUpgrade { function upgrade(ProposedUpgrade calldata _upgrade) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0x7a47c9a2 error InvalidChainId(); // 0xd7f8c13e error PreviousUpgradeBatchNotCleared(); // 0x3c43ccce error ProtocolMajorVersionNotZero(); // 0xd7f50a9d error PatchCantSetUpgradeTxn(); // 0xd2c011d6 error L2UpgradeNonceNotEqualToNewProtocolVersion(uint256 nonce, uint256 protocolVersion); // 0xcb5e4247 error L2BytecodeHashMismatch(bytes32 expected, bytes32 provided); // 0x88d7b498 error ProtocolVersionTooSmall(); // 0x56d45b12 error ProtocolVersionTooBig(); // 0x5c598b60 error PreviousProtocolMajorVersionNotZero(); // 0x72ea85ad error NewProtocolMajorVersionNotZero(); // 0xd328c12a error ProtocolVersionMinorDeltaTooBig(uint256 limit, uint256 proposed); // 0xe1a9736b error ProtocolVersionDeltaTooLarge(uint256 _proposedDelta, uint256 _maxDelta); // 0x6d172ab2 error ProtocolVersionShouldBeGreater(uint256 _oldProtocolVersion, uint256 _newProtocolVersion); // 0x559cc34e error PatchUpgradeCantSetDefaultAccount(); // 0x962fd7d0 error PatchUpgradeCantSetBootloader(); // 0x101ba748 error PreviousUpgradeNotFinalized(bytes32 txHash); // 0xa0f47245 error PreviousUpgradeNotCleaned(); // 0x07218375 error UnexpectedNumberOfFactoryDeps(); // 0x76da24b9 error TooManyFactoryDeps(); // 0x5cb29523 error InvalidTxType(uint256 txType); // 0x08753982 error TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp); // 0xd92e233d error ZeroAddress();
{ "optimizer": { "enabled": true, "runs": 9999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_bridgehub","type":"address"},{"internalType":"uint256","name":"_maxNumberOfHyperchains","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"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":[],"name":"HyperchainLimitReached","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":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"},{"indexed":false,"internalType":"bytes32","name":"newInitialCutHash","type":"bytes32"}],"name":"NewChainCreationParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_hyperchainContract","type":"address"}],"name":"NewHyperchain","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":"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":"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":"address","name":"_hyperchain","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":"SetChainIdUpgrade","type":"event"},{"inputs":[],"name":"BRIDGE_HUB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_HYPERCHAINS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"address","name":"_baseToken","type":"address"},{"internalType":"address","name":"_sharedBridge","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes","name":"_diamondCut","type":"bytes"}],"name":"createNewChain","outputs":[],"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"}],"name":"freezeChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisUpgrade","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllHyperchainChainIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllHyperchains","outputs":[{"internalType":"address[]","name":"chainAddresses","type":"address[]"}],"stateMutability":"view","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":"chainAddress","type":"address"}],"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":[],"name":"initialCutHash","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":"struct ChainCreationParams","name":"chainCreationParams","type":"tuple"},{"internalType":"uint256","name":"protocolVersion","type":"uint256"}],"internalType":"struct StateTransitionManagerInitializeData","name":"_initializeData","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_hyperchain","type":"address"}],"name":"registerAlreadyDeployedHyperchain","outputs":[],"stateMutability":"nonpayable","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":[{"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":"struct ChainCreationParams","name":"_chainCreationParams","type":"tuple"}],"name":"setChainCreationParams","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":"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":"_validatorTimelock","type":"address"}],"name":"setValidatorTimelock","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"}]
Contract Creation Code
60c060405234801562000010575f80fd5b5060405162005008380380620050088339810160408190526200003391620000a0565b6200003d62000055565b6001600160a01b039190911660805260a052620000d9565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf48054600190915580156200009d5760405163df3a8fdd60e01b815260040160405180910390fd5b50565b5f8060408385031215620000b2575f80fd5b82516001600160a01b0381168114620000c9575f80fd5b6020939093015192949293505050565b60805160a051614ef8620001105f395f8181610565015261199a01525f8181610467015281816111c801526112d30152614ef85ff3fe608060405234801562000010575f80fd5b5060043610620002fc575f3560e01c80639366518b116200019b578063def9d6af11620000ef578063f2fde38b116200009f578063f6370c7b1162000077578063f6370c7b14620006ef578063f851a4401462000706578063fa8f7ea61462000727575f80fd5b8063f2fde38b1462000684578063f4943a20146200069b578063f5c1182c14620006bd575f80fd5b8063e34a329a11620000d3578063e34a329a1462000635578063e66c8c44146200064c578063ec3d5f88146200066d575f80fd5b8063def9d6af14620005e0578063e30c39781462000616575f80fd5b8063bf54096e116200014b578063d241f618116200012f578063d241f618146200059e578063d2ef1b0e14620005bf578063dead6f7f14620005c9575f80fd5b8063bf54096e146200055f578063cf347e171462000587575f80fd5b8063a75b496d116200017f578063a75b496d1462000518578063aad742621462000531578063accdd16c1462000548575f80fd5b80639366518b14620004ea578063984615041462000501575f80fd5b806351d218f71162000253578063715018a611620002035780637ebba67211620001e75780637ebba672146200049d5780637fb6781614620004b45780638da5cb5b14620004cb575f80fd5b8063715018a6146200048957806379ba50971462000493575f80fd5b806353ce2061116200023757806353ce2061146200044057806357e6246b14620004575780635d4edca71462000461575f80fd5b806351d218f7146200040757806352c9eacb146200041e575f80fd5b806326e4ae2511620002af5780632e52285111620002935780632e522851146200039c578063301e776514620003b35780634dd18bf514620003f0575f80fd5b806326e4ae2514620003685780632ae9c600146200037f575f80fd5b80630dbad27e11620002e35780630dbad27e14620003305780630e18b681146200034757806318717dc11462000351575f80fd5b8063027f12e114620003005780630d14edf71462000319575b5f80fd5b6200031762000311366004620025e5565b62000740565b005b620003176200032a3660046200266e565b620007c4565b6200031762000341366004620026b6565b6200082c565b62000317620008b3565b620003176200036236600462002716565b620009e7565b620003176200037936600462002743565b62000a55565b62000389609d5481565b6040519081526020015b60405180910390f35b62000317620003ad3660046200277d565b62000b85565b620003ca620003c4366004620027d1565b62000cbc565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000393565b6200031762000401366004620027e9565b62000d3f565b6200031762000418366004620027d1565b62000e31565b620003896200042f366004620027d1565b60a06020525f908152604090205481565b620003176200045136600462002807565b62000ea7565b62000389609b5481565b620003ca7f000000000000000000000000000000000000000000000000000000000000000081565b6200031762000f6b565b6200031762000f82565b62000317620004ae36600462002848565b62001038565b62000317620004c5366004620027e9565b620010be565b60335473ffffffffffffffffffffffffffffffffffffffff16620003ca565b62000317620004fb36600462002886565b620011b0565b62000317620005123660046200293c565b62001453565b62000522620014e5565b60405162000393919062002982565b620003176200054236600462002807565b620014f8565b6200031762000559366004620027d1565b62001513565b620003897f000000000000000000000000000000000000000000000000000000000000000081565b6200031762000598366004620029c7565b6200156f565b609c54620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b62000389609a5481565b620003ca620005da366004620027d1565b62001657565b62000605620005f1366004620027d1565b5f908152609e602052604090205442111590565b604051901515815260200162000393565b60655473ffffffffffffffffffffffffffffffffffffffff16620003ca565b6200031762000646366004620029fe565b6200166c565b609f54620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b620003176200067e36600462002807565b620016bd565b6200031762000695366004620027e9565b6200170f565b62000389620006ac366004620027d1565b609e6020525f908152604090205481565b620006c7620017c2565b6040805163ffffffff9485168152928416602084015292169181019190915260600162000393565b620003176200070036600462002a46565b62001800565b60a154620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b6200073162001815565b60405162000393919062002a80565b6200074a620018f9565b620007576097836200197c565b73ffffffffffffffffffffffffffffffffffffffff166364bf8d66826040518263ffffffff1660e01b815260040162000791919062002afb565b5f604051808303815f87803b158015620007a9575f80fd5b505af1158015620007bc573d5f803e3d5ffd5b505050505050565b620007ce620018f9565b73ffffffffffffffffffffffffffffffffffffffff81166200081c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000828828262001989565b5050565b62000836620018f9565b620008436097846200197c565b73ffffffffffffffffffffffffffffffffffffffff1663fc57565f83836040518363ffffffff1660e01b81526004016200087f92919062002ee9565b5f604051808303815f87803b15801562000897575f80fd5b505af1158015620008aa573d5f803e3d5ffd5b50505050505050565b60a25473ffffffffffffffffffffffffffffffffffffffff163381146200090d576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60a1805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560a280549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b620009f1620018f9565b620009fe6097836200197c565b6040517f1cc5d103000000000000000000000000000000000000000000000000000000008152821515600482015273ffffffffffffffffffffffffffffffffffffffff9190911690631cc5d1039060240162000791565b62000a5f62001a44565b5f62000a6f6020830183620027e9565b73ffffffffffffffffffffffffffffffffffffffff160362000abd576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000ad662000ad06020830183620027e9565b62001aa5565b6060810135609d8190555f908152609e60209081526040918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905562000b24918301908301620027e9565b609f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905562000b8262000b7c604083018362002f03565b62001ad8565b50565b62000b8f620018f9565b5f8460405160200162000ba3919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120609d80545f8a815260a08552858120849055609e9094528484208990558784529383207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905586905593509091849183917f4235104f56661fe2e9d2f2a460b42766581bc45ce366c6a30a9f86c8a2b371a79190a3604051829086907f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d4905f90a3827ff99295383247eabb6bee8798669fa768502f8843d3be0e82a0aa81d7b6c4f60c8760405162000cac919062002f40565b60405180910390a2505050505050565b5f62000cca6097836200197c565b73ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000d13573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000d39919062002f54565b92915050565b60a15473ffffffffffffffffffffffffffffffffffffffff16331480159062000d80575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1562000dbb576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b60a2805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b62000e3b620018f9565b62000e486097826200197c565b73ffffffffffffffffffffffffffffffffffffffff1663173389456040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562000e8d575f80fd5b505af115801562000ea0573d5f803e3d5ffd5b5050505050565b60a15473ffffffffffffffffffffffffffffffffffffffff16331480159062000ee8575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1562000f23576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b62000f306097836200197c565b73ffffffffffffffffffffffffffffffffffffffff166397c09d34826040518263ffffffff1660e01b81526004016200079191815260200190565b62000f75620018f9565b62000f805f62001aa5565b565b606554339073ffffffffffffffffffffffffffffffffffffffff1681146200102d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e65720000000000000000000000000000000000000000000000606482015260840162000904565b62000b828162001aa5565b62001042620018f9565b6200104f6097846200197c565b6040517f235d9eb50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff80851660048301528316602482015273ffffffffffffffffffffffffffffffffffffffff919091169063235d9eb5906044016200087f565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590620010ff575060335473ffffffffffffffffffffffffffffffffffffffff163314155b156200113a576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5a1b0d8808a8dca64c1f7c230dce7a09f7f9a1c26507e190e03dcd382e69018e905f90a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161462001223576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b5f6200122f8762001657565b73ffffffffffffffffffffffffffffffffffffffff1603620007bc575f6200125a82840184620030fa565b90505f83836040516200126f9291906200331b565b60405180910390209050609b548114620012c457609b546040517f0b08d5be00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440162000904565b606063e4441b9860e01b895f1b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff165f1b3073ffffffffffffffffffffffffffffffffffffffff165f1b609d545f1b8a73ffffffffffffffffffffffffffffffffffffffff165f1b609f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165f1b8e73ffffffffffffffffffffffffffffffffffffffff165f1b8e73ffffffffffffffffffffffffffffffffffffffff165f1b609a548c60400151604051602001620013d19b9a999897969594939291906200334e565b60405160208183030381529060405290508083604001819052505f805f1b4685604051620013ff90620025d7565b6200140c92919062003573565b8190604051809103905ff59050801580156200142a573d5f803e3d5ffd5b509050806200143a8b8262001989565b620014468b8262001e83565b5050505050505050505050565b6200145d620018f9565b5f8260405160200162001471919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f86815260a0909252918120829055909250829184917f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d491a3505050565b6060620014f3609762002263565b905090565b62001502620018f9565b5f918252609e602052604090912055565b6200151d620018f9565b6200152a6097826200197c565b73ffffffffffffffffffffffffffffffffffffffff166327ae4c166040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562000e8d575f80fd5b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590620015b0575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15620015eb576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b620015f86097846200197c565b6040517f4623c91d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283151560248301529190911690634623c91d906044016200087f565b5f6200166560978362002271565b9392505050565b62001676620018f9565b620016836097836200197c565b73ffffffffffffffffffffffffffffffffffffffff1663a9f6d941826040518263ffffffff1660e01b815260040162000791919062002f40565b620016c7620018f9565b620016d46097836200197c565b73ffffffffffffffffffffffffffffffffffffffff1663be6f11cf826040518263ffffffff1660e01b81526004016200079191815260200190565b62001719620018f9565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556200177d60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f805f620017f5620017d6609d5462002290565b63ffffffff604082901c169167ffffffffffffffff602083901c169190565b925092509250909192565b6200180a620018f9565b62000b828162001ad8565b60605f62001824609762002263565b9050805167ffffffffffffffff81111562001843576200184362002f72565b6040519080825280602002602001820160405280156200186d578160200160208202803683370190505b5081519092505f5b81811015620018f357620018b08382815181106200189757620018976200358d565b602002602001015160976200197c90919063ffffffff16565b848281518110620018c557620018c56200358d565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010162001875565b50505090565b60335473ffffffffffffffffffffffffffffffffffffffff16331462000f80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000904565b5f62001665838362002333565b6200199760978383620023c1565b507f0000000000000000000000000000000000000000000000000000000000000000620019c56097620023ed565b1115620019fe576040517fb615c2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff82169083907f6cb7904ba60de613ccb460be43d4ab7c4fb9ad601052ce4b7e19993955974717905f90a35050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf480546001909155801562000b82576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905562000b8281620023f9565b5f62001ae86020830183620027e9565b73ffffffffffffffffffffffffffffffffffffffff160362001b36576040517f3a1a858900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013562001b72576040517f7940c83f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62001b856060830160408401620035ba565b67ffffffffffffffff160362001bc7576040517fb4fc683500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081013562001c03576040517f6d4a7df800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001c126020820182620027e9565b609c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905560408051610100810182525f80825260208481013590830152918181019062001c879060608601908601620035ba565b67ffffffffffffffff1681526020015f81526020017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f1b81526020015f801b81526020015f8152602001836060013581525090508060405160200162001d4f91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609a555f62001d986080840184620035d6565b60405160200162001daa919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602091820120609b81905591507ff693b52e1edb097c83c4406c189a03e96be0e6c7cf7a4544b1986b08f76a17969062001e1790850185620027e9565b602085013562001e2e6060870160408801620035ba565b6040805173ffffffffffffffffffffffffffffffffffffffff9094168452602084019290925267ffffffffffffffff1690820152606080860135908201526080810183905260a00160405180910390a1505050565b5f8260405160240162001e9891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fef0e2ff400000000000000000000000000000000000000000000000000000000179052609d5490915060609081905f62001f29620017d68362002290565b509150505f60405180610200016040528060fe815260200161800773ffffffffffffffffffffffffffffffffffffffff16815260200161800b73ffffffffffffffffffffffffffffffffffffffff16815260200163044aa200815260200161032081526020015f81526020015f81526020015f81526020018363ffffffff1681526020015f815260200160405180608001604052805f81526020015f81526020015f81526020015f81525081526020018781526020015f67ffffffffffffffff81111562001ffb5762001ffb62002f72565b6040519080825280601f01601f19166020018201604052801562002026576020820181803683370190505b5081526020808201889052604080515f808252818401835282850191909152815181815280840183526060948501528151610140810183528581528084018a9052808301829052808501829052608081018290528251808601845282815280850183905280840183905260a08201528251828152808501845260c08201528251828152808501845260e08201526101008101829052610120810189905282518086018452858152609c5473ffffffffffffffffffffffffffffffffffffffff16948101949094528251959650949092918201906200210990869060240162003806565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f08284e57000000000000000000000000000000000000000000000000000000001790529152517fa9f6d94100000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8b169063a9f6d94190620021d690849060040162003926565b5f604051808303815f87803b158015620021ee575f80fd5b505af115801562002201573d5f803e3d5ffd5b50505050858a73ffffffffffffffffffffffffffffffffffffffff167f6cddf65a8ecde9818f721d40492026200e10a08f5057291c5cc77eb7d020d617866040516200224e91906200393a565b60405180910390a35050505050505050505050565b60605f62001665836200246f565b5f8080806200228186866200247c565b909450925050505b9250929050565b5f6bffffffffffffffffffffffff8211156200232f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f3620626974730000000000000000000000000000000000000000000000000000606482015260840162000904565b5090565b5f81815260028301602052604081205480151580620023595750620023598484620024b9565b62001665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640162000904565b5f620023e5848473ffffffffffffffffffffffffffffffffffffffff8516620024c6565b949350505050565b5f62000d3982620024e4565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606062000d3982620024f0565b5f818152600283016020526040812054819080620024ad57620024a08585620024b9565b92505f9150620022899050565b60019250905062002289565b5f620016658383620024fe565b5f8281526002840160205260408120829055620023e5848462002516565b5f62000d398262002523565b60605f62001665836200252d565b5f818152600183016020526040812054151562001665565b5f62001665838362002588565b5f62000d39825490565b6060815f018054806020026020016040519081016040528092919081815260200182805480156200257c57602002820191905f5260205f20905b81548152602001906001019080831162002567575b50505050509050919050565b5f818152600183016020526040812054620025cf57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915562000d39565b505f62000d39565b611574806200394f83390190565b5f8082840360e0811215620025f8575f80fd5b8335925060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820112156200262c575f80fd5b506020830190509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811462000b82575f80fd5b803562002669816200263a565b919050565b5f806040838503121562002680575f80fd5b82359150602083013562002694816200263a565b809150509250929050565b5f60608284031215620026b0575f80fd5b50919050565b5f805f60608486031215620026c9575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115620026ee575f80fd5b620026fc868287016200269f565b9150509250925092565b8035801515811462002669575f80fd5b5f806040838503121562002728575f80fd5b823591506200273a6020840162002706565b90509250929050565b5f6020828403121562002754575f80fd5b813567ffffffffffffffff8111156200276b575f80fd5b82016080818503121562001665575f80fd5b5f805f806080858703121562002791575f80fd5b843567ffffffffffffffff811115620027a8575f80fd5b620027b6878288016200269f565b97602087013597506040870135966060013595509350505050565b5f60208284031215620027e2575f80fd5b5035919050565b5f60208284031215620027fa575f80fd5b813562001665816200263a565b5f806040838503121562002819575f80fd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff8116811462002669575f80fd5b5f805f606084860312156200285b575f80fd5b833592506200286d6020850162002828565b91506200287d6040850162002828565b90509250925092565b5f805f805f8060a087890312156200289c575f80fd5b863595506020870135620028b0816200263a565b94506040870135620028c2816200263a565b93506060870135620028d4816200263a565b9250608087013567ffffffffffffffff80821115620028f1575f80fd5b818901915089601f83011262002905575f80fd5b81358181111562002914575f80fd5b8a602082850101111562002926575f80fd5b6020830194508093505050509295509295509295565b5f80604083850312156200294e575f80fd5b823567ffffffffffffffff81111562002965575f80fd5b62002973858286016200269f565b95602094909401359450505050565b602080825282518282018190525f9190848201906040850190845b81811015620029bb578351835292840192918401916001016200299d565b50909695505050505050565b5f805f60608486031215620029da575f80fd5b833592506020840135620029ee816200263a565b91506200287d6040850162002706565b5f806040838503121562002a10575f80fd5b82359150602083013567ffffffffffffffff81111562002a2e575f80fd5b62002a3c858286016200269f565b9150509250929050565b5f6020828403121562002a57575f80fd5b813567ffffffffffffffff81111562002a6e575f80fd5b820160a0818503121562001665575f80fd5b602080825282518282018190525f9190848201906040850190845b81811015620029bb57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010162002a9b565b803563ffffffff8116811462002669575f80fd5b803567ffffffffffffffff8116811462002669575f80fd5b60c0810182356002811062002b0e575f80fd5b825262002b1e6020840162002acf565b63ffffffff80821660208501528062002b3a6040870162002acf565b1660408501528062002b4f6060870162002acf565b1660608501528062002b646080870162002acf565b166080850152505067ffffffffffffffff62002b8360a0850162002ae3565b1660a083015292915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262002bc3575f80fd5b830160208101925035905067ffffffffffffffff81111562002be3575f80fd5b8060051b360382131562002289575f80fd5b80356003811062002669575f80fd5b6003811062002c3a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811462002669575f80fd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262002ca2575f80fd5b830160208101925035905067ffffffffffffffff81111562002cc2575f80fd5b80360382131562002289575f80fd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f606080840162002d2a848562002b8f565b6060875291829052608091828701600582901b88018401835f5b8481101562002e86577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808b840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8187360301811262002da6575f80fd5b8601838801813562002db8816200263a565b73ffffffffffffffffffffffffffffffffffffffff168552602062002ddf83820162002bf5565b62002ded8288018262002c04565b50604062002dfd81850162002706565b15159087015262002e11838c018462002b8f565b878d018c9052928390529192505f60a087015b8482101562002e6f577fffffffff0000000000000000000000000000000000000000000000000000000062002e598562002c3e565b1681529282019260019190910190820162002e24565b978201979650509390930192505060010162002d44565b505062002e96602089016200265c565b73ffffffffffffffffffffffffffffffffffffffff811660208b0152955062002ec3604089018962002c6e565b9650945088810360408a015262002edc81878762002cd1565b9998505050505050505050565b828152604060208201525f620023e5604083018462002d18565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811262002f36575f80fd5b9190910192915050565b602081525f62001665602083018462002d18565b5f6020828403121562002f65575f80fd5b815162001665816200263a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff8111828210171562002fc55762002fc562002f72565b60405290565b6040516080810167ffffffffffffffff8111828210171562002fc55762002fc562002f72565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200303b576200303b62002f72565b604052919050565b5f67ffffffffffffffff8211156200305f576200305f62002f72565b5060051b60200190565b5f82601f83011262003079575f80fd5b813567ffffffffffffffff81111562003096576200309662002f72565b620030c960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160162002ff1565b818152846020838601011115620030de575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156200310b575f80fd5b67ffffffffffffffff808335111562003122575f80fd5b823583016060818603121562003136575f80fd5b6200314062002f9f565b82823511156200314e575f80fd5b8135820186601f82011262003161575f80fd5b6200317762003171823562003043565b62002ff1565b81358082526020808301929160051b8401018981111562003196575f80fd5b602084015b81811015620032d0578781351115620031b2575f80fd5b8035850160807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828e03011215620031e8575f80fd5b620031f262002fcb565b6200320160208301356200263a565b60208201358152620032166040830162002bf5565b6020820152620032296060830162002706565b604082015289608083013511156200323f575f80fd5b6080820135820191508c603f83011262003257575f80fd5b60208201356200326b620031718262003043565b81815260059190911b83016040019060208101908f8311156200328c575f80fd5b6040850194505b82851015620032b957620032a78562002c3e565b82526020948501949091019062003293565b60608401525050855250602093840193016200319b565b5050835250620032e59050602083016200265c565b60208201528260408301351115620032fb575f80fd5b6200330d866040840135840162003069565b604082015295945050505050565b818382375f9101908152919050565b5f5b83811015620033465781810151838201526020016200332c565b50505f910152565b7fffffffff000000000000000000000000000000000000000000000000000000008c1681528a60048201528960248201528860448201528760648201528660848201528560a48201528460c48201528360e4820152826101048201525f6101248351620033c281838601602088016200332a565b929092019091019c9b505050505050505050505050565b5f8151808452620033f28160208601602086016200332a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b5f60608084018351606086528181518084526080935060808801915060808160051b890101602080850194505f5b8381101562003535577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808b8403018552855187840173ffffffffffffffffffffffffffffffffffffffff825116855283820151620034b38587018262002c04565b50604082810151151590860152908901518985018990528051918290528301905f9060a08601905b808310156200351f5783517fffffffff00000000000000000000000000000000000000000000000000000000168252928501926001929092019190850190620034db565b5097840197968401969450505060010162003452565b508881015173ffffffffffffffffffffffffffffffffffffffff81168b8301529650506040880151955088810360408a015262002edc8187620033d9565b828152604060208201525f620023e5604083018462003424565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215620035cb575f80fd5b620016658262002ae3565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811262002f36575f80fd5b805f5b60048110156200362d5781518452602093840193909101906001016200360c565b50505050565b5f815180845260208085019450602084015f5b83811015620036645781518752958201959082019060010162003646565b509495945050505050565b5f610260825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151620036ea8287018262003609565b50506101608301516101c082818701526200370883870183620033d9565b925061018085015191506101e086840381880152620037288484620033d9565b93506101a0860151925086840361020088015262003747848462003633565b9350818601519250868403610220880152620037648484620033d9565b93508086015192505050848203610240860152620037838282620033d9565b95945050505050565b5f8282518085526020808601955060208260051b840101602086015f5b84811015620037f9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952620037e6838351620033d9565b98840198925090830190600101620037a9565b5090979650505050505050565b602081525f8251610180806020850152620038266101a08501836200366f565b915060208501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030160408701526200386484836200378c565b9350604087015160608701526060870151608087015260808701519150620038a460a087018373ffffffffffffffffffffffffffffffffffffffff169052565b60a0870151805160c0880152602081015160e08801526040810151610100880152915060c08701519150610120818786030181880152620038e68584620033d9565b945060e088015192508187860301610140880152620039068584620033d9565b610100890151610160890152970151929095019190915250929392505050565b602081525f62001665602083018462003424565b602081525f6200166560208301846200366f56fe608060405234801562000010575f80fd5b506040516200157438038062001574833981016040819052620000339162000f1c565b4682146200006d5760405162461bcd60e51b8152602060048201526002602482015261383960f11b60448201526064015b60405180910390fd5b620000788162000080565b5050620012ae565b80516020820151604083015182515f5b8181101562000202575f858281518110620000af57620000af620010c0565b60200260200101516020015190505f868381518110620000d357620000d3620010c0565b60200260200101515f015190505f878481518110620000f657620000f6620010c0565b60200260200101516040015190505f8885815181106200011a576200011a620010c0565b602002602001015160600151905080515f036200014a57604051630a6fef7160e41b815260040160405180910390fd5b5f846002811115620001605762000160620010d4565b0362000179576200017383828462000253565b620001e5565b6001846002811115620001905762000190620010d4565b03620001a3576200017383828462000389565b6002846002811115620001ba57620001ba620010d4565b03620001cc57620001738382620004a5565b60405163e52478c760e01b815260040160405180910390fd5b50505050620001fa81620005ae60201b60201c565b905062000090565b506200020f8383620005b4565b7f87b829356b3403d36217eff1f66ee48eacd0a69015153aba4f0de29fe5340c30848484604051620002449392919062001115565b60405180910390a15050505050565b5f80516020620015548339815191526001600160a01b0384163b5f0362000299576040516310d76a3760e31b81526001600160a01b038516600482015260240162000064565b620002a48462000707565b82515f5b8181101562000381575f858281518110620002c757620002c7620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff1615159181019190915290925090156200036957805160405163158947f360e31b81526001600160e01b0319841660048201526001600160a01b03909116602482015260440162000064565b62000376888388620007b1565b5050600101620002a8565b505050505050565b5f80516020620015548339815191526001600160a01b0384163b5f03620003cf576040516310d76a3760e31b81526001600160a01b038516600482015260240162000064565b82515f5b8181101562000381575f858281518110620003f257620003f2620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250906200047457604051630d600dc360e21b815260040160405180910390fd5b80516200048290836200095f565b6200048d8862000707565b6200049a888388620007b1565b5050600101620003d3565b5f80516020620015548339815191526001600160a01b03831615620004e95760405163333e8bef60e11b81526001600160a01b038416600482015260240162000064565b81515f5b81811015620005a7575f8482815181106200050c576200050c620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250906200058e576040516328b52c5b60e21b815260040160405180910390fd5b80516200059c90836200095f565b5050600101620004ed565b5050505050565b60010190565b6001600160a01b038216620005e857805115620005e45760405163c21b1ab760e01b815260040160405180910390fd5b5050565b5f80836001600160a01b03168360405162000604919062001224565b5f60405180830381855af49150503d805f81146200063e576040519150601f19603f3d011682016040523d82523d5f602084013e62000643565b606091505b5091509150816200067e5760048151101562000676578060405163f7a01e4d60e01b815260040162000064919062001241565b805160208201fd5b8051602014620006a5578060405163f7a01e4d60e01b815260040162000064919062001241565b7f33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a25f1b81806020019051810190620006de91906200125c565b1462000701578060405163f7a01e4d60e01b815260040162000064919062001241565b50505050565b6001600160a01b0381165f9081525f805160206200153483398151915260205260408120545f805160206200155483398151915291819003620007ac576002820154620007549062000b58565b6001600160a01b0384165f81815260018581016020908152604083208201805461ffff191661ffff96909616959095179094556002860180549182018155825292902090910180546001600160a01b03191690911790555b505050565b6001600160a01b0383165f9081525f805160206200153483398151915260205260408120545f80516020620015548339815191529190620007f29062000b58565b905061ffff81161562000896576001600160a01b0385165f9081526001830160205260408120805482906200082b576200082b620010c0565b5f918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03198116835290859052604090912054909150600160b01b900460ff16151584151514620008945760405163d3b6535b60e01b815260040160405180910390fd5b505b604080516060810182526001600160a01b0396871680825261ffff93841660208084019182529615158385019081526001600160e01b031989165f90815287895285812094518554935192519b166001600160b01b031990931692909217600160a01b91909616029490941760ff60b01b1916600160b01b981515989098029790971790559481526001918201835293842080549182018155845292206008830401805463ffffffff60079094166004026101000a938402191660e09290921c92909202179055565b6001600160e01b031981165f9081525f805160206200155483398151915260208181526040808420546001600160a01b03871685525f80516020620015348339815191529092528320549192600160a01b90910461ffff1691620009c69060019062001274565b905080821462000ac9576001600160a01b0385165f9081526001840160205260408120805483908110620009fe57620009fe620010c0565b5f91825260208083206008830401546001600160a01b038a168452600188019091526040909220805460079092166004026101000a90920460e01b92508291908590811062000a515762000a51620010c0565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555062000a908362000b5860201b60201c565b6001600160e01b03199091165f908152602085905260409020805461ffff92909216600160a01b0261ffff60a01b199092169190911790555b6001600160a01b0385165f908152600184016020526040902080548062000af45762000af46200129a565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319861682528490526040812080546001600160b81b0319169055819003620005a757620005a78562000bc0565b5f61ffff82111562000bbc5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b606482015260840162000064565b5090565b6001600160a01b0381165f9081525f8051602062001534833981519152602052604081206001908101547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d545f80516020620015548339815191529361ffff9092169262000c2e9162001274565b905080821462000ce9575f83600201828154811062000c515762000c51620010c0565b5f918252602090912001546002850180546001600160a01b03909216925082918590811062000c845762000c84620010c0565b5f91825260209091200180546001600160a01b0319166001600160a01b039290921691909117905562000cb78362000b58565b6001600160a01b03919091165f9081526001858101602052604090912001805461ffff191661ffff9092169190911790555b8260020180548062000cff5762000cff6200129a565b5f8281526020902081015f1990810180546001600160a01b031916905501905550505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171562000d5e5762000d5e62000d25565b60405290565b604051608081016001600160401b038111828210171562000d5e5762000d5e62000d25565b604051601f8201601f191681016001600160401b038111828210171562000db45762000db462000d25565b604052919050565b5f6001600160401b0382111562000dd75762000dd762000d25565b5060051b60200190565b80516001600160a01b038116811462000df8575f80fd5b919050565b5f82601f83011262000e0d575f80fd5b8151602062000e2662000e208362000dbc565b62000d89565b8083825260208201915060208460051b87010193508684111562000e48575f80fd5b602086015b8481101562000e7c5780516001600160e01b03198116811462000e6e575f80fd5b835291830191830162000e4d565b509695505050505050565b5f5b8381101562000ea357818101518382015260200162000e89565b50505f910152565b5f82601f83011262000ebb575f80fd5b81516001600160401b0381111562000ed75762000ed762000d25565b62000eec601f8201601f191660200162000d89565b81815284602083860101111562000f01575f80fd5b62000f1482602083016020870162000e87565b949350505050565b5f806040838503121562000f2e575f80fd5b825160208401519092506001600160401b038082111562000f4d575f80fd5b908401906060828703121562000f61575f80fd5b62000f6b62000d39565b82518281111562000f7a575f80fd5b8301601f8101881362000f8b575f80fd5b805162000f9c62000e208262000dbc565b8082825260208201915060208360051b85010192508a83111562000fbe575f80fd5b602084015b83811015620010735780518781111562000fdb575f80fd5b85016080818e03601f1901121562000ff1575f80fd5b62000ffb62000d64565b620010096020830162000de1565b81526040820151600381106200101d575f80fd5b60208201526060820151801515811462001035575f80fd5b60408201526080820151898111156200104c575f80fd5b6200105d8f60208386010162000dfd565b6060830152508452506020928301920162000fc3565b50845250620010889150506020840162000de1565b60208201526040830151828111156200109f575f80fd5b620010ad8882860162000eab565b6040830152508093505050509250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f81518084526200110181602086016020860162000e87565b601f01601f19169290920160200192915050565b5f6060808301606084528087518083526080925060808601915060808160051b8701016020808b015f5b84811015620011f257898403607f19018652815180516001600160a01b031685528381015188860190600381106200118557634e487b7160e01b5f52602160045260245ffd5b86860152604082810151151590870152908901518986018990528051918290528401905f9060a08701905b80831015620011dc5783516001600160e01b0319168252928601926001929092019190860190620011b0565b509785019795505050908201906001016200113f565b50506001600160a01b038a16908801528681036040880152620012168189620010e8565b9a9950505050505050505050565b5f82516200123781846020870162000e87565b9190910192915050565b602081525f620012556020830184620010e8565b9392505050565b5f602082840312156200126d575f80fd5b5051919050565b818103818111156200129457634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603160045260245ffd5b61027880620012bc5f395ff3fe60806040527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b600436101580610033575036155b61009e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f557400000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b5f80357fffffffff0000000000000000000000000000000000000000000000000000000016815260208281526040918290208251606081018452905473ffffffffffffffffffffffffffffffffffffffff811680835274010000000000000000000000000000000000000000820461ffff1693830193909352760100000000000000000000000000000000000000000000900460ff16151592810192909252806101a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f46000000000000000000000000000000000000000000000000000000000000006044820152606401610095565b600383015460ff1615806101ba57508160400151155b610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f71310000000000000000000000000000000000000000000000000000000000006044820152606401610095565b604051365f82375f803683855af43d805f843e81801561023e578184f35b8184fdfea2646970667358221220008b4899e63d1da58f6c056a941f85d587091ca7906cccff6c0a8e1a3ea76de164736f6c63430008180033c8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131cc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ba2646970667358221220790b6e55112efe113fe74ec195f76da5657d9108fb54b1e6f9e757dc45a9f66a64736f6c63430008180033000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb52130000000000000000000000000000000000000000000000000000000000000064
Deployed Bytecode
0x608060405234801562000010575f80fd5b5060043610620002fc575f3560e01c80639366518b116200019b578063def9d6af11620000ef578063f2fde38b116200009f578063f6370c7b1162000077578063f6370c7b14620006ef578063f851a4401462000706578063fa8f7ea61462000727575f80fd5b8063f2fde38b1462000684578063f4943a20146200069b578063f5c1182c14620006bd575f80fd5b8063e34a329a11620000d3578063e34a329a1462000635578063e66c8c44146200064c578063ec3d5f88146200066d575f80fd5b8063def9d6af14620005e0578063e30c39781462000616575f80fd5b8063bf54096e116200014b578063d241f618116200012f578063d241f618146200059e578063d2ef1b0e14620005bf578063dead6f7f14620005c9575f80fd5b8063bf54096e146200055f578063cf347e171462000587575f80fd5b8063a75b496d116200017f578063a75b496d1462000518578063aad742621462000531578063accdd16c1462000548575f80fd5b80639366518b14620004ea578063984615041462000501575f80fd5b806351d218f71162000253578063715018a611620002035780637ebba67211620001e75780637ebba672146200049d5780637fb6781614620004b45780638da5cb5b14620004cb575f80fd5b8063715018a6146200048957806379ba50971462000493575f80fd5b806353ce2061116200023757806353ce2061146200044057806357e6246b14620004575780635d4edca71462000461575f80fd5b806351d218f7146200040757806352c9eacb146200041e575f80fd5b806326e4ae2511620002af5780632e52285111620002935780632e522851146200039c578063301e776514620003b35780634dd18bf514620003f0575f80fd5b806326e4ae2514620003685780632ae9c600146200037f575f80fd5b80630dbad27e11620002e35780630dbad27e14620003305780630e18b681146200034757806318717dc11462000351575f80fd5b8063027f12e114620003005780630d14edf71462000319575b5f80fd5b6200031762000311366004620025e5565b62000740565b005b620003176200032a3660046200266e565b620007c4565b6200031762000341366004620026b6565b6200082c565b62000317620008b3565b620003176200036236600462002716565b620009e7565b620003176200037936600462002743565b62000a55565b62000389609d5481565b6040519081526020015b60405180910390f35b62000317620003ad3660046200277d565b62000b85565b620003ca620003c4366004620027d1565b62000cbc565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000393565b6200031762000401366004620027e9565b62000d3f565b6200031762000418366004620027d1565b62000e31565b620003896200042f366004620027d1565b60a06020525f908152604090205481565b620003176200045136600462002807565b62000ea7565b62000389609b5481565b620003ca7f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521381565b6200031762000f6b565b6200031762000f82565b62000317620004ae36600462002848565b62001038565b62000317620004c5366004620027e9565b620010be565b60335473ffffffffffffffffffffffffffffffffffffffff16620003ca565b62000317620004fb36600462002886565b620011b0565b62000317620005123660046200293c565b62001453565b62000522620014e5565b60405162000393919062002982565b620003176200054236600462002807565b620014f8565b6200031762000559366004620027d1565b62001513565b620003897f000000000000000000000000000000000000000000000000000000000000006481565b6200031762000598366004620029c7565b6200156f565b609c54620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b62000389609a5481565b620003ca620005da366004620027d1565b62001657565b62000605620005f1366004620027d1565b5f908152609e602052604090205442111590565b604051901515815260200162000393565b60655473ffffffffffffffffffffffffffffffffffffffff16620003ca565b6200031762000646366004620029fe565b6200166c565b609f54620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b620003176200067e36600462002807565b620016bd565b6200031762000695366004620027e9565b6200170f565b62000389620006ac366004620027d1565b609e6020525f908152604090205481565b620006c7620017c2565b6040805163ffffffff9485168152928416602084015292169181019190915260600162000393565b620003176200070036600462002a46565b62001800565b60a154620003ca9073ffffffffffffffffffffffffffffffffffffffff1681565b6200073162001815565b60405162000393919062002a80565b6200074a620018f9565b620007576097836200197c565b73ffffffffffffffffffffffffffffffffffffffff166364bf8d66826040518263ffffffff1660e01b815260040162000791919062002afb565b5f604051808303815f87803b158015620007a9575f80fd5b505af1158015620007bc573d5f803e3d5ffd5b505050505050565b620007ce620018f9565b73ffffffffffffffffffffffffffffffffffffffff81166200081c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000828828262001989565b5050565b62000836620018f9565b620008436097846200197c565b73ffffffffffffffffffffffffffffffffffffffff1663fc57565f83836040518363ffffffff1660e01b81526004016200087f92919062002ee9565b5f604051808303815f87803b15801562000897575f80fd5b505af1158015620008aa573d5f803e3d5ffd5b50505050505050565b60a25473ffffffffffffffffffffffffffffffffffffffff163381146200090d576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60a1805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000808416821790945560a280549094169093556040519116915f917fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9908390a38173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc60405160405180910390a35050565b620009f1620018f9565b620009fe6097836200197c565b6040517f1cc5d103000000000000000000000000000000000000000000000000000000008152821515600482015273ffffffffffffffffffffffffffffffffffffffff9190911690631cc5d1039060240162000791565b62000a5f62001a44565b5f62000a6f6020830183620027e9565b73ffffffffffffffffffffffffffffffffffffffff160362000abd576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000ad662000ad06020830183620027e9565b62001aa5565b6060810135609d8190555f908152609e60209081526040918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905562000b24918301908301620027e9565b609f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905562000b8262000b7c604083018362002f03565b62001ad8565b50565b62000b8f620018f9565b5f8460405160200162000ba3919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120609d80545f8a815260a08552858120849055609e9094528484208990558784529383207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905586905593509091849183917f4235104f56661fe2e9d2f2a460b42766581bc45ce366c6a30a9f86c8a2b371a79190a3604051829086907f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d4905f90a3827ff99295383247eabb6bee8798669fa768502f8843d3be0e82a0aa81d7b6c4f60c8760405162000cac919062002f40565b60405180910390a2505050505050565b5f62000cca6097836200197c565b73ffffffffffffffffffffffffffffffffffffffff16636e9960c36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000d13573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000d39919062002f54565b92915050565b60a15473ffffffffffffffffffffffffffffffffffffffff16331480159062000d80575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1562000dbb576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b60a2805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9905f90a35050565b62000e3b620018f9565b62000e486097826200197c565b73ffffffffffffffffffffffffffffffffffffffff1663173389456040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562000e8d575f80fd5b505af115801562000ea0573d5f803e3d5ffd5b5050505050565b60a15473ffffffffffffffffffffffffffffffffffffffff16331480159062000ee8575060335473ffffffffffffffffffffffffffffffffffffffff163314155b1562000f23576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b62000f306097836200197c565b73ffffffffffffffffffffffffffffffffffffffff166397c09d34826040518263ffffffff1660e01b81526004016200079191815260200190565b62000f75620018f9565b62000f805f62001aa5565b565b606554339073ffffffffffffffffffffffffffffffffffffffff1681146200102d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e65720000000000000000000000000000000000000000000000606482015260840162000904565b62000b828162001aa5565b62001042620018f9565b6200104f6097846200197c565b6040517f235d9eb50000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff80851660048301528316602482015273ffffffffffffffffffffffffffffffffffffffff919091169063235d9eb5906044016200087f565b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590620010ff575060335473ffffffffffffffffffffffffffffffffffffffff163314155b156200113a576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5a1b0d8808a8dca64c1f7c230dce7a09f7f9a1c26507e190e03dcd382e69018e905f90a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213161462001223576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b5f6200122f8762001657565b73ffffffffffffffffffffffffffffffffffffffff1603620007bc575f6200125a82840184620030fa565b90505f83836040516200126f9291906200331b565b60405180910390209050609b548114620012c457609b546040517f0b08d5be00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440162000904565b606063e4441b9860e01b895f1b7f000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb521373ffffffffffffffffffffffffffffffffffffffff165f1b3073ffffffffffffffffffffffffffffffffffffffff165f1b609d545f1b8a73ffffffffffffffffffffffffffffffffffffffff165f1b609f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165f1b8e73ffffffffffffffffffffffffffffffffffffffff165f1b8e73ffffffffffffffffffffffffffffffffffffffff165f1b609a548c60400151604051602001620013d19b9a999897969594939291906200334e565b60405160208183030381529060405290508083604001819052505f805f1b4685604051620013ff90620025d7565b6200140c92919062003573565b8190604051809103905ff59050801580156200142a573d5f803e3d5ffd5b509050806200143a8b8262001989565b620014468b8262001e83565b5050505050505050505050565b6200145d620018f9565b5f8260405160200162001471919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f86815260a0909252918120829055909250829184917f71b0aeaf8eaa06ed78ccb9a4981da026eea05ca1d818c22dd120446db4c936d491a3505050565b6060620014f3609762002263565b905090565b62001502620018f9565b5f918252609e602052604090912055565b6200151d620018f9565b6200152a6097826200197c565b73ffffffffffffffffffffffffffffffffffffffff166327ae4c166040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562000e8d575f80fd5b60a15473ffffffffffffffffffffffffffffffffffffffff163314801590620015b0575060335473ffffffffffffffffffffffffffffffffffffffff163314155b15620015eb576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240162000904565b620015f86097846200197c565b6040517f4623c91d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283151560248301529190911690634623c91d906044016200087f565b5f6200166560978362002271565b9392505050565b62001676620018f9565b620016836097836200197c565b73ffffffffffffffffffffffffffffffffffffffff1663a9f6d941826040518263ffffffff1660e01b815260040162000791919062002f40565b620016c7620018f9565b620016d46097836200197c565b73ffffffffffffffffffffffffffffffffffffffff1663be6f11cf826040518263ffffffff1660e01b81526004016200079191815260200190565b62001719620018f9565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff000000000000000000000000000000000000000090911681179091556200177d60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f805f620017f5620017d6609d5462002290565b63ffffffff604082901c169167ffffffffffffffff602083901c169190565b925092509250909192565b6200180a620018f9565b62000b828162001ad8565b60605f62001824609762002263565b9050805167ffffffffffffffff81111562001843576200184362002f72565b6040519080825280602002602001820160405280156200186d578160200160208202803683370190505b5081519092505f5b81811015620018f357620018b08382815181106200189757620018976200358d565b602002602001015160976200197c90919063ffffffff16565b848281518110620018c557620018c56200358d565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010162001875565b50505090565b60335473ffffffffffffffffffffffffffffffffffffffff16331462000f80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000904565b5f62001665838362002333565b6200199760978383620023c1565b507f0000000000000000000000000000000000000000000000000000000000000064620019c56097620023ed565b1115620019fe576040517fb615c2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff82169083907f6cb7904ba60de613ccb460be43d4ab7c4fb9ad601052ce4b7e19993955974717905f90a35050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf480546001909155801562000b82576040517fdf3a8fdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606580547fffffffffffffffffffffffff000000000000000000000000000000000000000016905562000b8281620023f9565b5f62001ae86020830183620027e9565b73ffffffffffffffffffffffffffffffffffffffff160362001b36576040517f3a1a858900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013562001b72576040517f7940c83f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62001b856060830160408401620035ba565b67ffffffffffffffff160362001bc7576040517fb4fc683500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081013562001c03576040517f6d4a7df800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001c126020820182620027e9565b609c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905560408051610100810182525f80825260208481013590830152918181019062001c879060608601908601620035ba565b67ffffffffffffffff1681526020015f81526020017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f1b81526020015f801b81526020015f8152602001836060013581525090508060405160200162001d4f91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609a555f62001d986080840184620035d6565b60405160200162001daa919062002f40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602091820120609b81905591507ff693b52e1edb097c83c4406c189a03e96be0e6c7cf7a4544b1986b08f76a17969062001e1790850185620027e9565b602085013562001e2e6060870160408801620035ba565b6040805173ffffffffffffffffffffffffffffffffffffffff9094168452602084019290925267ffffffffffffffff1690820152606080860135908201526080810183905260a00160405180910390a1505050565b5f8260405160240162001e9891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fef0e2ff400000000000000000000000000000000000000000000000000000000179052609d5490915060609081905f62001f29620017d68362002290565b509150505f60405180610200016040528060fe815260200161800773ffffffffffffffffffffffffffffffffffffffff16815260200161800b73ffffffffffffffffffffffffffffffffffffffff16815260200163044aa200815260200161032081526020015f81526020015f81526020015f81526020018363ffffffff1681526020015f815260200160405180608001604052805f81526020015f81526020015f81526020015f81525081526020018781526020015f67ffffffffffffffff81111562001ffb5762001ffb62002f72565b6040519080825280601f01601f19166020018201604052801562002026576020820181803683370190505b5081526020808201889052604080515f808252818401835282850191909152815181815280840183526060948501528151610140810183528581528084018a9052808301829052808501829052608081018290528251808601845282815280850183905280840183905260a08201528251828152808501845260c08201528251828152808501845260e08201526101008101829052610120810189905282518086018452858152609c5473ffffffffffffffffffffffffffffffffffffffff16948101949094528251959650949092918201906200210990869060240162003806565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f08284e57000000000000000000000000000000000000000000000000000000001790529152517fa9f6d94100000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8b169063a9f6d94190620021d690849060040162003926565b5f604051808303815f87803b158015620021ee575f80fd5b505af115801562002201573d5f803e3d5ffd5b50505050858a73ffffffffffffffffffffffffffffffffffffffff167f6cddf65a8ecde9818f721d40492026200e10a08f5057291c5cc77eb7d020d617866040516200224e91906200393a565b60405180910390a35050505050505050505050565b60605f62001665836200246f565b5f8080806200228186866200247c565b909450925050505b9250929050565b5f6bffffffffffffffffffffffff8211156200232f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f3620626974730000000000000000000000000000000000000000000000000000606482015260840162000904565b5090565b5f81815260028301602052604081205480151580620023595750620023598484620024b9565b62001665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640162000904565b5f620023e5848473ffffffffffffffffffffffffffffffffffffffff8516620024c6565b949350505050565b5f62000d3982620024e4565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606062000d3982620024f0565b5f818152600283016020526040812054819080620024ad57620024a08585620024b9565b92505f9150620022899050565b60019250905062002289565b5f620016658383620024fe565b5f8281526002840160205260408120829055620023e5848462002516565b5f62000d398262002523565b60605f62001665836200252d565b5f818152600183016020526040812054151562001665565b5f62001665838362002588565b5f62000d39825490565b6060815f018054806020026020016040519081016040528092919081815260200182805480156200257c57602002820191905f5260205f20905b81548152602001906001019080831162002567575b50505050509050919050565b5f818152600183016020526040812054620025cf57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915562000d39565b505f62000d39565b611574806200394f83390190565b5f8082840360e0811215620025f8575f80fd5b8335925060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820112156200262c575f80fd5b506020830190509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811462000b82575f80fd5b803562002669816200263a565b919050565b5f806040838503121562002680575f80fd5b82359150602083013562002694816200263a565b809150509250929050565b5f60608284031215620026b0575f80fd5b50919050565b5f805f60608486031215620026c9575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115620026ee575f80fd5b620026fc868287016200269f565b9150509250925092565b8035801515811462002669575f80fd5b5f806040838503121562002728575f80fd5b823591506200273a6020840162002706565b90509250929050565b5f6020828403121562002754575f80fd5b813567ffffffffffffffff8111156200276b575f80fd5b82016080818503121562001665575f80fd5b5f805f806080858703121562002791575f80fd5b843567ffffffffffffffff811115620027a8575f80fd5b620027b6878288016200269f565b97602087013597506040870135966060013595509350505050565b5f60208284031215620027e2575f80fd5b5035919050565b5f60208284031215620027fa575f80fd5b813562001665816200263a565b5f806040838503121562002819575f80fd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff8116811462002669575f80fd5b5f805f606084860312156200285b575f80fd5b833592506200286d6020850162002828565b91506200287d6040850162002828565b90509250925092565b5f805f805f8060a087890312156200289c575f80fd5b863595506020870135620028b0816200263a565b94506040870135620028c2816200263a565b93506060870135620028d4816200263a565b9250608087013567ffffffffffffffff80821115620028f1575f80fd5b818901915089601f83011262002905575f80fd5b81358181111562002914575f80fd5b8a602082850101111562002926575f80fd5b6020830194508093505050509295509295509295565b5f80604083850312156200294e575f80fd5b823567ffffffffffffffff81111562002965575f80fd5b62002973858286016200269f565b95602094909401359450505050565b602080825282518282018190525f9190848201906040850190845b81811015620029bb578351835292840192918401916001016200299d565b50909695505050505050565b5f805f60608486031215620029da575f80fd5b833592506020840135620029ee816200263a565b91506200287d6040850162002706565b5f806040838503121562002a10575f80fd5b82359150602083013567ffffffffffffffff81111562002a2e575f80fd5b62002a3c858286016200269f565b9150509250929050565b5f6020828403121562002a57575f80fd5b813567ffffffffffffffff81111562002a6e575f80fd5b820160a0818503121562001665575f80fd5b602080825282518282018190525f9190848201906040850190845b81811015620029bb57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010162002a9b565b803563ffffffff8116811462002669575f80fd5b803567ffffffffffffffff8116811462002669575f80fd5b60c0810182356002811062002b0e575f80fd5b825262002b1e6020840162002acf565b63ffffffff80821660208501528062002b3a6040870162002acf565b1660408501528062002b4f6060870162002acf565b1660608501528062002b646080870162002acf565b166080850152505067ffffffffffffffff62002b8360a0850162002ae3565b1660a083015292915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262002bc3575f80fd5b830160208101925035905067ffffffffffffffff81111562002be3575f80fd5b8060051b360382131562002289575f80fd5b80356003811062002669575f80fd5b6003811062002c3a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811462002669575f80fd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811262002ca2575f80fd5b830160208101925035905067ffffffffffffffff81111562002cc2575f80fd5b80360382131562002289575f80fd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f606080840162002d2a848562002b8f565b6060875291829052608091828701600582901b88018401835f5b8481101562002e86577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808b840301845281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8187360301811262002da6575f80fd5b8601838801813562002db8816200263a565b73ffffffffffffffffffffffffffffffffffffffff168552602062002ddf83820162002bf5565b62002ded8288018262002c04565b50604062002dfd81850162002706565b15159087015262002e11838c018462002b8f565b878d018c9052928390529192505f60a087015b8482101562002e6f577fffffffff0000000000000000000000000000000000000000000000000000000062002e598562002c3e565b1681529282019260019190910190820162002e24565b978201979650509390930192505060010162002d44565b505062002e96602089016200265c565b73ffffffffffffffffffffffffffffffffffffffff811660208b0152955062002ec3604089018962002c6e565b9650945088810360408a015262002edc81878762002cd1565b9998505050505050505050565b828152604060208201525f620023e5604083018462002d18565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811262002f36575f80fd5b9190910192915050565b602081525f62001665602083018462002d18565b5f6020828403121562002f65575f80fd5b815162001665816200263a565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff8111828210171562002fc55762002fc562002f72565b60405290565b6040516080810167ffffffffffffffff8111828210171562002fc55762002fc562002f72565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200303b576200303b62002f72565b604052919050565b5f67ffffffffffffffff8211156200305f576200305f62002f72565b5060051b60200190565b5f82601f83011262003079575f80fd5b813567ffffffffffffffff81111562003096576200309662002f72565b620030c960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160162002ff1565b818152846020838601011115620030de575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156200310b575f80fd5b67ffffffffffffffff808335111562003122575f80fd5b823583016060818603121562003136575f80fd5b6200314062002f9f565b82823511156200314e575f80fd5b8135820186601f82011262003161575f80fd5b6200317762003171823562003043565b62002ff1565b81358082526020808301929160051b8401018981111562003196575f80fd5b602084015b81811015620032d0578781351115620031b2575f80fd5b8035850160807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828e03011215620031e8575f80fd5b620031f262002fcb565b6200320160208301356200263a565b60208201358152620032166040830162002bf5565b6020820152620032296060830162002706565b604082015289608083013511156200323f575f80fd5b6080820135820191508c603f83011262003257575f80fd5b60208201356200326b620031718262003043565b81815260059190911b83016040019060208101908f8311156200328c575f80fd5b6040850194505b82851015620032b957620032a78562002c3e565b82526020948501949091019062003293565b60608401525050855250602093840193016200319b565b5050835250620032e59050602083016200265c565b60208201528260408301351115620032fb575f80fd5b6200330d866040840135840162003069565b604082015295945050505050565b818382375f9101908152919050565b5f5b83811015620033465781810151838201526020016200332c565b50505f910152565b7fffffffff000000000000000000000000000000000000000000000000000000008c1681528a60048201528960248201528860448201528760648201528660848201528560a48201528460c48201528360e4820152826101048201525f6101248351620033c281838601602088016200332a565b929092019091019c9b505050505050505050505050565b5f8151808452620033f28160208601602086016200332a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b5f60608084018351606086528181518084526080935060808801915060808160051b890101602080850194505f5b8381101562003535577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808b8403018552855187840173ffffffffffffffffffffffffffffffffffffffff825116855283820151620034b38587018262002c04565b50604082810151151590860152908901518985018990528051918290528301905f9060a08601905b808310156200351f5783517fffffffff00000000000000000000000000000000000000000000000000000000168252928501926001929092019190850190620034db565b5097840197968401969450505060010162003452565b508881015173ffffffffffffffffffffffffffffffffffffffff81168b8301529650506040880151955088810360408a015262002edc8187620033d9565b828152604060208201525f620023e5604083018462003424565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215620035cb575f80fd5b620016658262002ae3565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811262002f36575f80fd5b805f5b60048110156200362d5781518452602093840193909101906001016200360c565b50505050565b5f815180845260208085019450602084015f5b83811015620036645781518752958201959082019060010162003646565b509495945050505050565b5f610260825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151620036ea8287018262003609565b50506101608301516101c082818701526200370883870183620033d9565b925061018085015191506101e086840381880152620037288484620033d9565b93506101a0860151925086840361020088015262003747848462003633565b9350818601519250868403610220880152620037648484620033d9565b93508086015192505050848203610240860152620037838282620033d9565b95945050505050565b5f8282518085526020808601955060208260051b840101602086015f5b84811015620037f9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952620037e6838351620033d9565b98840198925090830190600101620037a9565b5090979650505050505050565b602081525f8251610180806020850152620038266101a08501836200366f565b915060208501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030160408701526200386484836200378c565b9350604087015160608701526060870151608087015260808701519150620038a460a087018373ffffffffffffffffffffffffffffffffffffffff169052565b60a0870151805160c0880152602081015160e08801526040810151610100880152915060c08701519150610120818786030181880152620038e68584620033d9565b945060e088015192508187860301610140880152620039068584620033d9565b610100890151610160890152970151929095019190915250929392505050565b602081525f62001665602083018462003424565b602081525f6200166560208301846200366f56fe608060405234801562000010575f80fd5b506040516200157438038062001574833981016040819052620000339162000f1c565b4682146200006d5760405162461bcd60e51b8152602060048201526002602482015261383960f11b60448201526064015b60405180910390fd5b620000788162000080565b5050620012ae565b80516020820151604083015182515f5b8181101562000202575f858281518110620000af57620000af620010c0565b60200260200101516020015190505f868381518110620000d357620000d3620010c0565b60200260200101515f015190505f878481518110620000f657620000f6620010c0565b60200260200101516040015190505f8885815181106200011a576200011a620010c0565b602002602001015160600151905080515f036200014a57604051630a6fef7160e41b815260040160405180910390fd5b5f846002811115620001605762000160620010d4565b0362000179576200017383828462000253565b620001e5565b6001846002811115620001905762000190620010d4565b03620001a3576200017383828462000389565b6002846002811115620001ba57620001ba620010d4565b03620001cc57620001738382620004a5565b60405163e52478c760e01b815260040160405180910390fd5b50505050620001fa81620005ae60201b60201c565b905062000090565b506200020f8383620005b4565b7f87b829356b3403d36217eff1f66ee48eacd0a69015153aba4f0de29fe5340c30848484604051620002449392919062001115565b60405180910390a15050505050565b5f80516020620015548339815191526001600160a01b0384163b5f0362000299576040516310d76a3760e31b81526001600160a01b038516600482015260240162000064565b620002a48462000707565b82515f5b8181101562000381575f858281518110620002c757620002c7620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff1615159181019190915290925090156200036957805160405163158947f360e31b81526001600160e01b0319841660048201526001600160a01b03909116602482015260440162000064565b62000376888388620007b1565b5050600101620002a8565b505050505050565b5f80516020620015548339815191526001600160a01b0384163b5f03620003cf576040516310d76a3760e31b81526001600160a01b038516600482015260240162000064565b82515f5b8181101562000381575f858281518110620003f257620003f2620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250906200047457604051630d600dc360e21b815260040160405180910390fd5b80516200048290836200095f565b6200048d8862000707565b6200049a888388620007b1565b5050600101620003d3565b5f80516020620015548339815191526001600160a01b03831615620004e95760405163333e8bef60e11b81526001600160a01b038416600482015260240162000064565b81515f5b81811015620005a7575f8482815181106200050c576200050c620010c0565b6020908102919091018101516001600160e01b031981165f908152868352604090819020815160608101835290546001600160a01b038116808352600160a01b820461ffff1695830195909552600160b01b900460ff16151591810191909152909250906200058e576040516328b52c5b60e21b815260040160405180910390fd5b80516200059c90836200095f565b5050600101620004ed565b5050505050565b60010190565b6001600160a01b038216620005e857805115620005e45760405163c21b1ab760e01b815260040160405180910390fd5b5050565b5f80836001600160a01b03168360405162000604919062001224565b5f60405180830381855af49150503d805f81146200063e576040519150601f19603f3d011682016040523d82523d5f602084013e62000643565b606091505b5091509150816200067e5760048151101562000676578060405163f7a01e4d60e01b815260040162000064919062001241565b805160208201fd5b8051602014620006a5578060405163f7a01e4d60e01b815260040162000064919062001241565b7f33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a25f1b81806020019051810190620006de91906200125c565b1462000701578060405163f7a01e4d60e01b815260040162000064919062001241565b50505050565b6001600160a01b0381165f9081525f805160206200153483398151915260205260408120545f805160206200155483398151915291819003620007ac576002820154620007549062000b58565b6001600160a01b0384165f81815260018581016020908152604083208201805461ffff191661ffff96909616959095179094556002860180549182018155825292902090910180546001600160a01b03191690911790555b505050565b6001600160a01b0383165f9081525f805160206200153483398151915260205260408120545f80516020620015548339815191529190620007f29062000b58565b905061ffff81161562000896576001600160a01b0385165f9081526001830160205260408120805482906200082b576200082b620010c0565b5f918252602080832060088304015460079092166004026101000a90910460e01b6001600160e01b03198116835290859052604090912054909150600160b01b900460ff16151584151514620008945760405163d3b6535b60e01b815260040160405180910390fd5b505b604080516060810182526001600160a01b0396871680825261ffff93841660208084019182529615158385019081526001600160e01b031989165f90815287895285812094518554935192519b166001600160b01b031990931692909217600160a01b91909616029490941760ff60b01b1916600160b01b981515989098029790971790559481526001918201835293842080549182018155845292206008830401805463ffffffff60079094166004026101000a938402191660e09290921c92909202179055565b6001600160e01b031981165f9081525f805160206200155483398151915260208181526040808420546001600160a01b03871685525f80516020620015348339815191529092528320549192600160a01b90910461ffff1691620009c69060019062001274565b905080821462000ac9576001600160a01b0385165f9081526001840160205260408120805483908110620009fe57620009fe620010c0565b5f91825260208083206008830401546001600160a01b038a168452600188019091526040909220805460079092166004026101000a90920460e01b92508291908590811062000a515762000a51620010c0565b905f5260205f2090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555062000a908362000b5860201b60201c565b6001600160e01b03199091165f908152602085905260409020805461ffff92909216600160a01b0261ffff60a01b199092169190911790555b6001600160a01b0385165f908152600184016020526040902080548062000af45762000af46200129a565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319861682528490526040812080546001600160b81b0319169055819003620005a757620005a78562000bc0565b5f61ffff82111562000bbc5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b606482015260840162000064565b5090565b6001600160a01b0381165f9081525f8051602062001534833981519152602052604081206001908101547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131d545f80516020620015548339815191529361ffff9092169262000c2e9162001274565b905080821462000ce9575f83600201828154811062000c515762000c51620010c0565b5f918252602090912001546002850180546001600160a01b03909216925082918590811062000c845762000c84620010c0565b5f91825260209091200180546001600160a01b0319166001600160a01b039290921691909117905562000cb78362000b58565b6001600160a01b03919091165f9081526001858101602052604090912001805461ffff191661ffff9092169190911790555b8260020180548062000cff5762000cff6200129a565b5f8281526020902081015f1990810180546001600160a01b031916905501905550505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171562000d5e5762000d5e62000d25565b60405290565b604051608081016001600160401b038111828210171562000d5e5762000d5e62000d25565b604051601f8201601f191681016001600160401b038111828210171562000db45762000db462000d25565b604052919050565b5f6001600160401b0382111562000dd75762000dd762000d25565b5060051b60200190565b80516001600160a01b038116811462000df8575f80fd5b919050565b5f82601f83011262000e0d575f80fd5b8151602062000e2662000e208362000dbc565b62000d89565b8083825260208201915060208460051b87010193508684111562000e48575f80fd5b602086015b8481101562000e7c5780516001600160e01b03198116811462000e6e575f80fd5b835291830191830162000e4d565b509695505050505050565b5f5b8381101562000ea357818101518382015260200162000e89565b50505f910152565b5f82601f83011262000ebb575f80fd5b81516001600160401b0381111562000ed75762000ed762000d25565b62000eec601f8201601f191660200162000d89565b81815284602083860101111562000f01575f80fd5b62000f1482602083016020870162000e87565b949350505050565b5f806040838503121562000f2e575f80fd5b825160208401519092506001600160401b038082111562000f4d575f80fd5b908401906060828703121562000f61575f80fd5b62000f6b62000d39565b82518281111562000f7a575f80fd5b8301601f8101881362000f8b575f80fd5b805162000f9c62000e208262000dbc565b8082825260208201915060208360051b85010192508a83111562000fbe575f80fd5b602084015b83811015620010735780518781111562000fdb575f80fd5b85016080818e03601f1901121562000ff1575f80fd5b62000ffb62000d64565b620010096020830162000de1565b81526040820151600381106200101d575f80fd5b60208201526060820151801515811462001035575f80fd5b60408201526080820151898111156200104c575f80fd5b6200105d8f60208386010162000dfd565b6060830152508452506020928301920162000fc3565b50845250620010889150506020840162000de1565b60208201526040830151828111156200109f575f80fd5b620010ad8882860162000eab565b6040830152508093505050509250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f81518084526200110181602086016020860162000e87565b601f01601f19169290920160200192915050565b5f6060808301606084528087518083526080925060808601915060808160051b8701016020808b015f5b84811015620011f257898403607f19018652815180516001600160a01b031685528381015188860190600381106200118557634e487b7160e01b5f52602160045260245ffd5b86860152604082810151151590870152908901518986018990528051918290528401905f9060a08701905b80831015620011dc5783516001600160e01b0319168252928601926001929092019190860190620011b0565b509785019795505050908201906001016200113f565b50506001600160a01b038a16908801528681036040880152620012168189620010e8565b9a9950505050505050505050565b5f82516200123781846020870162000e87565b9190910192915050565b602081525f620012556020830184620010e8565b9392505050565b5f602082840312156200126d575f80fd5b5051919050565b818103818111156200129457634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603160045260245ffd5b61027880620012bc5f395ff3fe60806040527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b600436101580610033575036155b61009e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f557400000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b5f80357fffffffff0000000000000000000000000000000000000000000000000000000016815260208281526040918290208251606081018452905473ffffffffffffffffffffffffffffffffffffffff811680835274010000000000000000000000000000000000000000820461ffff1693830193909352760100000000000000000000000000000000000000000000900460ff16151592810192909252806101a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f46000000000000000000000000000000000000000000000000000000000000006044820152606401610095565b600383015460ff1615806101ba57508160400151155b610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f71310000000000000000000000000000000000000000000000000000000000006044820152606401610095565b604051365f82375f803683855af43d805f843e81801561023e578184f35b8184fdfea2646970667358221220008b4899e63d1da58f6c056a941f85d587091ca7906cccff6c0a8e1a3ea76de164736f6c63430008180033c8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131cc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ba2646970667358221220790b6e55112efe113fe74ec195f76da5657d9108fb54b1e6f9e757dc45a9f66a64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb52130000000000000000000000000000000000000000000000000000000000000064
-----Decoded View---------------
Arg [0] : _bridgehub (address): 0x303a465B659cBB0ab36eE643eA362c509EEb5213
Arg [1] : _maxNumberOfHyperchains (uint256): 100
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000303a465b659cbb0ab36ee643ea362c509eeb5213
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000064
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.