Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PolygonZkEVM
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "./interfaces/IVerifierRollup.sol"; import "./interfaces/IPolygonZkEVMGlobalExitRoot.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./interfaces/IPolygonZkEVMBridge.sol"; import "./lib/EmergencyManager.sol"; import "./interfaces/IPolygonZkEVMErrors.sol"; /** * Contract responsible for managing the states and the updates of L2 network. * There will be a trusted sequencer, which is able to send transactions. * Any user can force some transaction and the sequencer will have a timeout to add them in the queue. * The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. * The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. * To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. */ contract PolygonZkEVM is OwnableUpgradeable, EmergencyManager, IPolygonZkEVMErrors { using SafeERC20Upgradeable for IERC20Upgradeable; /** * @notice Struct which will be used to call sequenceBatches * @param transactions L2 ethereum transactions EIP-155 or pre-EIP-155 with signature: * EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data, chainid, 0, 0,) || v || r || s * pre-EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data) || v || r || s * @param globalExitRoot Global exit root of the batch * @param timestamp Sequenced timestamp of the batch * @param minForcedTimestamp Minimum timestamp of the force batch data, empty when non forced batch */ struct BatchData { bytes transactions; bytes32 globalExitRoot; uint64 timestamp; uint64 minForcedTimestamp; } /** * @notice Struct which will be used to call sequenceForceBatches * @param transactions L2 ethereum transactions EIP-155 or pre-EIP-155 with signature: * EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data, chainid, 0, 0,) || v || r || s * pre-EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data) || v || r || s * @param globalExitRoot Global exit root of the batch * @param minForcedTimestamp Indicates the minimum sequenced timestamp of the batch */ struct ForcedBatchData { bytes transactions; bytes32 globalExitRoot; uint64 minForcedTimestamp; } /** * @notice Struct which will be stored for every batch sequence * @param accInputHash Hash chain that contains all the information to process a batch: * keccak256(bytes32 oldAccInputHash, keccak256(bytes transactions), bytes32 globalExitRoot, uint64 timestamp, address seqAddress) * @param sequencedTimestamp Sequenced timestamp * @param previousLastBatchSequenced Previous last batch sequenced before the current one, this is used to properly calculate the fees */ struct SequencedBatchData { bytes32 accInputHash; uint64 sequencedTimestamp; uint64 previousLastBatchSequenced; } /** * @notice Struct to store the pending states * Pending state will be an intermediary state, that after a timeout can be consolidated, which means that will be added * to the state root mapping, and the global exit root will be updated * This is a protection mechanism against soundness attacks, that will be turned off in the future * @param timestamp Timestamp where the pending state is added to the queue * @param lastVerifiedBatch Last batch verified batch of this pending state * @param exitRoot Pending exit root * @param stateRoot Pending state root */ struct PendingState { uint64 timestamp; uint64 lastVerifiedBatch; bytes32 exitRoot; bytes32 stateRoot; } /** * @notice Struct to call initialize, this saves gas because pack the parameters and avoid stack too deep errors. * @param admin Admin address * @param trustedSequencer Trusted sequencer address * @param pendingStateTimeout Pending state timeout * @param trustedAggregator Trusted aggregator * @param trustedAggregatorTimeout Trusted aggregator timeout */ struct InitializePackedParameters { address admin; address trustedSequencer; uint64 pendingStateTimeout; address trustedAggregator; uint64 trustedAggregatorTimeout; } // Modulus zkSNARK uint256 internal constant _RFIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Max transactions bytes that can be added in a single batch // Max keccaks circuit = (2**23 / 155286) * 44 = 2376 // Bytes per keccak = 136 // Minimum Static keccaks batch = 2 // Max bytes allowed = (2376 - 2) * 136 = 322864 bytes - 1 byte padding // Rounded to 300000 bytes // In order to process the transaction, the data is approximately hashed twice for ecrecover: // 300000 bytes / 2 = 150000 bytes // Since geth pool currently only accepts at maximum 128kb transactions: // https://github.com/ethereum/go-ethereum/blob/master/core/txpool/txpool.go#L54 // We will limit this length to be compliant with the geth restrictions since our node will use it // We let 8kb as a sanity margin uint256 internal constant _MAX_TRANSACTIONS_BYTE_LENGTH = 120000; // Max force batch transaction length // This is used to avoid huge calldata attacks, where the attacker call force batches from another contract uint256 internal constant _MAX_FORCE_BATCH_BYTE_LENGTH = 5000; // If a sequenced batch exceeds this timeout without being verified, the contract enters in emergency mode uint64 internal constant _HALT_AGGREGATION_TIMEOUT = 1 weeks; // Maximum batches that can be verified in one call. It depends on our current metrics // This should be a protection against someone that tries to generate huge chunk of invalid batches, and we can't prove otherwise before the pending timeout expires uint64 internal constant _MAX_VERIFY_BATCHES = 1000; // Max batch multiplier per verification uint256 internal constant _MAX_BATCH_MULTIPLIER = 12; // Max batch fee value uint256 internal constant _MAX_BATCH_FEE = 1000 ether; // Min value batch fee uint256 internal constant _MIN_BATCH_FEE = 1 gwei; // Goldilocks prime field uint256 internal constant _GOLDILOCKS_PRIME_FIELD = 0xFFFFFFFF00000001; // 2 ** 64 - 2 ** 32 + 1 // Max uint64 uint256 internal constant _MAX_UINT_64 = type(uint64).max; // 0xFFFFFFFFFFFFFFFF // MATIC token address IERC20Upgradeable public immutable matic; // Rollup verifier interface IVerifierRollup public immutable rollupVerifier; // Global Exit Root interface IPolygonZkEVMGlobalExitRoot public immutable globalExitRootManager; // PolygonZkEVM Bridge Address IPolygonZkEVMBridge public immutable bridgeAddress; // L2 chain identifier uint64 public immutable chainID; // L2 chain identifier uint64 public immutable forkID; // Time target of the verification of a batch // Adaptatly the batchFee will be updated to achieve this target uint64 public verifyBatchTimeTarget; // Batch fee multiplier with 3 decimals that goes from 1000 - 1023 uint16 public multiplierBatchFee; // Trusted sequencer address address public trustedSequencer; // Current matic fee per batch sequenced uint256 public batchFee; // Queue of forced batches with their associated data // ForceBatchNum --> hashedForcedBatchData // hashedForcedBatchData: hash containing the necessary information to force a batch: // keccak256(keccak256(bytes transactions), bytes32 globalExitRoot, unint64 minForcedTimestamp) mapping(uint64 => bytes32) public forcedBatches; // Queue of batches that defines the virtual state // SequenceBatchNum --> SequencedBatchData mapping(uint64 => SequencedBatchData) public sequencedBatches; // Last sequenced timestamp uint64 public lastTimestamp; // Last batch sent by the sequencers uint64 public lastBatchSequenced; // Last forced batch included in the sequence uint64 public lastForceBatchSequenced; // Last forced batch uint64 public lastForceBatch; // Last batch verified by the aggregators uint64 public lastVerifiedBatch; // Trusted aggregator address address public trustedAggregator; // State root mapping // BatchNum --> state root mapping(uint64 => bytes32) public batchNumToStateRoot; // Trusted sequencer URL string public trustedSequencerURL; // L2 network name string public networkName; // Pending state mapping // pendingStateNumber --> PendingState mapping(uint256 => PendingState) public pendingStateTransitions; // Last pending state uint64 public lastPendingState; // Last pending state consolidated uint64 public lastPendingStateConsolidated; // Once a pending state exceeds this timeout it can be consolidated uint64 public pendingStateTimeout; // Trusted aggregator timeout, if a sequence is not verified in this time frame, // everyone can verify that sequence uint64 public trustedAggregatorTimeout; // Address that will be able to adjust contract parameters or stop the emergency state address public admin; // This account will be able to accept the admin role address public pendingAdmin; // Force batch timeout uint64 public forceBatchTimeout; // Indicates if forced batches are disallowed bool public isForcedBatchDisallowed; /** * @dev Emitted when the trusted sequencer sends a new batch of transactions */ event SequenceBatches(uint64 indexed numBatch); /** * @dev Emitted when a batch is forced */ event ForceBatch( uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions ); /** * @dev Emitted when forced batches are sequenced by not the trusted sequencer */ event SequenceForceBatches(uint64 indexed numBatch); /** * @dev Emitted when a aggregator verifies batches */ event VerifyBatches( uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator ); /** * @dev Emitted when the trusted aggregator verifies batches */ event VerifyBatchesTrustedAggregator( uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator ); /** * @dev Emitted when pending state is consolidated */ event ConsolidatePendingState( uint64 indexed numBatch, bytes32 stateRoot, uint64 indexed pendingStateNum ); /** * @dev Emitted when the admin updates the trusted sequencer address */ event SetTrustedSequencer(address newTrustedSequencer); /** * @dev Emitted when the admin updates the sequencer URL */ event SetTrustedSequencerURL(string newTrustedSequencerURL); /** * @dev Emitted when the admin updates the trusted aggregator timeout */ event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout); /** * @dev Emitted when the admin updates the pending state timeout */ event SetPendingStateTimeout(uint64 newPendingStateTimeout); /** * @dev Emitted when the admin updates the trusted aggregator address */ event SetTrustedAggregator(address newTrustedAggregator); /** * @dev Emitted when the admin updates the multiplier batch fee */ event SetMultiplierBatchFee(uint16 newMultiplierBatchFee); /** * @dev Emitted when the admin updates the verify batch timeout */ event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget); /** * @dev Emitted when the admin update the force batch timeout */ event SetForceBatchTimeout(uint64 newforceBatchTimeout); /** * @dev Emitted when activate force batches */ event ActivateForceBatches(); /** * @dev Emitted when the admin starts the two-step transfer role setting a new pending admin */ event TransferAdminRole(address newPendingAdmin); /** * @dev Emitted when the pending admin accepts the admin role */ event AcceptAdminRole(address newAdmin); /** * @dev Emitted when is proved a different state given the same batches */ event ProveNonDeterministicPendingState( bytes32 storedStateRoot, bytes32 provedStateRoot ); /** * @dev Emitted when the trusted aggregator overrides pending state */ event OverridePendingState( uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator ); /** * @dev Emitted everytime the forkID is updated, this includes the first initialization of the contract * This event is intended to be emitted for every upgrade of the contract with relevant changes for the nodes */ event UpdateZkEVMVersion(uint64 numBatch, uint64 forkID, string version); /** * @param _globalExitRootManager Global exit root manager address * @param _matic MATIC token address * @param _rollupVerifier Rollup verifier address * @param _bridgeAddress Bridge address * @param _chainID L2 chainID * @param _forkID Fork Id */ constructor( IPolygonZkEVMGlobalExitRoot _globalExitRootManager, IERC20Upgradeable _matic, IVerifierRollup _rollupVerifier, IPolygonZkEVMBridge _bridgeAddress, uint64 _chainID, uint64 _forkID ) { globalExitRootManager = _globalExitRootManager; matic = _matic; rollupVerifier = _rollupVerifier; bridgeAddress = _bridgeAddress; chainID = _chainID; forkID = _forkID; } /** * @param initializePackedParameters Struct to save gas and avoid stack too deep errors * @param genesisRoot Rollup genesis root * @param _trustedSequencerURL Trusted sequencer URL * @param _networkName L2 network name */ function initialize( InitializePackedParameters calldata initializePackedParameters, bytes32 genesisRoot, string memory _trustedSequencerURL, string memory _networkName, string calldata _version ) external initializer { admin = initializePackedParameters.admin; trustedSequencer = initializePackedParameters.trustedSequencer; trustedAggregator = initializePackedParameters.trustedAggregator; batchNumToStateRoot[0] = genesisRoot; trustedSequencerURL = _trustedSequencerURL; networkName = _networkName; // Check initialize parameters if ( initializePackedParameters.pendingStateTimeout > _HALT_AGGREGATION_TIMEOUT ) { revert PendingStateTimeoutExceedHaltAggregationTimeout(); } pendingStateTimeout = initializePackedParameters.pendingStateTimeout; if ( initializePackedParameters.trustedAggregatorTimeout > _HALT_AGGREGATION_TIMEOUT ) { revert TrustedAggregatorTimeoutExceedHaltAggregationTimeout(); } trustedAggregatorTimeout = initializePackedParameters .trustedAggregatorTimeout; // Constant deployment variables batchFee = 0.1 ether; // 0.1 Matic verifyBatchTimeTarget = 30 minutes; multiplierBatchFee = 1002; forceBatchTimeout = 5 days; isForcedBatchDisallowed = true; // Initialize OZ contracts __Ownable_init_unchained(); // emit version event emit UpdateZkEVMVersion(0, forkID, _version); } modifier onlyAdmin() { if (admin != msg.sender) { revert OnlyAdmin(); } _; } modifier onlyTrustedSequencer() { if (trustedSequencer != msg.sender) { revert OnlyTrustedSequencer(); } _; } modifier onlyTrustedAggregator() { if (trustedAggregator != msg.sender) { revert OnlyTrustedAggregator(); } _; } modifier isForceBatchAllowed() { if (isForcedBatchDisallowed) { revert ForceBatchNotAllowed(); } _; } ///////////////////////////////////// // Sequence/Verify batches functions //////////////////////////////////// /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence * @param l2Coinbase Address that will receive the fees from L2 */ function sequenceBatches( BatchData[] calldata batches, address l2Coinbase ) external ifNotEmergencyState onlyTrustedSequencer { uint256 batchesNum = batches.length; if (batchesNum == 0) { revert SequenceZeroBatches(); } if (batchesNum > _MAX_VERIFY_BATCHES) { revert ExceedMaxVerifyBatches(); } // Store storage variables in memory, to save gas, because will be overrided multiple times uint64 currentTimestamp = lastTimestamp; uint64 currentBatchSequenced = lastBatchSequenced; uint64 currentLastForceBatchSequenced = lastForceBatchSequenced; bytes32 currentAccInputHash = sequencedBatches[currentBatchSequenced] .accInputHash; // Store in a temporal variable, for avoid access again the storage slot uint64 initLastForceBatchSequenced = currentLastForceBatchSequenced; for (uint256 i = 0; i < batchesNum; i++) { // Load current sequence BatchData memory currentBatch = batches[i]; // Store the current transactions hash since can be used more than once for gas saving bytes32 currentTransactionsHash = keccak256( currentBatch.transactions ); // Check if it's a forced batch if (currentBatch.minForcedTimestamp > 0) { currentLastForceBatchSequenced++; // Check forced data matches bytes32 hashedForcedBatchData = keccak256( abi.encodePacked( currentTransactionsHash, currentBatch.globalExitRoot, currentBatch.minForcedTimestamp ) ); if ( hashedForcedBatchData != forcedBatches[currentLastForceBatchSequenced] ) { revert ForcedDataDoesNotMatch(); } // Delete forceBatch data since won't be used anymore delete forcedBatches[currentLastForceBatchSequenced]; // Check timestamp is bigger than min timestamp if (currentBatch.timestamp < currentBatch.minForcedTimestamp) { revert SequencedTimestampBelowForcedTimestamp(); } } else { // Check global exit root exists with proper batch length. These checks are already done in the forceBatches call // Note that the sequencer can skip setting a global exit root putting zeros if ( currentBatch.globalExitRoot != bytes32(0) && globalExitRootManager.globalExitRootMap( currentBatch.globalExitRoot ) == 0 ) { revert GlobalExitRootNotExist(); } if ( currentBatch.transactions.length > _MAX_TRANSACTIONS_BYTE_LENGTH ) { revert TransactionsLengthAboveMax(); } } // Check Batch timestamps are correct if ( currentBatch.timestamp < currentTimestamp || currentBatch.timestamp > block.timestamp ) { revert SequencedTimestampInvalid(); } // Calculate next accumulated input hash currentAccInputHash = keccak256( abi.encodePacked( currentAccInputHash, currentTransactionsHash, currentBatch.globalExitRoot, currentBatch.timestamp, l2Coinbase ) ); // Update timestamp currentTimestamp = currentBatch.timestamp; } // Update currentBatchSequenced currentBatchSequenced += uint64(batchesNum); // Sanity check, should be unreachable if (currentLastForceBatchSequenced > lastForceBatch) { revert ForceBatchesOverflow(); } uint256 nonForcedBatchesSequenced = batchesNum - (currentLastForceBatchSequenced - initLastForceBatchSequenced); // Update sequencedBatches mapping sequencedBatches[currentBatchSequenced] = SequencedBatchData({ accInputHash: currentAccInputHash, sequencedTimestamp: uint64(block.timestamp), previousLastBatchSequenced: lastBatchSequenced }); // Store back the storage variables lastTimestamp = currentTimestamp; lastBatchSequenced = currentBatchSequenced; if (currentLastForceBatchSequenced != initLastForceBatchSequenced) lastForceBatchSequenced = currentLastForceBatchSequenced; // Pay collateral for every non-forced batch submitted matic.safeTransferFrom( msg.sender, address(this), batchFee * nonForcedBatchesSequenced ); // Consolidate pending state if possible _tryConsolidatePendingState(); // Update global exit root if there are new deposits bridgeAddress.updateGlobalExitRoot(); emit SequenceBatches(currentBatchSequenced); } /** * @notice Allows an aggregator to verify multiple batches * @param pendingStateNum Init pending state, 0 if consolidated state is used * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function verifyBatches( uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) external ifNotEmergencyState { // Check if the trusted aggregator timeout expired, // Note that the sequencedBatches struct must exists for this finalNewBatch, if not newAccInputHash will be 0 if ( sequencedBatches[finalNewBatch].sequencedTimestamp + trustedAggregatorTimeout > block.timestamp ) { revert TrustedAggregatorTimeoutNotExpired(); } if (finalNewBatch - initNumBatch > _MAX_VERIFY_BATCHES) { revert ExceedMaxVerifyBatches(); } _verifyAndRewardBatches( pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof ); // Update batch fees _updateBatchFee(finalNewBatch); if (pendingStateTimeout == 0) { // Consolidate state lastVerifiedBatch = finalNewBatch; batchNumToStateRoot[finalNewBatch] = newStateRoot; // Clean pending state if any if (lastPendingState > 0) { lastPendingState = 0; lastPendingStateConsolidated = 0; } // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(newLocalExitRoot); } else { // Consolidate pending state if possible _tryConsolidatePendingState(); // Update pending state lastPendingState++; pendingStateTransitions[lastPendingState] = PendingState({ timestamp: uint64(block.timestamp), lastVerifiedBatch: finalNewBatch, exitRoot: newLocalExitRoot, stateRoot: newStateRoot }); } emit VerifyBatches(finalNewBatch, newStateRoot, msg.sender); } /** * @notice Allows an aggregator to verify multiple batches * @param pendingStateNum Init pending state, 0 if consolidated state is used * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function verifyBatchesTrustedAggregator( uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) external onlyTrustedAggregator { _verifyAndRewardBatches( pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof ); // Consolidate state lastVerifiedBatch = finalNewBatch; batchNumToStateRoot[finalNewBatch] = newStateRoot; // Clean pending state if any if (lastPendingState > 0) { lastPendingState = 0; lastPendingStateConsolidated = 0; } // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(newLocalExitRoot); emit VerifyBatchesTrustedAggregator( finalNewBatch, newStateRoot, msg.sender ); } /** * @notice Verify and reward batches internal function * @param pendingStateNum Init pending state, 0 if consolidated state is used * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function _verifyAndRewardBatches( uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) internal { bytes32 oldStateRoot; uint64 currentLastVerifiedBatch = getLastVerifiedBatch(); // Use pending state if specified, otherwise use consolidated state if (pendingStateNum != 0) { // Check that pending state exist // Already consolidated pending states can be used aswell if (pendingStateNum > lastPendingState) { revert PendingStateDoesNotExist(); } // Check choosen pending state PendingState storage currentPendingState = pendingStateTransitions[ pendingStateNum ]; // Get oldStateRoot from pending batch oldStateRoot = currentPendingState.stateRoot; // Check initNumBatch matches the pending state if (initNumBatch != currentPendingState.lastVerifiedBatch) { revert InitNumBatchDoesNotMatchPendingState(); } } else { // Use consolidated state oldStateRoot = batchNumToStateRoot[initNumBatch]; if (oldStateRoot == bytes32(0)) { revert OldStateRootDoesNotExist(); } // Check initNumBatch is inside the range, sanity check if (initNumBatch > currentLastVerifiedBatch) { revert InitNumBatchAboveLastVerifiedBatch(); } } // Check final batch if (finalNewBatch <= currentLastVerifiedBatch) { revert FinalNumBatchBelowLastVerifiedBatch(); } // Get snark bytes bytes memory snarkHashBytes = getInputSnarkBytes( initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot ); // Calulate the snark input uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; // Verify proof if (!rollupVerifier.verifyProof(proof, [inputSnark])) { revert InvalidProof(); } // Get MATIC reward matic.safeTransfer( msg.sender, calculateRewardPerBatch() * (finalNewBatch - currentLastVerifiedBatch) ); } /** * @notice Internal function to consolidate the state automatically once sequence or verify batches are called * It tries to consolidate the first and the middle pending state in the queue */ function _tryConsolidatePendingState() internal { // Check if there's any state to consolidate if (lastPendingState > lastPendingStateConsolidated) { // Check if it's possible to consolidate the next pending state uint64 nextPendingState = lastPendingStateConsolidated + 1; if (isPendingStateConsolidable(nextPendingState)) { // Check middle pending state ( binary search of 1 step) uint64 middlePendingState = nextPendingState + (lastPendingState - nextPendingState) / 2; // Try to consolidate it, and if not, consolidate the nextPendingState if (isPendingStateConsolidable(middlePendingState)) { _consolidatePendingState(middlePendingState); } else { _consolidatePendingState(nextPendingState); } } } } /** * @notice Allows to consolidate any pending state that has already exceed the pendingStateTimeout * Can be called by the trusted aggregator, which can consolidate any state without the timeout restrictions * @param pendingStateNum Pending state to consolidate */ function consolidatePendingState(uint64 pendingStateNum) external { // Check if pending state can be consolidated // If trusted aggregator is the sender, do not check the timeout or the emergency state if (msg.sender != trustedAggregator) { if (isEmergencyState) { revert OnlyNotEmergencyState(); } if (!isPendingStateConsolidable(pendingStateNum)) { revert PendingStateNotConsolidable(); } } _consolidatePendingState(pendingStateNum); } /** * @notice Internal function to consolidate any pending state that has already exceed the pendingStateTimeout * @param pendingStateNum Pending state to consolidate */ function _consolidatePendingState(uint64 pendingStateNum) internal { // Check if pendingStateNum is in correct range // - not consolidated (implicity checks that is not 0) // - exist ( has been added) if ( pendingStateNum <= lastPendingStateConsolidated || pendingStateNum > lastPendingState ) { revert PendingStateInvalid(); } PendingState storage currentPendingState = pendingStateTransitions[ pendingStateNum ]; // Update state uint64 newLastVerifiedBatch = currentPendingState.lastVerifiedBatch; lastVerifiedBatch = newLastVerifiedBatch; batchNumToStateRoot[newLastVerifiedBatch] = currentPendingState .stateRoot; // Update pending state lastPendingStateConsolidated = pendingStateNum; // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(currentPendingState.exitRoot); emit ConsolidatePendingState( newLastVerifiedBatch, currentPendingState.stateRoot, pendingStateNum ); } /** * @notice Function to update the batch fee based on the new verified batches * The batch fee will not be updated when the trusted aggregator verifies batches * @param newLastVerifiedBatch New last verified batch */ function _updateBatchFee(uint64 newLastVerifiedBatch) internal { uint64 currentLastVerifiedBatch = getLastVerifiedBatch(); uint64 currentBatch = newLastVerifiedBatch; uint256 totalBatchesAboveTarget; uint256 newBatchesVerified = newLastVerifiedBatch - currentLastVerifiedBatch; uint256 targetTimestamp = block.timestamp - verifyBatchTimeTarget; while (currentBatch != currentLastVerifiedBatch) { // Load sequenced batchdata SequencedBatchData storage currentSequencedBatchData = sequencedBatches[ currentBatch ]; // Check if timestamp is below the verifyBatchTimeTarget if ( targetTimestamp < currentSequencedBatchData.sequencedTimestamp ) { // update currentBatch currentBatch = currentSequencedBatchData .previousLastBatchSequenced; } else { // The rest of batches will be above totalBatchesAboveTarget = currentBatch - currentLastVerifiedBatch; break; } } uint256 totalBatchesBelowTarget = newBatchesVerified - totalBatchesAboveTarget; // _MAX_BATCH_FEE --> (< 70 bits) // multiplierBatchFee --> (< 10 bits) // _MAX_BATCH_MULTIPLIER = 12 // multiplierBatchFee ** _MAX_BATCH_MULTIPLIER --> (< 128 bits) // batchFee * (multiplierBatchFee ** _MAX_BATCH_MULTIPLIER)--> // (< 70 bits) * (< 128 bits) = < 256 bits // Since all the following operations cannot overflow, we can optimize this operations with unchecked unchecked { if (totalBatchesBelowTarget < totalBatchesAboveTarget) { // There are more batches above target, fee is multiplied uint256 diffBatches = totalBatchesAboveTarget - totalBatchesBelowTarget; diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER ? _MAX_BATCH_MULTIPLIER : diffBatches; // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals batchFee = (batchFee * (uint256(multiplierBatchFee) ** diffBatches)) / (uint256(1000) ** diffBatches); } else { // There are more batches below target, fee is divided uint256 diffBatches = totalBatchesBelowTarget - totalBatchesAboveTarget; diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER ? _MAX_BATCH_MULTIPLIER : diffBatches; // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals uint256 accDivisor = (uint256(1 ether) * (uint256(multiplierBatchFee) ** diffBatches)) / (uint256(1000) ** diffBatches); // multiplyFactor = multiplierBatchFee ** diffBatches / 10 ** (diffBatches * 3) // accDivisor = 1E18 * multiplyFactor // 1E18 * batchFee / accDivisor = batchFee / multiplyFactor // < 60 bits * < 70 bits / ~60 bits --> overflow not possible batchFee = (uint256(1 ether) * batchFee) / accDivisor; } } // Batch fee must remain inside a range if (batchFee > _MAX_BATCH_FEE) { batchFee = _MAX_BATCH_FEE; } else if (batchFee < _MIN_BATCH_FEE) { batchFee = _MIN_BATCH_FEE; } } //////////////////////////// // Force batches functions //////////////////////////// /** * @notice Allows a sequencer/user to force a batch of L2 transactions. * This should be used only in extreme cases where the trusted sequencer does not work as expected * Note The sequencer has certain degree of control on how non-forced and forced batches are ordered * In order to assure that users force transactions will be processed properly, user must not sign any other transaction * with the same nonce * @param transactions L2 ethereum transactions EIP-155 or pre-EIP-155 with signature: * @param maticAmount Max amount of MATIC tokens that the sender is willing to pay */ function forceBatch( bytes calldata transactions, uint256 maticAmount ) public isForceBatchAllowed ifNotEmergencyState { // Calculate matic collateral uint256 maticFee = getForcedBatchFee(); if (maticFee > maticAmount) { revert NotEnoughMaticAmount(); } if (transactions.length > _MAX_FORCE_BATCH_BYTE_LENGTH) { revert TransactionsLengthAboveMax(); } matic.safeTransferFrom(msg.sender, address(this), maticFee); // Get globalExitRoot global exit root bytes32 lastGlobalExitRoot = globalExitRootManager .getLastGlobalExitRoot(); // Update forcedBatches mapping lastForceBatch++; forcedBatches[lastForceBatch] = keccak256( abi.encodePacked( keccak256(transactions), lastGlobalExitRoot, uint64(block.timestamp) ) ); if (msg.sender == tx.origin) { // Getting the calldata from an EOA is easy so no need to put the `transactions` in the event emit ForceBatch(lastForceBatch, lastGlobalExitRoot, msg.sender, ""); } else { // Getting internal transaction calldata is complicated (because it requires an archive node) // Therefore it's worth it to put the `transactions` in the event, which is easy to query emit ForceBatch( lastForceBatch, lastGlobalExitRoot, msg.sender, transactions ); } } /** * @notice Allows anyone to sequence forced Batches if the trusted sequencer has not done so in the timeout period * @param batches Struct array which holds the necessary data to append force batches */ function sequenceForceBatches( ForcedBatchData[] calldata batches ) external isForceBatchAllowed ifNotEmergencyState { uint256 batchesNum = batches.length; if (batchesNum == 0) { revert SequenceZeroBatches(); } if (batchesNum > _MAX_VERIFY_BATCHES) { revert ExceedMaxVerifyBatches(); } if ( uint256(lastForceBatchSequenced) + batchesNum > uint256(lastForceBatch) ) { revert ForceBatchesOverflow(); } // Store storage variables in memory, to save gas, because will be overrided multiple times uint64 currentBatchSequenced = lastBatchSequenced; uint64 currentLastForceBatchSequenced = lastForceBatchSequenced; bytes32 currentAccInputHash = sequencedBatches[currentBatchSequenced] .accInputHash; // Sequence force batches for (uint256 i = 0; i < batchesNum; i++) { // Load current sequence ForcedBatchData memory currentBatch = batches[i]; currentLastForceBatchSequenced++; // Store the current transactions hash since it's used more than once for gas saving bytes32 currentTransactionsHash = keccak256( currentBatch.transactions ); // Check forced data matches bytes32 hashedForcedBatchData = keccak256( abi.encodePacked( currentTransactionsHash, currentBatch.globalExitRoot, currentBatch.minForcedTimestamp ) ); if ( hashedForcedBatchData != forcedBatches[currentLastForceBatchSequenced] ) { revert ForcedDataDoesNotMatch(); } // Delete forceBatch data since won't be used anymore delete forcedBatches[currentLastForceBatchSequenced]; if (i == (batchesNum - 1)) { // The last batch will have the most restrictive timestamp if ( currentBatch.minForcedTimestamp + forceBatchTimeout > block.timestamp ) { revert ForceBatchTimeoutNotExpired(); } } // Calculate next acc input hash currentAccInputHash = keccak256( abi.encodePacked( currentAccInputHash, currentTransactionsHash, currentBatch.globalExitRoot, uint64(block.timestamp), msg.sender ) ); } // Update currentBatchSequenced currentBatchSequenced += uint64(batchesNum); lastTimestamp = uint64(block.timestamp); // Store back the storage variables sequencedBatches[currentBatchSequenced] = SequencedBatchData({ accInputHash: currentAccInputHash, sequencedTimestamp: uint64(block.timestamp), previousLastBatchSequenced: lastBatchSequenced }); lastBatchSequenced = currentBatchSequenced; lastForceBatchSequenced = currentLastForceBatchSequenced; emit SequenceForceBatches(currentBatchSequenced); } ////////////////// // admin functions ////////////////// /** * @notice Allow the admin to set a new trusted sequencer * @param newTrustedSequencer Address of the new trusted sequencer */ function setTrustedSequencer( address newTrustedSequencer ) external onlyAdmin { trustedSequencer = newTrustedSequencer; emit SetTrustedSequencer(newTrustedSequencer); } /** * @notice Allow the admin to set the trusted sequencer URL * @param newTrustedSequencerURL URL of trusted sequencer */ function setTrustedSequencerURL( string memory newTrustedSequencerURL ) external onlyAdmin { trustedSequencerURL = newTrustedSequencerURL; emit SetTrustedSequencerURL(newTrustedSequencerURL); } /** * @notice Allow the admin to set a new trusted aggregator address * @param newTrustedAggregator Address of the new trusted aggregator */ function setTrustedAggregator( address newTrustedAggregator ) external onlyAdmin { trustedAggregator = newTrustedAggregator; emit SetTrustedAggregator(newTrustedAggregator); } /** * @notice Allow the admin to set a new pending state timeout * The timeout can only be lowered, except if emergency state is active * @param newTrustedAggregatorTimeout Trusted aggregator timeout */ function setTrustedAggregatorTimeout( uint64 newTrustedAggregatorTimeout ) external onlyAdmin { if (newTrustedAggregatorTimeout > _HALT_AGGREGATION_TIMEOUT) { revert TrustedAggregatorTimeoutExceedHaltAggregationTimeout(); } if (!isEmergencyState) { if (newTrustedAggregatorTimeout >= trustedAggregatorTimeout) { revert NewTrustedAggregatorTimeoutMustBeLower(); } } trustedAggregatorTimeout = newTrustedAggregatorTimeout; emit SetTrustedAggregatorTimeout(newTrustedAggregatorTimeout); } /** * @notice Allow the admin to set a new trusted aggregator timeout * The timeout can only be lowered, except if emergency state is active * @param newPendingStateTimeout Trusted aggregator timeout */ function setPendingStateTimeout( uint64 newPendingStateTimeout ) external onlyAdmin { if (newPendingStateTimeout > _HALT_AGGREGATION_TIMEOUT) { revert PendingStateTimeoutExceedHaltAggregationTimeout(); } if (!isEmergencyState) { if (newPendingStateTimeout >= pendingStateTimeout) { revert NewPendingStateTimeoutMustBeLower(); } } pendingStateTimeout = newPendingStateTimeout; emit SetPendingStateTimeout(newPendingStateTimeout); } /** * @notice Allow the admin to set a new multiplier batch fee * @param newMultiplierBatchFee multiplier batch fee */ function setMultiplierBatchFee( uint16 newMultiplierBatchFee ) external onlyAdmin { if (newMultiplierBatchFee < 1000 || newMultiplierBatchFee > 1023) { revert InvalidRangeMultiplierBatchFee(); } multiplierBatchFee = newMultiplierBatchFee; emit SetMultiplierBatchFee(newMultiplierBatchFee); } /** * @notice Allow the admin to set a new verify batch time target * This value will only be relevant once the aggregation is decentralized, so * the trustedAggregatorTimeout should be zero or very close to zero * @param newVerifyBatchTimeTarget Verify batch time target */ function setVerifyBatchTimeTarget( uint64 newVerifyBatchTimeTarget ) external onlyAdmin { if (newVerifyBatchTimeTarget > 1 days) { revert InvalidRangeBatchTimeTarget(); } verifyBatchTimeTarget = newVerifyBatchTimeTarget; emit SetVerifyBatchTimeTarget(newVerifyBatchTimeTarget); } /** * @notice Allow the admin to set the forcedBatchTimeout * The new value can only be lower, except if emergency state is active * @param newforceBatchTimeout New force batch timeout */ function setForceBatchTimeout( uint64 newforceBatchTimeout ) external onlyAdmin { if (newforceBatchTimeout > _HALT_AGGREGATION_TIMEOUT) { revert InvalidRangeForceBatchTimeout(); } if (!isEmergencyState) { if (newforceBatchTimeout >= forceBatchTimeout) { revert InvalidRangeForceBatchTimeout(); } } forceBatchTimeout = newforceBatchTimeout; emit SetForceBatchTimeout(newforceBatchTimeout); } /** * @notice Allow the admin to turn on the force batches * This action is not reversible */ function activateForceBatches() external onlyAdmin { if (!isForcedBatchDisallowed) { revert ForceBatchesAlreadyActive(); } isForcedBatchDisallowed = false; emit ActivateForceBatches(); } /** * @notice Starts the admin role transfer * This is a two step process, the pending admin must accepted to finalize the process * @param newPendingAdmin Address of the new pending admin */ function transferAdminRole(address newPendingAdmin) external onlyAdmin { pendingAdmin = newPendingAdmin; emit TransferAdminRole(newPendingAdmin); } /** * @notice Allow the current pending admin to accept the admin role */ function acceptAdminRole() external { if (pendingAdmin != msg.sender) { revert OnlyPendingAdmin(); } admin = pendingAdmin; emit AcceptAdminRole(pendingAdmin); } ///////////////////////////////// // Soundness protection functions ///////////////////////////////// /** * @notice Allows the trusted aggregator to override the pending state * if it's possible to prove a different state root given the same batches * @param initPendingStateNum Init pending state, 0 if consolidated state is used * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function overridePendingState( uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) external onlyTrustedAggregator { _proveDistinctPendingState( initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof ); // Consolidate state state lastVerifiedBatch = finalNewBatch; batchNumToStateRoot[finalNewBatch] = newStateRoot; // Clean pending state if any if (lastPendingState > 0) { lastPendingState = 0; lastPendingStateConsolidated = 0; } // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(newLocalExitRoot); // Update trusted aggregator timeout to max trustedAggregatorTimeout = _HALT_AGGREGATION_TIMEOUT; emit OverridePendingState(finalNewBatch, newStateRoot, msg.sender); } /** * @notice Allows to halt the PolygonZkEVM if its possible to prove a different state root given the same batches * @param initPendingStateNum Init pending state, 0 if consolidated state is used * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function proveNonDeterministicPendingState( uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) external ifNotEmergencyState { _proveDistinctPendingState( initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof ); emit ProveNonDeterministicPendingState( batchNumToStateRoot[finalNewBatch], newStateRoot ); // Activate emergency state _activateEmergencyState(); } /** * @notice Internal function that proves a different state root given the same batches to verify * @param initPendingStateNum Init pending state, 0 if consolidated state is used * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param newStateRoot New State root once the batch is processed * @param proof fflonk proof */ function _proveDistinctPendingState( uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes calldata proof ) internal view { bytes32 oldStateRoot; // Use pending state if specified, otherwise use consolidated state if (initPendingStateNum != 0) { // Check that pending state exist // Already consolidated pending states can be used aswell if (initPendingStateNum > lastPendingState) { revert PendingStateDoesNotExist(); } // Check choosen pending state PendingState storage initPendingState = pendingStateTransitions[ initPendingStateNum ]; // Get oldStateRoot from init pending state oldStateRoot = initPendingState.stateRoot; // Check initNumBatch matches the init pending state if (initNumBatch != initPendingState.lastVerifiedBatch) { revert InitNumBatchDoesNotMatchPendingState(); } } else { // Use consolidated state oldStateRoot = batchNumToStateRoot[initNumBatch]; if (oldStateRoot == bytes32(0)) { revert OldStateRootDoesNotExist(); } // Check initNumBatch is inside the range, sanity check if (initNumBatch > lastVerifiedBatch) { revert InitNumBatchAboveLastVerifiedBatch(); } } // Assert final pending state num is in correct range // - exist ( has been added) // - bigger than the initPendingstate // - not consolidated if ( finalPendingStateNum > lastPendingState || finalPendingStateNum <= initPendingStateNum || finalPendingStateNum <= lastPendingStateConsolidated ) { revert FinalPendingStateNumInvalid(); } // Check final num batch if ( finalNewBatch != pendingStateTransitions[finalPendingStateNum].lastVerifiedBatch ) { revert FinalNumBatchDoesNotMatchPendingState(); } // Get snark bytes bytes memory snarkHashBytes = getInputSnarkBytes( initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot ); // Calulate the snark input uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; // Verify proof if (!rollupVerifier.verifyProof(proof, [inputSnark])) { revert InvalidProof(); } if ( pendingStateTransitions[finalPendingStateNum].stateRoot == newStateRoot ) { revert StoredRootMustBeDifferentThanNewRoot(); } } /** * @notice Function to activate emergency state, which also enables the emergency mode on both PolygonZkEVM and PolygonZkEVMBridge contracts * If not called by the owner must be provided a batcnNum that does not have been aggregated in a _HALT_AGGREGATION_TIMEOUT period * @param sequencedBatchNum Sequenced batch number that has not been aggreagated in _HALT_AGGREGATION_TIMEOUT */ function activateEmergencyState(uint64 sequencedBatchNum) external { if (msg.sender != owner()) { // Only check conditions if is not called by the owner uint64 currentLastVerifiedBatch = getLastVerifiedBatch(); // Check that the batch has not been verified if (sequencedBatchNum <= currentLastVerifiedBatch) { revert BatchAlreadyVerified(); } // Check that the batch has been sequenced and this was the end of a sequence if ( sequencedBatchNum > lastBatchSequenced || sequencedBatches[sequencedBatchNum].sequencedTimestamp == 0 ) { revert BatchNotSequencedOrNotSequenceEnd(); } // Check that has been passed _HALT_AGGREGATION_TIMEOUT since it was sequenced if ( sequencedBatches[sequencedBatchNum].sequencedTimestamp + _HALT_AGGREGATION_TIMEOUT > block.timestamp ) { revert HaltTimeoutNotExpired(); } } _activateEmergencyState(); } /** * @notice Function to deactivate emergency state on both PolygonZkEVM and PolygonZkEVMBridge contracts */ function deactivateEmergencyState() external onlyAdmin { // Deactivate emergency state on PolygonZkEVMBridge bridgeAddress.deactivateEmergencyState(); // Deactivate emergency state on this contract super._deactivateEmergencyState(); } /** * @notice Internal function to activate emergency state on both PolygonZkEVM and PolygonZkEVMBridge contracts */ function _activateEmergencyState() internal override { // Activate emergency state on PolygonZkEVM Bridge bridgeAddress.activateEmergencyState(); // Activate emergency state on this contract super._activateEmergencyState(); } //////////////////////// // public/view functions //////////////////////// /** * @notice Get forced batch fee */ function getForcedBatchFee() public view returns (uint256) { return batchFee * 100; } /** * @notice Get the last verified batch */ function getLastVerifiedBatch() public view returns (uint64) { if (lastPendingState > 0) { return pendingStateTransitions[lastPendingState].lastVerifiedBatch; } else { return lastVerifiedBatch; } } /** * @notice Returns a boolean that indicates if the pendingStateNum is or not consolidable * Note that his function does not check if the pending state currently exists, or if it's consolidated already */ function isPendingStateConsolidable( uint64 pendingStateNum ) public view returns (bool) { return (pendingStateTransitions[pendingStateNum].timestamp + pendingStateTimeout <= block.timestamp); } /** * @notice Function to calculate the reward to verify a single batch */ function calculateRewardPerBatch() public view returns (uint256) { uint256 currentBalance = matic.balanceOf(address(this)); // Total Sequenced Batches = forcedBatches to be sequenced (total forced Batches - sequenced Batches) + sequencedBatches // Total Batches to be verified = Total Sequenced Batches - verified Batches uint256 totalBatchesToVerify = ((lastForceBatch - lastForceBatchSequenced) + lastBatchSequenced) - getLastVerifiedBatch(); if (totalBatchesToVerify == 0) return 0; return currentBalance / totalBatchesToVerify; } /** * @notice Function to calculate the input snark bytes * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed * @param oldStateRoot State root before batch is processed * @param newStateRoot New State root once the batch is processed */ function getInputSnarkBytes( uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 oldStateRoot, bytes32 newStateRoot ) public view returns (bytes memory) { // sanity checks bytes32 oldAccInputHash = sequencedBatches[initNumBatch].accInputHash; bytes32 newAccInputHash = sequencedBatches[finalNewBatch].accInputHash; if (initNumBatch != 0 && oldAccInputHash == bytes32(0)) { revert OldAccInputHashDoesNotExist(); } if (newAccInputHash == bytes32(0)) { revert NewAccInputHashDoesNotExist(); } // Check that new state root is inside goldilocks field if (!checkStateRootInsidePrime(uint256(newStateRoot))) { revert NewStateRootNotInsidePrime(); } return abi.encodePacked( msg.sender, oldStateRoot, oldAccInputHash, initNumBatch, chainID, forkID, newStateRoot, newAccInputHash, newLocalExitRoot, finalNewBatch ); } function checkStateRootInsidePrime( uint256 newStateRoot ) public pure returns (bool) { if ( ((newStateRoot & _MAX_UINT_64) < _GOLDILOCKS_PRIME_FIELD) && (((newStateRoot >> 64) & _MAX_UINT_64) < _GOLDILOCKS_PRIME_FIELD) && (((newStateRoot >> 128) & _MAX_UINT_64) < _GOLDILOCKS_PRIME_FIELD) && ((newStateRoot >> 192) < _GOLDILOCKS_PRIME_FIELD) ) { return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../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 anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing 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.8.1) (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] * ``` * 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 v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../extensions/draft-IERC20PermitUpgradeable.sol"; import "../../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20Upgradeable token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20Upgradeable token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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 * ==== * * [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://diligence.consensys.net/posts/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.5.11/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 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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../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; } /** * @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: AGPL-3.0 pragma solidity 0.8.17; interface IBasePolygonZkEVMGlobalExitRoot { /** * @dev Thrown when the caller is not the allowed contracts */ error OnlyAllowedContracts(); function updateExitRoot(bytes32 newRollupExitRoot) external; function globalExitRootMap( bytes32 globalExitRootNum ) external returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; interface IPolygonZkEVMBridge { /** * @dev Thrown when sender is not the PolygonZkEVM address */ error OnlyPolygonZkEVM(); /** * @dev Thrown when the destination network is invalid */ error DestinationNetworkInvalid(); /** * @dev Thrown when the amount does not match msg.value */ error AmountDoesNotMatchMsgValue(); /** * @dev Thrown when user is bridging tokens and is also sending a value */ error MsgValueNotZero(); /** * @dev Thrown when the Ether transfer on claimAsset fails */ error EtherTransferFailed(); /** * @dev Thrown when the message transaction on claimMessage fails */ error MessageFailed(); /** * @dev Thrown when the global exit root does not exist */ error GlobalExitRootInvalid(); /** * @dev Thrown when the smt proof does not match */ error InvalidSmtProof(); /** * @dev Thrown when an index is already claimed */ error AlreadyClaimed(); /** * @dev Thrown when the owner of permit does not match the sender */ error NotValidOwner(); /** * @dev Thrown when the spender of the permit does not match this contract address */ error NotValidSpender(); /** * @dev Thrown when the amount of the permit does not match */ error NotValidAmount(); /** * @dev Thrown when the permit data contains an invalid signature */ error NotValidSignature(); function bridgeAsset( uint32 destinationNetwork, address destinationAddress, uint256 amount, address token, bool forceUpdateGlobalExitRoot, bytes calldata permitData ) external payable; function bridgeMessage( uint32 destinationNetwork, address destinationAddress, bool forceUpdateGlobalExitRoot, bytes calldata metadata ) external payable; function claimAsset( bytes32[32] calldata smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes calldata metadata ) external; function claimMessage( bytes32[32] calldata smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes calldata metadata ) external; function updateGlobalExitRoot() external; function activateEmergencyState() external; function deactivateEmergencyState() external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; interface IPolygonZkEVMErrors { /** * @dev Thrown when the pending state timeout exceeds the _HALT_AGGREGATION_TIMEOUT */ error PendingStateTimeoutExceedHaltAggregationTimeout(); /** * @dev Thrown when the trusted aggregator timeout exceeds the _HALT_AGGREGATION_TIMEOUT */ error TrustedAggregatorTimeoutExceedHaltAggregationTimeout(); /** * @dev Thrown when the caller is not the admin */ error OnlyAdmin(); /** * @dev Thrown when the caller is not the trusted sequencer */ error OnlyTrustedSequencer(); /** * @dev Thrown when the caller is not the trusted aggregator */ error OnlyTrustedAggregator(); /** * @dev Thrown when attempting to sequence 0 batches */ error SequenceZeroBatches(); /** * @dev Thrown when attempting to sequence or verify more batches than _MAX_VERIFY_BATCHES */ error ExceedMaxVerifyBatches(); /** * @dev Thrown when the forced data does not match */ error ForcedDataDoesNotMatch(); /** * @dev Thrown when the sequenced timestamp is below the forced minimum timestamp */ error SequencedTimestampBelowForcedTimestamp(); /** * @dev Thrown when a global exit root is not zero and does not exist */ error GlobalExitRootNotExist(); /** * @dev Thrown when transactions array length is above _MAX_TRANSACTIONS_BYTE_LENGTH. */ error TransactionsLengthAboveMax(); /** * @dev Thrown when a sequenced timestamp is not inside a correct range. */ error SequencedTimestampInvalid(); /** * @dev Thrown when there are more sequenced force batches than were actually submitted, should be unreachable */ error ForceBatchesOverflow(); /** * @dev Thrown when there are more sequenced force batches than were actually submitted */ error TrustedAggregatorTimeoutNotExpired(); /** * @dev Thrown when attempting to access a pending state that does not exist */ error PendingStateDoesNotExist(); /** * @dev Thrown when the init num batch does not match with the one in the pending state */ error InitNumBatchDoesNotMatchPendingState(); /** * @dev Thrown when the old state root of a certain batch does not exist */ error OldStateRootDoesNotExist(); /** * @dev Thrown when the init verification batch is above the last verification batch */ error InitNumBatchAboveLastVerifiedBatch(); /** * @dev Thrown when the final verification batch is below or equal the last verification batch */ error FinalNumBatchBelowLastVerifiedBatch(); /** * @dev Thrown when the zkproof is not valid */ error InvalidProof(); /** * @dev Thrown when attempting to consolidate a pending state not yet consolidable */ error PendingStateNotConsolidable(); /** * @dev Thrown when attempting to consolidate a pending state that is already consolidated or does not exist */ error PendingStateInvalid(); /** * @dev Thrown when the matic amount is below the necessary matic fee */ error NotEnoughMaticAmount(); /** * @dev Thrown when attempting to sequence a force batch using sequenceForceBatches and the * force timeout did not expire */ error ForceBatchTimeoutNotExpired(); /** * @dev Thrown when attempting to set a new trusted aggregator timeout equal or bigger than current one */ error NewTrustedAggregatorTimeoutMustBeLower(); /** * @dev Thrown when attempting to set a new pending state timeout equal or bigger than current one */ error NewPendingStateTimeoutMustBeLower(); /** * @dev Thrown when attempting to set a new multiplier batch fee in a invalid range of values */ error InvalidRangeMultiplierBatchFee(); /** * @dev Thrown when attempting to set a batch time target in an invalid range of values */ error InvalidRangeBatchTimeTarget(); /** * @dev Thrown when attempting to set a force batch timeout in an invalid range of values */ error InvalidRangeForceBatchTimeout(); /** * @dev Thrown when the caller is not the pending admin */ error OnlyPendingAdmin(); /** * @dev Thrown when the final pending state num is not in a valid range */ error FinalPendingStateNumInvalid(); /** * @dev Thrown when the final num batch does not match with the one in the pending state */ error FinalNumBatchDoesNotMatchPendingState(); /** * @dev Thrown when the stored root matches the new root proving a different state */ error StoredRootMustBeDifferentThanNewRoot(); /** * @dev Thrown when the batch is already verified when attempting to activate the emergency state */ error BatchAlreadyVerified(); /** * @dev Thrown when the batch is not sequenced or not at the end of a sequence when attempting to activate the emergency state */ error BatchNotSequencedOrNotSequenceEnd(); /** * @dev Thrown when the halt timeout is not expired when attempting to activate the emergency state */ error HaltTimeoutNotExpired(); /** * @dev Thrown when the old accumulate input hash does not exist */ error OldAccInputHashDoesNotExist(); /** * @dev Thrown when the new accumulate input hash does not exist */ error NewAccInputHashDoesNotExist(); /** * @dev Thrown when the new state root is not inside prime */ error NewStateRootNotInsidePrime(); /** * @dev Thrown when force batch is not allowed */ error ForceBatchNotAllowed(); /** * @dev Thrown when try to activate force batches when they are already active */ error ForceBatchesAlreadyActive(); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; import "./IBasePolygonZkEVMGlobalExitRoot.sol"; interface IPolygonZkEVMGlobalExitRoot is IBasePolygonZkEVMGlobalExitRoot { function getLastGlobalExitRoot() external view returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; /** * @dev Define interface verifier */ interface IVerifierRollup { function verifyProof( bytes memory proof, uint256[1] memory pubSignals ) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; /** * @dev Contract helper responsible to manage the emergency state */ contract EmergencyManager { /** * @dev Thrown when emergency state is active, and the function requires otherwise */ error OnlyNotEmergencyState(); /** * @dev Thrown when emergency state is not active, and the function requires otherwise */ error OnlyEmergencyState(); /** * @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. */ uint256[10] private _gap; // Indicates whether the emergency state is active or not bool public isEmergencyState; /** * @dev Emitted when emergency state is activated */ event EmergencyStateActivated(); /** * @dev Emitted when emergency state is deactivated */ event EmergencyStateDeactivated(); /** * @notice Only allows a function to be callable if emergency state is unactive */ modifier ifNotEmergencyState() { if (isEmergencyState) { revert OnlyNotEmergencyState(); } _; } /** * @notice Only allows a function to be callable if emergency state is active */ modifier ifEmergencyState() { if (!isEmergencyState) { revert OnlyEmergencyState(); } _; } /** * @notice Activate emergency state */ function _activateEmergencyState() internal virtual ifNotEmergencyState { isEmergencyState = true; emit EmergencyStateActivated(); } /** * @notice Deactivate emergency state */ function _deactivateEmergencyState() internal virtual ifEmergencyState { isEmergencyState = false; emit EmergencyStateDeactivated(); } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IPolygonZkEVMGlobalExitRoot","name":"_globalExitRootManager","type":"address"},{"internalType":"contract IERC20Upgradeable","name":"_matic","type":"address"},{"internalType":"contract IVerifierRollup","name":"_rollupVerifier","type":"address"},{"internalType":"contract IPolygonZkEVMBridge","name":"_bridgeAddress","type":"address"},{"internalType":"uint64","name":"_chainID","type":"uint64"},{"internalType":"uint64","name":"_forkID","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BatchAlreadyVerified","type":"error"},{"inputs":[],"name":"BatchNotSequencedOrNotSequenceEnd","type":"error"},{"inputs":[],"name":"ExceedMaxVerifyBatches","type":"error"},{"inputs":[],"name":"FinalNumBatchBelowLastVerifiedBatch","type":"error"},{"inputs":[],"name":"FinalNumBatchDoesNotMatchPendingState","type":"error"},{"inputs":[],"name":"FinalPendingStateNumInvalid","type":"error"},{"inputs":[],"name":"ForceBatchNotAllowed","type":"error"},{"inputs":[],"name":"ForceBatchTimeoutNotExpired","type":"error"},{"inputs":[],"name":"ForceBatchesAlreadyActive","type":"error"},{"inputs":[],"name":"ForceBatchesOverflow","type":"error"},{"inputs":[],"name":"ForcedDataDoesNotMatch","type":"error"},{"inputs":[],"name":"GlobalExitRootNotExist","type":"error"},{"inputs":[],"name":"HaltTimeoutNotExpired","type":"error"},{"inputs":[],"name":"InitNumBatchAboveLastVerifiedBatch","type":"error"},{"inputs":[],"name":"InitNumBatchDoesNotMatchPendingState","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidRangeBatchTimeTarget","type":"error"},{"inputs":[],"name":"InvalidRangeForceBatchTimeout","type":"error"},{"inputs":[],"name":"InvalidRangeMultiplierBatchFee","type":"error"},{"inputs":[],"name":"NewAccInputHashDoesNotExist","type":"error"},{"inputs":[],"name":"NewPendingStateTimeoutMustBeLower","type":"error"},{"inputs":[],"name":"NewStateRootNotInsidePrime","type":"error"},{"inputs":[],"name":"NewTrustedAggregatorTimeoutMustBeLower","type":"error"},{"inputs":[],"name":"NotEnoughMaticAmount","type":"error"},{"inputs":[],"name":"OldAccInputHashDoesNotExist","type":"error"},{"inputs":[],"name":"OldStateRootDoesNotExist","type":"error"},{"inputs":[],"name":"OnlyAdmin","type":"error"},{"inputs":[],"name":"OnlyEmergencyState","type":"error"},{"inputs":[],"name":"OnlyNotEmergencyState","type":"error"},{"inputs":[],"name":"OnlyPendingAdmin","type":"error"},{"inputs":[],"name":"OnlyTrustedAggregator","type":"error"},{"inputs":[],"name":"OnlyTrustedSequencer","type":"error"},{"inputs":[],"name":"PendingStateDoesNotExist","type":"error"},{"inputs":[],"name":"PendingStateInvalid","type":"error"},{"inputs":[],"name":"PendingStateNotConsolidable","type":"error"},{"inputs":[],"name":"PendingStateTimeoutExceedHaltAggregationTimeout","type":"error"},{"inputs":[],"name":"SequenceZeroBatches","type":"error"},{"inputs":[],"name":"SequencedTimestampBelowForcedTimestamp","type":"error"},{"inputs":[],"name":"SequencedTimestampInvalid","type":"error"},{"inputs":[],"name":"StoredRootMustBeDifferentThanNewRoot","type":"error"},{"inputs":[],"name":"TransactionsLengthAboveMax","type":"error"},{"inputs":[],"name":"TrustedAggregatorTimeoutExceedHaltAggregationTimeout","type":"error"},{"inputs":[],"name":"TrustedAggregatorTimeoutNotExpired","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AcceptAdminRole","type":"event"},{"anonymous":false,"inputs":[],"name":"ActivateForceBatches","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"pendingStateNum","type":"uint64"}],"name":"ConsolidatePendingState","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyStateActivated","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyStateDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"forceBatchNum","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"lastGlobalExitRoot","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sequencer","type":"address"},{"indexed":false,"internalType":"bytes","name":"transactions","type":"bytes"}],"name":"ForceBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"OverridePendingState","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":false,"internalType":"bytes32","name":"storedStateRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"provedStateRoot","type":"bytes32"}],"name":"ProveNonDeterministicPendingState","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"}],"name":"SequenceBatches","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"}],"name":"SequenceForceBatches","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newforceBatchTimeout","type":"uint64"}],"name":"SetForceBatchTimeout","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"newMultiplierBatchFee","type":"uint16"}],"name":"SetMultiplierBatchFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newPendingStateTimeout","type":"uint64"}],"name":"SetPendingStateTimeout","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTrustedAggregator","type":"address"}],"name":"SetTrustedAggregator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newTrustedAggregatorTimeout","type":"uint64"}],"name":"SetTrustedAggregatorTimeout","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTrustedSequencer","type":"address"}],"name":"SetTrustedSequencer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newTrustedSequencerURL","type":"string"}],"name":"SetTrustedSequencerURL","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"newVerifyBatchTimeTarget","type":"uint64"}],"name":"SetVerifyBatchTimeTarget","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"TransferAdminRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"numBatch","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"forkID","type":"uint64"},{"indexed":false,"internalType":"string","name":"version","type":"string"}],"name":"UpdateZkEVMVersion","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"VerifyBatches","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"numBatch","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"VerifyBatchesTrustedAggregator","type":"event"},{"inputs":[],"name":"acceptAdminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"sequencedBatchNum","type":"uint64"}],"name":"activateEmergencyState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"activateForceBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"batchNumToStateRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeAddress","outputs":[{"internalType":"contract IPolygonZkEVMBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateRewardPerBatch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newStateRoot","type":"uint256"}],"name":"checkStateRootInsidePrime","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"pendingStateNum","type":"uint64"}],"name":"consolidatePendingState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deactivateEmergencyState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"transactions","type":"bytes"},{"internalType":"uint256","name":"maticAmount","type":"uint256"}],"name":"forceBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"forceBatchTimeout","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"forcedBatches","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forkID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getForcedBatchFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"initNumBatch","type":"uint64"},{"internalType":"uint64","name":"finalNewBatch","type":"uint64"},{"internalType":"bytes32","name":"newLocalExitRoot","type":"bytes32"},{"internalType":"bytes32","name":"oldStateRoot","type":"bytes32"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"}],"name":"getInputSnarkBytes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastVerifiedBatch","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalExitRootManager","outputs":[{"internalType":"contract IPolygonZkEVMGlobalExitRoot","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"trustedSequencer","type":"address"},{"internalType":"uint64","name":"pendingStateTimeout","type":"uint64"},{"internalType":"address","name":"trustedAggregator","type":"address"},{"internalType":"uint64","name":"trustedAggregatorTimeout","type":"uint64"}],"internalType":"struct PolygonZkEVM.InitializePackedParameters","name":"initializePackedParameters","type":"tuple"},{"internalType":"bytes32","name":"genesisRoot","type":"bytes32"},{"internalType":"string","name":"_trustedSequencerURL","type":"string"},{"internalType":"string","name":"_networkName","type":"string"},{"internalType":"string","name":"_version","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isEmergencyState","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isForcedBatchDisallowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"pendingStateNum","type":"uint64"}],"name":"isPendingStateConsolidable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBatchSequenced","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastForceBatch","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastForceBatchSequenced","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPendingState","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPendingStateConsolidated","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastVerifiedBatch","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"matic","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"multiplierBatchFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"networkName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"initPendingStateNum","type":"uint64"},{"internalType":"uint64","name":"finalPendingStateNum","type":"uint64"},{"internalType":"uint64","name":"initNumBatch","type":"uint64"},{"internalType":"uint64","name":"finalNewBatch","type":"uint64"},{"internalType":"bytes32","name":"newLocalExitRoot","type":"bytes32"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"overridePendingState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingStateTimeout","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingStateTransitions","outputs":[{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBatch","type":"uint64"},{"internalType":"bytes32","name":"exitRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"initPendingStateNum","type":"uint64"},{"internalType":"uint64","name":"finalPendingStateNum","type":"uint64"},{"internalType":"uint64","name":"initNumBatch","type":"uint64"},{"internalType":"uint64","name":"finalNewBatch","type":"uint64"},{"internalType":"bytes32","name":"newLocalExitRoot","type":"bytes32"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"proveNonDeterministicPendingState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollupVerifier","outputs":[{"internalType":"contract IVerifierRollup","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"transactions","type":"bytes"},{"internalType":"bytes32","name":"globalExitRoot","type":"bytes32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"minForcedTimestamp","type":"uint64"}],"internalType":"struct PolygonZkEVM.BatchData[]","name":"batches","type":"tuple[]"},{"internalType":"address","name":"l2Coinbase","type":"address"}],"name":"sequenceBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"transactions","type":"bytes"},{"internalType":"bytes32","name":"globalExitRoot","type":"bytes32"},{"internalType":"uint64","name":"minForcedTimestamp","type":"uint64"}],"internalType":"struct PolygonZkEVM.ForcedBatchData[]","name":"batches","type":"tuple[]"}],"name":"sequenceForceBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"sequencedBatches","outputs":[{"internalType":"bytes32","name":"accInputHash","type":"bytes32"},{"internalType":"uint64","name":"sequencedTimestamp","type":"uint64"},{"internalType":"uint64","name":"previousLastBatchSequenced","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"newforceBatchTimeout","type":"uint64"}],"name":"setForceBatchTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newMultiplierBatchFee","type":"uint16"}],"name":"setMultiplierBatchFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newPendingStateTimeout","type":"uint64"}],"name":"setPendingStateTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTrustedAggregator","type":"address"}],"name":"setTrustedAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newTrustedAggregatorTimeout","type":"uint64"}],"name":"setTrustedAggregatorTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTrustedSequencer","type":"address"}],"name":"setTrustedSequencer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newTrustedSequencerURL","type":"string"}],"name":"setTrustedSequencerURL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newVerifyBatchTimeTarget","type":"uint64"}],"name":"setVerifyBatchTimeTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"transferAdminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trustedAggregator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedAggregatorTimeout","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedSequencer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedSequencerURL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifyBatchTimeTarget","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"pendingStateNum","type":"uint64"},{"internalType":"uint64","name":"initNumBatch","type":"uint64"},{"internalType":"uint64","name":"finalNewBatch","type":"uint64"},{"internalType":"bytes32","name":"newLocalExitRoot","type":"bytes32"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"verifyBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"pendingStateNum","type":"uint64"},{"internalType":"uint64","name":"initNumBatch","type":"uint64"},{"internalType":"uint64","name":"finalNewBatch","type":"uint64"},{"internalType":"bytes32","name":"newLocalExitRoot","type":"bytes32"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"verifyBatchesTrustedAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b50604051620060be380380620060be8339810160408190526200003591620000a5565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b0391821661010052166101205262000131565b6001600160a01b03811681146200008557600080fd5b50565b80516001600160401b0381168114620000a057600080fd5b919050565b60008060008060008060c08789031215620000bf57600080fd5b8651620000cc816200006f565b6020880151909650620000df816200006f565b6040880151909550620000f2816200006f565b606088015190945062000105816200006f565b9250620001156080880162000088565b91506200012560a0880162000088565b90509295509295509295565b60805160a05160c05160e0516101005161012051615ebf620001ff6000396000818161068301528181610e9f0152612f6d0152600081816107f00152610e750152600081816107a301528181611dfc01528181613607015261426301526000818161095c0152818161151301528181611a04015281816127e7015281816137a4015281816139ff0152614433015260008181610a1c01528181614150015261479f0152600081816108ac01528181611dca0152818161233e015281816139d3015261488e0152615ebf6000f3fe608060405234801561001057600080fd5b50600436106103ba5760003560e01c80638c3d7301116101f4578063c89e42df1161011a578063e7a7ed02116100ad578063f14916d61161007c578063f14916d614610a7e578063f2fde38b14610a91578063f851a44014610aa4578063f8b823e414610ac457600080fd5b8063e7a7ed02146109e7578063e8bf92ed14610a17578063eaeb077b14610a3e578063ed6b010414610a5157600080fd5b8063d8d1091b116100e9578063d8d1091b14610991578063d939b315146109a4578063dbc16976146109cc578063e6ad707e146109d457600080fd5b8063c89e42df14610915578063cfa8ed4714610928578063d02103ca14610957578063d2e129f91461097e57600080fd5b8063ada8f91911610192578063b6b0b09711610161578063b6b0b097146108a7578063ba58ae39146108ce578063c0ed84e0146108e1578063c754c7ed146108e957600080fd5b8063ada8f919146107d8578063adc879e9146107eb578063afd23cbe14610812578063b4d63f581461084057600080fd5b80639c9f3dfe116101ce5780639c9f3dfe14610778578063a066215c1461078b578063a3c573eb1461079e578063a50a164b146107c557600080fd5b80638c3d73011461074a5780638da5cb5b1461075257806399f5634e1461077057600080fd5b80634a910e6a116102e45780636b8616ce116102775780637fcb3653116102465780637fcb36531461066a578063831c7ead1461067e578063837a4738146106a5578063841b24d71461071a57600080fd5b80636b8616ce1461061c5780636ff512cc1461063c578063715018a61461064f5780637215541a1461065757600080fd5b8063542028d5116102b3578063542028d5146105f15780635e9145c9146105f95780635ec919581461060c578063604691691461061457600080fd5b80634a910e6a1461058a5780634e4877061461059d5780634fd70464146105b05780635392c5e0146105c357600080fd5b8063267822471161035c578063423fa8561161032b578063423fa8561461050e578063456052671461052e578063458c0477146105565780634a1a89a71461056a57600080fd5b8063267822471461047757806329878983146104bc578063383b3be8146104e8578063394218e9146104fb57600080fd5b806315064c961161039857806315064c96146104205780631816b7e51461043d57806319d8ac6114610450578063220d78991461046457600080fd5b80630808270c146103bf5780630a0d9fbe146103d4578063107bf28c1461040b575b600080fd5b6103d26103cd3660046152b9565b610acd565b005b606f546103ed90610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b610413610b80565b60405161040291906153c0565b606f5461042d9060ff1681565b6040519015158152602001610402565b6103d261044b3660046153da565b610c0e565b6073546103ed9067ffffffffffffffff1681565b6104136104723660046153fe565b610d26565b607b546104979073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610402565b6074546104979068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b61042d6104f636600461544b565b610efd565b6103d261050936600461544b565b610f53565b6073546103ed9068010000000000000000900467ffffffffffffffff1681565b6073546103ed90700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103ed9067ffffffffffffffff1681565b6079546103ed9068010000000000000000900467ffffffffffffffff1681565b6103d261059836600461544b565b6110d7565b6103d26105ab36600461544b565b61118a565b6103d26105be366004615466565b61130e565b6105e36105d136600461544b565b60756020526000908152604090205481565b604051908152602001610402565b6104136116a4565b6103d2610607366004615558565b6116b1565b6103d2611ebb565b6105e3611fbb565b6105e361062a36600461544b565b60716020526000908152604090205481565b6103d261064a3660046155ac565b611fd1565b6103d26120a6565b6103d261066536600461544b565b6120ba565b6074546103ed9067ffffffffffffffff1681565b6103ed7f000000000000000000000000000000000000000000000000000000000000000081565b6106ee6106b33660046155c7565b60786020526000908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff9586168152949093166020850152918301526060820152608001610402565b6079546103ed907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6103d261222a565b60335473ffffffffffffffffffffffffffffffffffffffff16610497565b6105e36122f6565b6103d261078636600461544b565b61244f565b6103d261079936600461544b565b6125cb565b6104977f000000000000000000000000000000000000000000000000000000000000000081565b6103d26107d3366004615466565b6126d1565b6103d26107e63660046155ac565b612896565b6103ed7f000000000000000000000000000000000000000000000000000000000000000081565b606f5461082d906901000000000000000000900461ffff1681565b60405161ffff9091168152602001610402565b61088161084e36600461544b565b6072602052600090815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff9283166020850152911690820152606001610402565b6104977f000000000000000000000000000000000000000000000000000000000000000081565b61042d6108dc3660046155c7565b61295a565b6103ed6129e4565b607b546103ed9074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6103d26109233660046156ba565b612a39565b606f54610497906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104977f000000000000000000000000000000000000000000000000000000000000000081565b6103d261098c3660046156ef565b612ac6565b6103d261099f3660046157a2565b613012565b6079546103ed90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103d26135b4565b6103d26109e23660046152b9565b61368d565b6073546103ed907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104977f000000000000000000000000000000000000000000000000000000000000000081565b6103d2610a4c3660046157e4565b61389d565b607b5461042d907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6103d2610a8c3660046155ac565b613c93565b6103d2610a9f3660046155ac565b613d65565b607a546104979073ffffffffffffffffffffffffffffffffffffffff1681565b6105e360705481565b606f5460ff1615610b0a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b1a8888888888888888613e19565b67ffffffffffffffff85166000908152607560209081526040918290205482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a1610b76614261565b5050505050505050565b60778054610b8d90615830565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb990615830565b8015610c065780601f10610bdb57610100808354040283529160200191610c06565b820191906000526020600020905b815481529060010190602001808311610be957829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610c5f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610c7857506103ff8161ffff16115b15610caf576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086166000818152607260205260408082205493881682529020546060929115801590610d5a575081155b15610d91576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610dc8576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dd18461295a565b610e07576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60795467ffffffffffffffff82811660009081526078602052604081205490924292610f4192700100000000000000000000000000000000909204811691166158b2565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610fa4576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610feb576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661105a5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061105a576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610d1b565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461117e57606f5460ff161561113f576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61114881610efd565b61117e576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611187816142e9565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146111db576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611222576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661128d57607b5467ffffffffffffffff7401000000000000000000000000000000000000000090910481169082161061128d576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610d1b565b606f5460ff161561134b576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8681166000908152607260205260409020600101544292611398927801000000000000000000000000000000000000000000000000909104811691166158b2565b67ffffffffffffffff1611156113da576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86113e787876158da565b67ffffffffffffffff161115611429576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611438878787878787876144fc565b611441856148b5565b607954700100000000000000000000000000000000900467ffffffffffffffff1660000361158957607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff878116918217909255600090815260756020526040902084905560795416156114e457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b50505050611659565b611591614a95565b6079805467ffffffffffffffff169060006115ab836158fb565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815288831660208083019182528284018a8152606084018a815260795487166000908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051838152339067ffffffffffffffff8716907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966906020015b60405180910390a350505050505050565b60768054610b8d90615830565b606f5460ff16156116ee576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461174e576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600081900361178a576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156117c6576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff6801000000000000000082048116600081815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611c165760008a8a8381811061182e5761182e615922565b90506020028101906118409190615951565b6118499061598f565b8051805160209091012060608201519192509067ffffffffffffffff16156119c15785611875816158fb565b965050600081836020015184606001516040516020016118cd93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a16600090815260719093529120549091508114611956576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80881660009081526071602052604080822091909155606085015190850151908216911610156119bb576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611afe565b602082015115801590611a88575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303816000875af1158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a869190615a1c565b155b15611abf576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611afe576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611b31575042826040015167ffffffffffffffff16115b15611b68576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611c0e90615a35565b915050611812565b50611c2186856158b2565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611c8a576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c9682856158da565b611caa9067ffffffffffffffff1688615a6d565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d861660008181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611da057607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611df2333083607054611db39190615a86565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190614b46565b611dfa614a95565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e6257600080fd5b505af1158015611e76573d6000803e3d6000fd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce9150600090a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f0c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611f68576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f90600090a1565b60006070546064611fcc9190615a86565b905090565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612022576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610d1b565b6120ae614c28565b6120b86000614ca9565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146122225760006120e36129e4565b90508067ffffffffffffffff168267ffffffffffffffff1611612132576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff6801000000000000000090910481169083161180612178575067ffffffffffffffff80831660009081526072602052604090206001015416155b156121af576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80831660009081526072602052604090206001015442916121de9162093a8091166158b2565b67ffffffffffffffff161115612220576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b611187614261565b607b5473ffffffffffffffffffffffffffffffffffffffff16331461227b576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a99190615a1c565b905060006123b56129e4565b60735467ffffffffffffffff68010000000000000000820481169161240d91700100000000000000000000000000000000820481169178010000000000000000000000000000000000000000000000009004166158da565b61241791906158b2565b61242191906158da565b67ffffffffffffffff1690508060000361243e5760009250505090565b6124488183615acc565b9250505090565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146124a0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156124e7576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661254e5760795467ffffffffffffffff70010000000000000000000000000000000090910481169082161061254e576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610d1b565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461261c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff161115612663576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610d1b565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461272e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61273d878787878787876144fc565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff878116918217909255600090815260756020526040902084905560795416156127b857607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561284057600080fd5b505af1158015612854573d6000803e3d6000fd5b505060405185815233925067ffffffffffffffff881691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe90602001611693565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146128e7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610d1b565b600067ffffffff0000000167ffffffffffffffff8316108015612992575067ffffffff00000001604083901c67ffffffffffffffff16105b80156129b3575067ffffffff00000001608083901c67ffffffffffffffff16105b80156129ca575067ffffffff0000000160c083901c105b156129d757506001919050565b506000919050565b919050565b60795460009067ffffffffffffffff1615612a28575060795467ffffffffffffffff9081166000908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612a8a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612a968282615b2e565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610d1b91906153c0565b600054610100900460ff1615808015612ae65750600054600160ff909116105b80612b005750303b158015612b00575060005460ff166001145b612b91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612bef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612bfc60208801886155ac565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612c5160408801602089016155ac565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612cb660808801606089016155ac565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790556000805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612d418682615b2e565b506077612d4e8582615b2e565b5062093a80612d636060890160408a0161544b565b67ffffffffffffffff161115612da5576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612db5606088016040890161544b565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612e1760a0890160808a0161544b565b67ffffffffffffffff161115612e59576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e6960a088016080890161544b565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055612f48614d20565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd660007f00000000000000000000000000000000000000000000000000000000000000008585604051612f9e9493929190615c91565b60405180910390a1801561300957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561306f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156130ac576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060008190036130e8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115613124576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161316f918491700100000000000000000000000000000000900416615cc9565b11156131a7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000008204811660008181526072602052604081205491937001000000000000000000000000000000009004909216915b8481101561345157600087878381811061320757613207615922565b90506020028101906132199190615cdc565b61322290615d10565b90508361322e816158fb565b825180516020918201208185015160408087015190519499509194506000936132909386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8916600090815260719093529120549091508114613319576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff861660009081526071602052604081205561333e600189615a6d565b84036133ad5742607b60149054906101000a900467ffffffffffffffff16846040015161336b91906158b2565b67ffffffffffffffff1611156133ad576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061344990615a35565b9150506131eb565b5061345c84846158b2565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589166000818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613605576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561366d57600080fd5b505af1158015613681573d6000803e3d6000fd5b505050506120b8614dc0565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146136ea576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136fa8888888888888888613e19565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8781169182179092556000908152607560205260409020849055607954161561377557607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b1580156137fd57600080fd5b505af1158015613811573d6000803e3d6000fd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051838152339067ffffffffffffffff8716907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a35050505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16156138fa576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613937576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613941611fbb565b90508181111561397d576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113888311156139b9576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6139fb73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084614b46565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8c9190615a1c565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613ac6836158fb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613afd929190615d8c565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660009081526071909352912055323303613c2d57607354604080518381523360208201526060918101829052600091810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c8c565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c839493929190615d9c565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613ce4576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610d1b565b613d6d614c28565b73ffffffffffffffffffffffffffffffffffffffff8116613e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612b88565b61118781614ca9565b600067ffffffffffffffff891615613ee75760795467ffffffffffffffff908116908a161115613e75576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8089166000908152607860205260409020600281015481549092898116680100000000000000009092041614613ee1576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f83565b5067ffffffffffffffff861660009081526075602052604090205480613f39576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169088161115613f83576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff9081169089161180613fb557508867ffffffffffffffff168867ffffffffffffffff1611155b80613fdc575060795467ffffffffffffffff68010000000000000000909104811690891611155b15614013576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff888116600090815260786020526040902054680100000000000000009004811690871614614076576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006140858888888589610d26565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516140ba9190615dd2565b602060405180830381855afa1580156140d7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906140fa9190615a1c565b6141049190615de4565b6040805160208101825282815290517f8d8f8a5c00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916141879189918991600401615df8565b602060405180830381865afa1580156141a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141c89190615e40565b6141fe576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8a16600090815260786020526040902060020154869003614254576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156142c957600080fd5b505af11580156142dd573d6000803e3d6000fd5b505050506120b8614e4f565b60795467ffffffffffffffff680100000000000000009091048116908216111580614323575060795467ffffffffffffffff908116908216115b1561435a576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff818116600081815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561448c57600080fd5b505af11580156144a0573d6000803e3d6000fd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516144ef91815260200190565b60405180910390a3505050565b6000806145076129e4565b905067ffffffffffffffff8916156145d75760795467ffffffffffffffff908116908a161115614563576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808a1660009081526078602052604090206002810154815490945090918a81166801000000000000000090920416146145d1576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614678565b67ffffffffffffffff881660009081526075602052604090205491508161462a576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff161115614678576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff16116146c5576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006146d4898989868a610d26565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516147099190615dd2565b602060405180830381855afa158015614726573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906147499190615a1c565b6147539190615de4565b6040805160208101825282815290517f8d8f8a5c00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916147d6918a918a91600401615df8565b602060405180830381865afa1580156147f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148179190615e40565b61484d576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142543361485b858c6158da565b67ffffffffffffffff1661486d6122f6565b6148779190615a86565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190614ee2565b60006148bf6129e4565b9050816000806148cf84846158da565b606f5467ffffffffffffffff91821692506000916148f39161010090041642615a6d565b90505b8467ffffffffffffffff168467ffffffffffffffff161461497e5767ffffffffffffffff8085166000908152607260205260409020600181015490911682101561495c57600181015468010000000000000000900467ffffffffffffffff169450614978565b61496686866158da565b67ffffffffffffffff1693505061497e565b506148f6565b600061498a8484615a6d565b9050838110156149e157808403600c81116149a557806149a8565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816149d7576149d7615a9d565b0460705550614a51565b838103600c81116149f257806149f5565b600c5b90506000816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a2c57614a2c615a9d565b04905080607054670de0b6b3a76400000281614a4a57614a4a615a9d565b0460705550505b683635c9adc5dea000006070541115614a7657683635c9adc5dea00000607055613009565b633b9aca00607054101561300957633b9aca0060705550505050505050565b60795467ffffffffffffffff6801000000000000000082048116911611156120b857607954600090614ade9068010000000000000000900467ffffffffffffffff1660016158b2565b9050614ae981610efd565b1561118757607954600090600290614b0c90849067ffffffffffffffff166158da565b614b169190615e62565b614b2090836158b2565b9050614b2b81610efd565b15614b3d57614b39816142e9565b5050565b614b39826142e9565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052614c229085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614f3d565b50505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146120b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612b88565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16614db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612b88565b6120b833614ca9565b606f5460ff16614dfc576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b606f5460ff1615614e8c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614f389084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401614ba0565b505050565b6000614f9f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166150499092919063ffffffff16565b805190915015614f385780806020019051810190614fbd9190615e40565b614f38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612b88565b60606150588484600085615060565b949350505050565b6060824710156150f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612b88565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161511b9190615dd2565b60006040518083038185875af1925050503d8060008114615158576040519150601f19603f3d011682016040523d82523d6000602084013e61515d565b606091505b509150915061516e87838387615179565b979650505050505050565b6060831561520f5782516000036152085773ffffffffffffffffffffffffffffffffffffffff85163b615208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612b88565b5081615058565b61505883838151156152245781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b8891906153c0565b803567ffffffffffffffff811681146129df57600080fd5b60008083601f84011261528257600080fd5b50813567ffffffffffffffff81111561529a57600080fd5b6020830191508360208285010111156152b257600080fd5b9250929050565b60008060008060008060008060e0898b0312156152d557600080fd5b6152de89615258565b97506152ec60208a01615258565b96506152fa60408a01615258565b955061530860608a01615258565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561533257600080fd5b61533e8b828c01615270565b999c989b5096995094979396929594505050565b60005b8381101561536d578181015183820152602001615355565b50506000910152565b6000815180845261538e816020860160208601615352565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006153d36020830184615376565b9392505050565b6000602082840312156153ec57600080fd5b813561ffff811681146153d357600080fd5b600080600080600060a0868803121561541657600080fd5b61541f86615258565b945061542d60208701615258565b94979496505050506040830135926060810135926080909101359150565b60006020828403121561545d57600080fd5b6153d382615258565b600080600080600080600060c0888a03121561548157600080fd5b61548a88615258565b965061549860208901615258565b95506154a660408901615258565b9450606088013593506080880135925060a088013567ffffffffffffffff8111156154d057600080fd5b6154dc8a828b01615270565b989b979a50959850939692959293505050565b60008083601f84011261550157600080fd5b50813567ffffffffffffffff81111561551957600080fd5b6020830191508360208260051b85010111156152b257600080fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146129df57600080fd5b60008060006040848603121561556d57600080fd5b833567ffffffffffffffff81111561558457600080fd5b615590868287016154ef565b90945092506155a3905060208501615534565b90509250925092565b6000602082840312156155be57600080fd5b6153d382615534565b6000602082840312156155d957600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261562057600080fd5b813567ffffffffffffffff8082111561563b5761563b6155e0565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615681576156816155e0565b8160405283815286602085880101111561569a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156156cc57600080fd5b813567ffffffffffffffff8111156156e357600080fd5b6150588482850161560f565b60008060008060008086880361012081121561570a57600080fd5b60a081121561571857600080fd5b5086955060a0870135945060c087013567ffffffffffffffff8082111561573e57600080fd5b61574a8a838b0161560f565b955060e089013591508082111561576057600080fd5b61576c8a838b0161560f565b945061010089013591508082111561578357600080fd5b5061579089828a01615270565b979a9699509497509295939492505050565b600080602083850312156157b557600080fd5b823567ffffffffffffffff8111156157cc57600080fd5b6157d8858286016154ef565b90969095509350505050565b6000806000604084860312156157f957600080fd5b833567ffffffffffffffff81111561581057600080fd5b61581c86828701615270565b909790965060209590950135949350505050565b600181811c9082168061584457607f821691505b60208210810361587d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156158d3576158d3615883565b5092915050565b67ffffffffffffffff8281168282160390808211156158d3576158d3615883565b600067ffffffffffffffff80831681810361591857615918615883565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261598557600080fd5b9190910192915050565b6000608082360312156159a157600080fd5b6040516080810167ffffffffffffffff82821081831117156159c5576159c56155e0565b8160405284359150808211156159da57600080fd5b506159e73682860161560f565b82525060208301356020820152615a0060408401615258565b6040820152615a1160608401615258565b606082015292915050565b600060208284031215615a2e57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a6657615a66615883565b5060010190565b81810381811115615a8057615a80615883565b92915050565b8082028115828204841417615a8057615a80615883565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615adb57615adb615a9d565b500490565b601f821115614f3857600081815260208120601f850160051c81016020861015615b075750805b601f850160051c820191505b81811015615b2657828155600101615b13565b505050505050565b815167ffffffffffffffff811115615b4857615b486155e0565b615b5c81615b568454615830565b84615ae0565b602080601f831160018114615baf5760008415615b795750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555615b26565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615bfc57888601518255948401946001909101908401615bdd565b5085821015615c3857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600067ffffffffffffffff808716835280861660208401525060606040830152615cbf606083018486615c48565b9695505050505050565b80820180821115615a8057615a80615883565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261598557600080fd5b600060608236031215615d2257600080fd5b6040516060810167ffffffffffffffff8282108183111715615d4657615d466155e0565b816040528435915080821115615d5b57600080fd5b50615d683682860161560f565b82525060208301356020820152615d8160408401615258565b604082015292915050565b8183823760009101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201526000615cbf606083018486615c48565b60008251615985818460208701615352565b600082615df357615df3615a9d565b500690565b604081526000615e0c604083018587615c48565b905060208083018460005b6001811015615e3457815183529183019190830190600101615e17565b50505050949350505050565b600060208284031215615e5257600080fd5b815180151581146153d357600080fd5b600067ffffffffffffffff80841680615e7d57615e7d615a9d565b9216919091049291505056fea2646970667358221220445ad406e7775b9ae031e5588d654f761118a1b49e4f965aa3fa3f7fbaeb46ac64736f6c63430008110033000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb00000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e90000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede000000000000000000000000000000000000000000000000000000000000044d0000000000000000000000000000000000000000000000000000000000000004
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103ba5760003560e01c80638c3d7301116101f4578063c89e42df1161011a578063e7a7ed02116100ad578063f14916d61161007c578063f14916d614610a7e578063f2fde38b14610a91578063f851a44014610aa4578063f8b823e414610ac457600080fd5b8063e7a7ed02146109e7578063e8bf92ed14610a17578063eaeb077b14610a3e578063ed6b010414610a5157600080fd5b8063d8d1091b116100e9578063d8d1091b14610991578063d939b315146109a4578063dbc16976146109cc578063e6ad707e146109d457600080fd5b8063c89e42df14610915578063cfa8ed4714610928578063d02103ca14610957578063d2e129f91461097e57600080fd5b8063ada8f91911610192578063b6b0b09711610161578063b6b0b097146108a7578063ba58ae39146108ce578063c0ed84e0146108e1578063c754c7ed146108e957600080fd5b8063ada8f919146107d8578063adc879e9146107eb578063afd23cbe14610812578063b4d63f581461084057600080fd5b80639c9f3dfe116101ce5780639c9f3dfe14610778578063a066215c1461078b578063a3c573eb1461079e578063a50a164b146107c557600080fd5b80638c3d73011461074a5780638da5cb5b1461075257806399f5634e1461077057600080fd5b80634a910e6a116102e45780636b8616ce116102775780637fcb3653116102465780637fcb36531461066a578063831c7ead1461067e578063837a4738146106a5578063841b24d71461071a57600080fd5b80636b8616ce1461061c5780636ff512cc1461063c578063715018a61461064f5780637215541a1461065757600080fd5b8063542028d5116102b3578063542028d5146105f15780635e9145c9146105f95780635ec919581461060c578063604691691461061457600080fd5b80634a910e6a1461058a5780634e4877061461059d5780634fd70464146105b05780635392c5e0146105c357600080fd5b8063267822471161035c578063423fa8561161032b578063423fa8561461050e578063456052671461052e578063458c0477146105565780634a1a89a71461056a57600080fd5b8063267822471461047757806329878983146104bc578063383b3be8146104e8578063394218e9146104fb57600080fd5b806315064c961161039857806315064c96146104205780631816b7e51461043d57806319d8ac6114610450578063220d78991461046457600080fd5b80630808270c146103bf5780630a0d9fbe146103d4578063107bf28c1461040b575b600080fd5b6103d26103cd3660046152b9565b610acd565b005b606f546103ed90610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b610413610b80565b60405161040291906153c0565b606f5461042d9060ff1681565b6040519015158152602001610402565b6103d261044b3660046153da565b610c0e565b6073546103ed9067ffffffffffffffff1681565b6104136104723660046153fe565b610d26565b607b546104979073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610402565b6074546104979068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b61042d6104f636600461544b565b610efd565b6103d261050936600461544b565b610f53565b6073546103ed9068010000000000000000900467ffffffffffffffff1681565b6073546103ed90700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103ed9067ffffffffffffffff1681565b6079546103ed9068010000000000000000900467ffffffffffffffff1681565b6103d261059836600461544b565b6110d7565b6103d26105ab36600461544b565b61118a565b6103d26105be366004615466565b61130e565b6105e36105d136600461544b565b60756020526000908152604090205481565b604051908152602001610402565b6104136116a4565b6103d2610607366004615558565b6116b1565b6103d2611ebb565b6105e3611fbb565b6105e361062a36600461544b565b60716020526000908152604090205481565b6103d261064a3660046155ac565b611fd1565b6103d26120a6565b6103d261066536600461544b565b6120ba565b6074546103ed9067ffffffffffffffff1681565b6103ed7f000000000000000000000000000000000000000000000000000000000000000481565b6106ee6106b33660046155c7565b60786020526000908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff9586168152949093166020850152918301526060820152608001610402565b6079546103ed907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6103d261222a565b60335473ffffffffffffffffffffffffffffffffffffffff16610497565b6105e36122f6565b6103d261078636600461544b565b61244f565b6103d261079936600461544b565b6125cb565b6104977f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede81565b6103d26107d3366004615466565b6126d1565b6103d26107e63660046155ac565b612896565b6103ed7f000000000000000000000000000000000000000000000000000000000000044d81565b606f5461082d906901000000000000000000900461ffff1681565b60405161ffff9091168152602001610402565b61088161084e36600461544b565b6072602052600090815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff9283166020850152911690820152606001610402565b6104977f0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb081565b61042d6108dc3660046155c7565b61295a565b6103ed6129e4565b607b546103ed9074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6103d26109233660046156ba565b612a39565b606f54610497906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104977f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb81565b6103d261098c3660046156ef565b612ac6565b6103d261099f3660046157a2565b613012565b6079546103ed90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103d26135b4565b6103d26109e23660046152b9565b61368d565b6073546103ed907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104977f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e981565b6103d2610a4c3660046157e4565b61389d565b607b5461042d907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6103d2610a8c3660046155ac565b613c93565b6103d2610a9f3660046155ac565b613d65565b607a546104979073ffffffffffffffffffffffffffffffffffffffff1681565b6105e360705481565b606f5460ff1615610b0a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b1a8888888888888888613e19565b67ffffffffffffffff85166000908152607560209081526040918290205482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a1610b76614261565b5050505050505050565b60778054610b8d90615830565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb990615830565b8015610c065780601f10610bdb57610100808354040283529160200191610c06565b820191906000526020600020905b815481529060010190602001808311610be957829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610c5f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610c7857506103ff8161ffff16115b15610caf576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086166000818152607260205260408082205493881682529020546060929115801590610d5a575081155b15610d91576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610dc8576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dd18461295a565b610e07576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f000000000000000000000000000000000000000000000000000000000000044d891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000004891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60795467ffffffffffffffff82811660009081526078602052604081205490924292610f4192700100000000000000000000000000000000909204811691166158b2565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610fa4576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610feb576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661105a5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061105a576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610d1b565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461117e57606f5460ff161561113f576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61114881610efd565b61117e576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611187816142e9565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146111db576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611222576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661128d57607b5467ffffffffffffffff7401000000000000000000000000000000000000000090910481169082161061128d576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610d1b565b606f5460ff161561134b576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8681166000908152607260205260409020600101544292611398927801000000000000000000000000000000000000000000000000909104811691166158b2565b67ffffffffffffffff1611156113da576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86113e787876158da565b67ffffffffffffffff161115611429576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611438878787878787876144fc565b611441856148b5565b607954700100000000000000000000000000000000900467ffffffffffffffff1660000361158957607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff878116918217909255600090815260756020526040902084905560795416156114e457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b50505050611659565b611591614a95565b6079805467ffffffffffffffff169060006115ab836158fb565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815288831660208083019182528284018a8152606084018a815260795487166000908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051838152339067ffffffffffffffff8716907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966906020015b60405180910390a350505050505050565b60768054610b8d90615830565b606f5460ff16156116ee576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461174e576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600081900361178a576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156117c6576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff6801000000000000000082048116600081815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611c165760008a8a8381811061182e5761182e615922565b90506020028101906118409190615951565b6118499061598f565b8051805160209091012060608201519192509067ffffffffffffffff16156119c15785611875816158fb565b965050600081836020015184606001516040516020016118cd93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a16600090815260719093529120549091508114611956576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80881660009081526071602052604080822091909155606085015190850151908216911610156119bb576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611afe565b602082015115801590611a88575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303816000875af1158015611a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a869190615a1c565b155b15611abf576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611afe576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611b31575042826040015167ffffffffffffffff16115b15611b68576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611c0e90615a35565b915050611812565b50611c2186856158b2565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611c8a576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c9682856158da565b611caa9067ffffffffffffffff1688615a6d565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d861660008181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611da057607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611df2333083607054611db39190615a86565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb016929190614b46565b611dfa614a95565b7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede73ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e6257600080fd5b505af1158015611e76573d6000803e3d6000fd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce9150600090a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f0c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611f68576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f90600090a1565b60006070546064611fcc9190615a86565b905090565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612022576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610d1b565b6120ae614c28565b6120b86000614ca9565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146122225760006120e36129e4565b90508067ffffffffffffffff168267ffffffffffffffff1611612132576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff6801000000000000000090910481169083161180612178575067ffffffffffffffff80831660009081526072602052604090206001015416155b156121af576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff80831660009081526072602052604090206001015442916121de9162093a8091166158b2565b67ffffffffffffffff161115612220576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b611187614261565b607b5473ffffffffffffffffffffffffffffffffffffffff16331461227b576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb016906370a0823190602401602060405180830381865afa158015612385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a99190615a1c565b905060006123b56129e4565b60735467ffffffffffffffff68010000000000000000820481169161240d91700100000000000000000000000000000000820481169178010000000000000000000000000000000000000000000000009004166158da565b61241791906158b2565b61242191906158da565b67ffffffffffffffff1690508060000361243e5760009250505090565b6124488183615acc565b9250505090565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146124a0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156124e7576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661254e5760795467ffffffffffffffff70010000000000000000000000000000000090910481169082161061254e576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610d1b565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461261c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff161115612663576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610d1b565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461272e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61273d878787878787876144fc565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff878116918217909255600090815260756020526040902084905560795416156127b857607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561284057600080fd5b505af1158015612854573d6000803e3d6000fd5b505060405185815233925067ffffffffffffffff881691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe90602001611693565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146128e7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610d1b565b600067ffffffff0000000167ffffffffffffffff8316108015612992575067ffffffff00000001604083901c67ffffffffffffffff16105b80156129b3575067ffffffff00000001608083901c67ffffffffffffffff16105b80156129ca575067ffffffff0000000160c083901c105b156129d757506001919050565b506000919050565b919050565b60795460009067ffffffffffffffff1615612a28575060795467ffffffffffffffff9081166000908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612a8a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612a968282615b2e565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610d1b91906153c0565b600054610100900460ff1615808015612ae65750600054600160ff909116105b80612b005750303b158015612b00575060005460ff166001145b612b91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612bef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612bfc60208801886155ac565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612c5160408801602089016155ac565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612cb660808801606089016155ac565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790556000805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612d418682615b2e565b506077612d4e8582615b2e565b5062093a80612d636060890160408a0161544b565b67ffffffffffffffff161115612da5576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612db5606088016040890161544b565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612e1760a0890160808a0161544b565b67ffffffffffffffff161115612e59576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e6960a088016080890161544b565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055612f48614d20565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd660007f00000000000000000000000000000000000000000000000000000000000000048585604051612f9e9493929190615c91565b60405180910390a1801561300957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561306f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156130ac576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060008190036130e8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115613124576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161316f918491700100000000000000000000000000000000900416615cc9565b11156131a7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000008204811660008181526072602052604081205491937001000000000000000000000000000000009004909216915b8481101561345157600087878381811061320757613207615922565b90506020028101906132199190615cdc565b61322290615d10565b90508361322e816158fb565b825180516020918201208185015160408087015190519499509194506000936132909386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8916600090815260719093529120549091508114613319576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff861660009081526071602052604081205561333e600189615a6d565b84036133ad5742607b60149054906101000a900467ffffffffffffffff16846040015161336b91906158b2565b67ffffffffffffffff1611156133ad576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061344990615a35565b9150506131eb565b5061345c84846158b2565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589166000818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613605576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede73ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561366d57600080fd5b505af1158015613681573d6000803e3d6000fd5b505050506120b8614dc0565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146136ea576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136fa8888888888888888613e19565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8781169182179092556000908152607560205260409020849055607954161561377557607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018590527f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b1580156137fd57600080fd5b505af1158015613811573d6000803e3d6000fd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051838152339067ffffffffffffffff8716907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a35050505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16156138fa576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613937576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613941611fbb565b90508181111561397d576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113888311156139b9576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6139fb73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb016333084614b46565b60007f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8c9190615a1c565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613ac6836158fb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613afd929190615d8c565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660009081526071909352912055323303613c2d57607354604080518381523360208201526060918101829052600091810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c8c565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c839493929190615d9c565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613ce4576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610d1b565b613d6d614c28565b73ffffffffffffffffffffffffffffffffffffffff8116613e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612b88565b61118781614ca9565b600067ffffffffffffffff891615613ee75760795467ffffffffffffffff908116908a161115613e75576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8089166000908152607860205260409020600281015481549092898116680100000000000000009092041614613ee1576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f83565b5067ffffffffffffffff861660009081526075602052604090205480613f39576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169088161115613f83576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff9081169089161180613fb557508867ffffffffffffffff168867ffffffffffffffff1611155b80613fdc575060795467ffffffffffffffff68010000000000000000909104811690891611155b15614013576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff888116600090815260786020526040902054680100000000000000009004811690871614614076576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006140858888888589610d26565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516140ba9190615dd2565b602060405180830381855afa1580156140d7573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906140fa9190615a1c565b6141049190615de4565b6040805160208101825282815290517f8d8f8a5c00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e91691638d8f8a5c916141879189918991600401615df8565b602060405180830381865afa1580156141a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141c89190615e40565b6141fe576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8a16600090815260786020526040902060020154869003614254576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede73ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156142c957600080fd5b505af11580156142dd573d6000803e3d6000fd5b505050506120b8614e4f565b60795467ffffffffffffffff680100000000000000009091048116908216111580614323575060795467ffffffffffffffff908116908216115b1561435a576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff818116600081815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb73ffffffffffffffffffffffffffffffffffffffff16906333d6247d90602401600060405180830381600087803b15801561448c57600080fd5b505af11580156144a0573d6000803e3d6000fd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516144ef91815260200190565b60405180910390a3505050565b6000806145076129e4565b905067ffffffffffffffff8916156145d75760795467ffffffffffffffff908116908a161115614563576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808a1660009081526078602052604090206002810154815490945090918a81166801000000000000000090920416146145d1576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614678565b67ffffffffffffffff881660009081526075602052604090205491508161462a576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff161115614678576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff16116146c5576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006146d4898989868a610d26565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516147099190615dd2565b602060405180830381855afa158015614726573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906147499190615a1c565b6147539190615de4565b6040805160208101825282815290517f8d8f8a5c00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e91691638d8f8a5c916147d6918a918a91600401615df8565b602060405180830381865afa1580156147f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148179190615e40565b61484d576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142543361485b858c6158da565b67ffffffffffffffff1661486d6122f6565b6148779190615a86565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb0169190614ee2565b60006148bf6129e4565b9050816000806148cf84846158da565b606f5467ffffffffffffffff91821692506000916148f39161010090041642615a6d565b90505b8467ffffffffffffffff168467ffffffffffffffff161461497e5767ffffffffffffffff8085166000908152607260205260409020600181015490911682101561495c57600181015468010000000000000000900467ffffffffffffffff169450614978565b61496686866158da565b67ffffffffffffffff1693505061497e565b506148f6565b600061498a8484615a6d565b9050838110156149e157808403600c81116149a557806149a8565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816149d7576149d7615a9d565b0460705550614a51565b838103600c81116149f257806149f5565b600c5b90506000816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a2c57614a2c615a9d565b04905080607054670de0b6b3a76400000281614a4a57614a4a615a9d565b0460705550505b683635c9adc5dea000006070541115614a7657683635c9adc5dea00000607055613009565b633b9aca00607054101561300957633b9aca0060705550505050505050565b60795467ffffffffffffffff6801000000000000000082048116911611156120b857607954600090614ade9068010000000000000000900467ffffffffffffffff1660016158b2565b9050614ae981610efd565b1561118757607954600090600290614b0c90849067ffffffffffffffff166158da565b614b169190615e62565b614b2090836158b2565b9050614b2b81610efd565b15614b3d57614b39816142e9565b5050565b614b39826142e9565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052614c229085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614f3d565b50505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146120b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612b88565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16614db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612b88565b6120b833614ca9565b606f5460ff16614dfc576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b606f5460ff1615614e8c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614f389084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401614ba0565b505050565b6000614f9f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166150499092919063ffffffff16565b805190915015614f385780806020019051810190614fbd9190615e40565b614f38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612b88565b60606150588484600085615060565b949350505050565b6060824710156150f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612b88565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161511b9190615dd2565b60006040518083038185875af1925050503d8060008114615158576040519150601f19603f3d011682016040523d82523d6000602084013e61515d565b606091505b509150915061516e87838387615179565b979650505050505050565b6060831561520f5782516000036152085773ffffffffffffffffffffffffffffffffffffffff85163b615208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612b88565b5081615058565b61505883838151156152245781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b8891906153c0565b803567ffffffffffffffff811681146129df57600080fd5b60008083601f84011261528257600080fd5b50813567ffffffffffffffff81111561529a57600080fd5b6020830191508360208285010111156152b257600080fd5b9250929050565b60008060008060008060008060e0898b0312156152d557600080fd5b6152de89615258565b97506152ec60208a01615258565b96506152fa60408a01615258565b955061530860608a01615258565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561533257600080fd5b61533e8b828c01615270565b999c989b5096995094979396929594505050565b60005b8381101561536d578181015183820152602001615355565b50506000910152565b6000815180845261538e816020860160208601615352565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006153d36020830184615376565b9392505050565b6000602082840312156153ec57600080fd5b813561ffff811681146153d357600080fd5b600080600080600060a0868803121561541657600080fd5b61541f86615258565b945061542d60208701615258565b94979496505050506040830135926060810135926080909101359150565b60006020828403121561545d57600080fd5b6153d382615258565b600080600080600080600060c0888a03121561548157600080fd5b61548a88615258565b965061549860208901615258565b95506154a660408901615258565b9450606088013593506080880135925060a088013567ffffffffffffffff8111156154d057600080fd5b6154dc8a828b01615270565b989b979a50959850939692959293505050565b60008083601f84011261550157600080fd5b50813567ffffffffffffffff81111561551957600080fd5b6020830191508360208260051b85010111156152b257600080fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146129df57600080fd5b60008060006040848603121561556d57600080fd5b833567ffffffffffffffff81111561558457600080fd5b615590868287016154ef565b90945092506155a3905060208501615534565b90509250925092565b6000602082840312156155be57600080fd5b6153d382615534565b6000602082840312156155d957600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261562057600080fd5b813567ffffffffffffffff8082111561563b5761563b6155e0565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615681576156816155e0565b8160405283815286602085880101111561569a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156156cc57600080fd5b813567ffffffffffffffff8111156156e357600080fd5b6150588482850161560f565b60008060008060008086880361012081121561570a57600080fd5b60a081121561571857600080fd5b5086955060a0870135945060c087013567ffffffffffffffff8082111561573e57600080fd5b61574a8a838b0161560f565b955060e089013591508082111561576057600080fd5b61576c8a838b0161560f565b945061010089013591508082111561578357600080fd5b5061579089828a01615270565b979a9699509497509295939492505050565b600080602083850312156157b557600080fd5b823567ffffffffffffffff8111156157cc57600080fd5b6157d8858286016154ef565b90969095509350505050565b6000806000604084860312156157f957600080fd5b833567ffffffffffffffff81111561581057600080fd5b61581c86828701615270565b909790965060209590950135949350505050565b600181811c9082168061584457607f821691505b60208210810361587d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156158d3576158d3615883565b5092915050565b67ffffffffffffffff8281168282160390808211156158d3576158d3615883565b600067ffffffffffffffff80831681810361591857615918615883565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261598557600080fd5b9190910192915050565b6000608082360312156159a157600080fd5b6040516080810167ffffffffffffffff82821081831117156159c5576159c56155e0565b8160405284359150808211156159da57600080fd5b506159e73682860161560f565b82525060208301356020820152615a0060408401615258565b6040820152615a1160608401615258565b606082015292915050565b600060208284031215615a2e57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a6657615a66615883565b5060010190565b81810381811115615a8057615a80615883565b92915050565b8082028115828204841417615a8057615a80615883565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615adb57615adb615a9d565b500490565b601f821115614f3857600081815260208120601f850160051c81016020861015615b075750805b601f850160051c820191505b81811015615b2657828155600101615b13565b505050505050565b815167ffffffffffffffff811115615b4857615b486155e0565b615b5c81615b568454615830565b84615ae0565b602080601f831160018114615baf5760008415615b795750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555615b26565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615bfc57888601518255948401946001909101908401615bdd565b5085821015615c3857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600067ffffffffffffffff808716835280861660208401525060606040830152615cbf606083018486615c48565b9695505050505050565b80820180821115615a8057615a80615883565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261598557600080fd5b600060608236031215615d2257600080fd5b6040516060810167ffffffffffffffff8282108183111715615d4657615d466155e0565b816040528435915080821115615d5b57600080fd5b50615d683682860161560f565b82525060208301356020820152615d8160408401615258565b604082015292915050565b8183823760009101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201526000615cbf606083018486615c48565b60008251615985818460208701615352565b600082615df357615df3615a9d565b500690565b604081526000615e0c604083018587615c48565b905060208083018460005b6001811015615e3457815183529183019190830190600101615e17565b50505050949350505050565b600060208284031215615e5257600080fd5b815180151581146153d357600080fd5b600067ffffffffffffffff80841680615e7d57615e7d615a9d565b9216919091049291505056fea2646970667358221220445ad406e7775b9ae031e5588d654f761118a1b49e4f965aa3fa3f7fbaeb46ac64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb00000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e90000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede000000000000000000000000000000000000000000000000000000000000044d0000000000000000000000000000000000000000000000000000000000000004
-----Decoded View---------------
Arg [0] : _globalExitRootManager (address): 0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb
Arg [1] : _matic (address): 0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0
Arg [2] : _rollupVerifier (address): 0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9
Arg [3] : _bridgeAddress (address): 0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe
Arg [4] : _chainID (uint64): 1101
Arg [5] : _forkID (uint64): 4
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000580bda1e7a0cfae92fa7f6c20a3794f169ce3cfb
Arg [1] : 0000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb0
Arg [2] : 0000000000000000000000004f9a0e7fd2bf6067db6994cf12e4495df938e6e9
Arg [3] : 0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede
Arg [4] : 000000000000000000000000000000000000000000000000000000000000044d
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000004
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.