Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21080758 | 107 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ExecutorFacet
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 9999999 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol"; import {COMMIT_TIMESTAMP_NOT_OLDER, COMMIT_TIMESTAMP_APPROXIMATION_DELTA, EMPTY_STRING_KECCAK, L2_TO_L1_LOG_SERIALIZE_SIZE, MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES, PACKED_L2_BLOCK_TIMESTAMP_MASK, PUBLIC_INPUT_SHIFT, POINT_EVALUATION_PRECOMPILE_ADDR} from "../../../common/Config.sol"; import {IExecutor, L2_LOG_ADDRESS_OFFSET, L2_LOG_KEY_OFFSET, L2_LOG_VALUE_OFFSET, SystemLogKey, LogProcessingOutput, PubdataSource, BLS_MODULUS, PUBDATA_COMMITMENT_SIZE, PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET, PUBDATA_COMMITMENT_COMMITMENT_OFFSET, MAX_NUMBER_OF_BLOBS, TOTAL_BLOBS_IN_COMMITMENT, BLOB_SIZE_BYTES} from "../../chain-interfaces/IExecutor.sol"; import {PriorityQueue, PriorityOperation} from "../../libraries/PriorityQueue.sol"; import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol"; import {UnsafeBytes} from "../../../common/libraries/UnsafeBytes.sol"; import {L2_BOOTLOADER_ADDRESS, L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, L2_PUBDATA_CHUNK_PUBLISHER_ADDR} from "../../../common/L2ContractAddresses.sol"; import {PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol"; import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; import {BatchNumberMismatch, TimeNotReached, TooManyBlobs, ValueMismatch, InvalidPubdataMode, InvalidPubdataLength, HashMismatch, NonIncreasingTimestamp, TimestampError, InvalidLogSender, TxHashMismatch, UnexpectedSystemLog, MissingSystemLogs, LogAlreadyProcessed, InvalidProtocolVersion, CanOnlyProcessOneBatch, BatchHashMismatch, UpgradeBatchNumberIsNotZero, NonSequentialBatch, CantExecuteUnprovenBatches, SystemLogsSizeTooBig, InvalidNumberOfBlobs, VerifiedBatchesExceedsCommittedBatches, InvalidProof, RevertedBatchNotAfterNewLastBatch, CantRevertExecutedBatch, PointEvalFailed, EmptyBlobVersionHash, NonEmptyBlobVersionHash, BlobHashCommitmentError, CalldataLengthTooBig, InvalidPubdataHash, L2TimestampTooBig, PriorityOperationsRollingHashMismatch, PubdataCommitmentsEmpty, PointEvalCallFailed, PubdataCommitmentsTooBig, InvalidPubdataCommitmentsSize} from "../../../common/L1ContractErrors.sol"; // While formally the following import is not used, it is needed to inherit documentation from it import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol"; /// @title ZKsync hyperchain Executor contract capable of processing events emitted in the ZKsync hyperchain protocol. /// @author Matter Labs /// @custom:security-contact [email protected] contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { using UncheckedMath for uint256; using PriorityQueue for PriorityQueue.Queue; /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "ExecutorFacet"; /// @dev Process one batch commit using the previous batch StoredBatchInfo /// @dev returns new batch StoredBatchInfo /// @notice Does not change storage function _commitOneBatch( StoredBatchInfo memory _previousBatch, CommitBatchInfo calldata _newBatch, bytes32 _expectedSystemContractUpgradeTxHash ) internal view returns (StoredBatchInfo memory) { // only commit next batch if (_newBatch.batchNumber != _previousBatch.batchNumber + 1) { revert BatchNumberMismatch(_previousBatch.batchNumber + 1, _newBatch.batchNumber); } uint8 pubdataSource = uint8(bytes1(_newBatch.pubdataCommitments[0])); PubdataPricingMode pricingMode = s.feeParams.pubdataPricingMode; if ( pricingMode != PubdataPricingMode.Validium && pubdataSource != uint8(PubdataSource.Calldata) && pubdataSource != uint8(PubdataSource.Blob) ) { revert InvalidPubdataMode(); } // Check that batch contain all meta information for L2 logs. // Get the chained hash of priority transaction hashes. LogProcessingOutput memory logOutput = _processL2Logs(_newBatch, _expectedSystemContractUpgradeTxHash); bytes32[] memory blobCommitments = new bytes32[](MAX_NUMBER_OF_BLOBS); if (pricingMode == PubdataPricingMode.Validium) { // skipping data validation for validium, we just check that the data is empty if (_newBatch.pubdataCommitments.length != 1) { revert CalldataLengthTooBig(); } for (uint8 i = uint8(SystemLogKey.BLOB_ONE_HASH_KEY); i <= uint8(SystemLogKey.BLOB_SIX_HASH_KEY); ++i) { logOutput.blobHashes[i - uint8(SystemLogKey.BLOB_ONE_HASH_KEY)] = bytes32(0); } } else if (pubdataSource == uint8(PubdataSource.Blob)) { // In this scenario, pubdataCommitments is a list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes)) = 144 bytes blobCommitments = _verifyBlobInformation(_newBatch.pubdataCommitments[1:], logOutput.blobHashes); } else if (pubdataSource == uint8(PubdataSource.Calldata)) { // In this scenario pubdataCommitments is actual pubdata consisting of l2 to l1 logs, l2 to l1 message, compressed smart contract bytecode, and compressed state diffs if (_newBatch.pubdataCommitments.length > BLOB_SIZE_BYTES) { revert InvalidPubdataLength(); } bytes32 pubdataHash = keccak256(_newBatch.pubdataCommitments[1:_newBatch.pubdataCommitments.length - 32]); if (logOutput.pubdataHash != pubdataHash) { revert InvalidPubdataHash(pubdataHash, logOutput.pubdataHash); } blobCommitments[0] = bytes32( _newBatch.pubdataCommitments[_newBatch.pubdataCommitments.length - 32:_newBatch .pubdataCommitments .length] ); } if (_previousBatch.batchHash != logOutput.previousBatchHash) { revert HashMismatch(logOutput.previousBatchHash, _previousBatch.batchHash); } // Check that the priority operation hash in the L2 logs is as expected if (logOutput.chainedPriorityTxsHash != _newBatch.priorityOperationsHash) { revert HashMismatch(logOutput.chainedPriorityTxsHash, _newBatch.priorityOperationsHash); } // Check that the number of processed priority operations is as expected if (logOutput.numberOfLayer1Txs != _newBatch.numberOfLayer1Txs) { revert ValueMismatch(logOutput.numberOfLayer1Txs, _newBatch.numberOfLayer1Txs); } // Check the timestamp of the new batch _verifyBatchTimestamp(logOutput.packedBatchAndL2BlockTimestamp, _newBatch.timestamp, _previousBatch.timestamp); // Create batch commitment for the proof verification bytes32 commitment = _createBatchCommitment( _newBatch, logOutput.stateDiffHash, blobCommitments, logOutput.blobHashes ); return StoredBatchInfo({ batchNumber: _newBatch.batchNumber, batchHash: _newBatch.newStateRoot, indexRepeatedStorageChanges: _newBatch.indexRepeatedStorageChanges, numberOfLayer1Txs: _newBatch.numberOfLayer1Txs, priorityOperationsHash: _newBatch.priorityOperationsHash, l2LogsTreeRoot: logOutput.l2LogsTreeRoot, timestamp: _newBatch.timestamp, commitment: commitment }); } /// @notice checks that the timestamps of both the new batch and the new L2 block are correct. /// @param _packedBatchAndL2BlockTimestamp - packed batch and L2 block timestamp in a format of batchTimestamp * 2**128 + l2BatchTimestamp /// @param _expectedBatchTimestamp - expected batch timestamp /// @param _previousBatchTimestamp - the timestamp of the previous batch function _verifyBatchTimestamp( uint256 _packedBatchAndL2BlockTimestamp, uint256 _expectedBatchTimestamp, uint256 _previousBatchTimestamp ) internal view { // Check that the timestamp that came from the system context is expected uint256 batchTimestamp = _packedBatchAndL2BlockTimestamp >> 128; if (batchTimestamp != _expectedBatchTimestamp) { revert TimestampError(); } // While the fact that _previousBatchTimestamp < batchTimestamp is already checked on L2, // we double check it here for clarity if (_previousBatchTimestamp >= batchTimestamp) { revert NonIncreasingTimestamp(); } uint256 lastL2BlockTimestamp = _packedBatchAndL2BlockTimestamp & PACKED_L2_BLOCK_TIMESTAMP_MASK; // All L2 blocks have timestamps within the range of [batchTimestamp, lastL2BlockTimestamp]. // So here we need to only double check that: // - The timestamp of the batch is not too small. // - The timestamp of the last L2 block is not too big. // New batch timestamp is too small if (block.timestamp - COMMIT_TIMESTAMP_NOT_OLDER > batchTimestamp) { revert TimeNotReached(batchTimestamp, block.timestamp - COMMIT_TIMESTAMP_NOT_OLDER); } // The last L2 block timestamp is too big if (lastL2BlockTimestamp > block.timestamp + COMMIT_TIMESTAMP_APPROXIMATION_DELTA) { revert L2TimestampTooBig(); } } /// @dev Check that L2 logs are proper and batch contain all meta information for them /// @dev The logs processed here should line up such that only one log for each key from the /// SystemLogKey enum in Constants.sol is processed per new batch. /// @dev Data returned from here will be used to form the batch commitment. function _processL2Logs( CommitBatchInfo calldata _newBatch, bytes32 _expectedSystemContractUpgradeTxHash ) internal pure returns (LogProcessingOutput memory logOutput) { // Copy L2 to L1 logs into memory. bytes memory emittedL2Logs = _newBatch.systemLogs; logOutput.blobHashes = new bytes32[](MAX_NUMBER_OF_BLOBS); // Used as bitmap to set/check log processing happens exactly once. // See SystemLogKey enum in Constants.sol for ordering. uint256 processedLogs = 0; // linear traversal of the logs uint256 logsLength = emittedL2Logs.length; for (uint256 i = 0; i < logsLength; i = i.uncheckedAdd(L2_TO_L1_LOG_SERIALIZE_SIZE)) { // Extract the values to be compared to/used such as the log sender, key, and value // slither-disable-next-line unused-return (address logSender, ) = UnsafeBytes.readAddress(emittedL2Logs, i + L2_LOG_ADDRESS_OFFSET); // slither-disable-next-line unused-return (uint256 logKey, ) = UnsafeBytes.readUint256(emittedL2Logs, i + L2_LOG_KEY_OFFSET); // slither-disable-next-line unused-return (bytes32 logValue, ) = UnsafeBytes.readBytes32(emittedL2Logs, i + L2_LOG_VALUE_OFFSET); // Ensure that the log hasn't been processed already if (_checkBit(processedLogs, uint8(logKey))) { revert LogAlreadyProcessed(uint8(logKey)); } processedLogs = _setBit(processedLogs, uint8(logKey)); // Need to check that each log was sent by the correct address. if (logKey == uint256(SystemLogKey.L2_TO_L1_LOGS_TREE_ROOT_KEY)) { if (logSender != L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR) { revert InvalidLogSender(logSender, logKey); } logOutput.l2LogsTreeRoot = logValue; } else if (logKey == uint256(SystemLogKey.TOTAL_L2_TO_L1_PUBDATA_KEY)) { if (logSender != L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR) { revert InvalidLogSender(logSender, logKey); } logOutput.pubdataHash = logValue; } else if (logKey == uint256(SystemLogKey.STATE_DIFF_HASH_KEY)) { if (logSender != L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR) { revert InvalidLogSender(logSender, logKey); } logOutput.stateDiffHash = logValue; } else if (logKey == uint256(SystemLogKey.PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY)) { if (logSender != L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR) { revert InvalidLogSender(logSender, logKey); } logOutput.packedBatchAndL2BlockTimestamp = uint256(logValue); } else if (logKey == uint256(SystemLogKey.PREV_BATCH_HASH_KEY)) { if (logSender != L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR) { revert InvalidLogSender(logSender, logKey); } logOutput.previousBatchHash = logValue; } else if (logKey == uint256(SystemLogKey.CHAINED_PRIORITY_TXN_HASH_KEY)) { if (logSender != L2_BOOTLOADER_ADDRESS) { revert InvalidLogSender(logSender, logKey); } logOutput.chainedPriorityTxsHash = logValue; } else if (logKey == uint256(SystemLogKey.NUMBER_OF_LAYER_1_TXS_KEY)) { if (logSender != L2_BOOTLOADER_ADDRESS) { revert InvalidLogSender(logSender, logKey); } logOutput.numberOfLayer1Txs = uint256(logValue); } else if ( logKey >= uint256(SystemLogKey.BLOB_ONE_HASH_KEY) && logKey <= uint256(SystemLogKey.BLOB_SIX_HASH_KEY) ) { if (logSender != L2_PUBDATA_CHUNK_PUBLISHER_ADDR) { revert InvalidLogSender(logSender, logKey); } uint8 blobNumber = uint8(logKey) - uint8(SystemLogKey.BLOB_ONE_HASH_KEY); if (blobNumber >= MAX_NUMBER_OF_BLOBS) { revert TooManyBlobs(); } logOutput.blobHashes[blobNumber] = logValue; } else if (logKey == uint256(SystemLogKey.EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY)) { if (logSender != L2_BOOTLOADER_ADDRESS) { revert InvalidLogSender(logSender, logKey); } if (_expectedSystemContractUpgradeTxHash != logValue) { revert TxHashMismatch(); } } else if (logKey > uint256(SystemLogKey.EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY)) { revert UnexpectedSystemLog(logKey); } } // We only require 13 logs to be checked, the 14th is if we are expecting a protocol upgrade // Without the protocol upgrade we expect 13 logs: 2^13 - 1 = 8191 // With the protocol upgrade we expect 14 logs: 2^14 - 1 = 16383 if (_expectedSystemContractUpgradeTxHash == bytes32(0)) { if (processedLogs != 8191) { revert MissingSystemLogs(8191, processedLogs); } } else { if (processedLogs != 16383) { revert MissingSystemLogs(16383, processedLogs); } } } /// @inheritdoc IExecutor function commitBatches( StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external nonReentrant onlyValidator { _commitBatches(_lastCommittedBatchData, _newBatchesData); } /// @inheritdoc IExecutor function commitBatchesSharedBridge( uint256, // _chainId StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external nonReentrant onlyValidator { _commitBatches(_lastCommittedBatchData, _newBatchesData); } function _commitBatches( StoredBatchInfo memory _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) internal { // check that we have the right protocol version // three comments: // 1. A chain has to keep their protocol version up to date, as processing a block requires the latest or previous protocol version // to solve this we will need to add the feature to create batches with only the protocol upgrade tx, without any other txs. // 2. A chain might become out of sync if it launches while we are in the middle of a protocol upgrade. This would mean they cannot process their genesis upgrade // as their protocolversion would be outdated, and they also cannot process the protocol upgrade tx as they have a pending upgrade. // 3. The protocol upgrade is increased in the BaseZkSyncUpgrade, in the executor only the systemContractsUpgradeTxHash is checked if (!IStateTransitionManager(s.stateTransitionManager).protocolVersionIsActive(s.protocolVersion)) { revert InvalidProtocolVersion(); } // With the new changes for EIP-4844, namely the restriction on number of blobs per block, we only allow for a single batch to be committed at a time. if (_newBatchesData.length != 1) { revert CanOnlyProcessOneBatch(); } // Check that we commit batches after last committed batch if (s.storedBatchHashes[s.totalBatchesCommitted] != _hashStoredBatchInfo(_lastCommittedBatchData)) { // incorrect previous batch data revert BatchHashMismatch( s.storedBatchHashes[s.totalBatchesCommitted], _hashStoredBatchInfo(_lastCommittedBatchData) ); } bytes32 systemContractsUpgradeTxHash = s.l2SystemContractsUpgradeTxHash; // Upgrades are rarely done so we optimize a case with no active system contracts upgrade. if (systemContractsUpgradeTxHash == bytes32(0) || s.l2SystemContractsUpgradeBatchNumber != 0) { _commitBatchesWithoutSystemContractsUpgrade(_lastCommittedBatchData, _newBatchesData); } else { _commitBatchesWithSystemContractsUpgrade( _lastCommittedBatchData, _newBatchesData, systemContractsUpgradeTxHash ); } s.totalBatchesCommitted = s.totalBatchesCommitted + _newBatchesData.length; } /// @dev Commits new batches without any system contracts upgrade. /// @param _lastCommittedBatchData The data of the last committed batch. /// @param _newBatchesData An array of batch data that needs to be committed. function _commitBatchesWithoutSystemContractsUpgrade( StoredBatchInfo memory _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) internal { // We disable this check because calldata array length is cheap. // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _newBatchesData.length; i = i.uncheckedInc()) { _lastCommittedBatchData = _commitOneBatch(_lastCommittedBatchData, _newBatchesData[i], bytes32(0)); s.storedBatchHashes[_lastCommittedBatchData.batchNumber] = _hashStoredBatchInfo(_lastCommittedBatchData); emit BlockCommit( _lastCommittedBatchData.batchNumber, _lastCommittedBatchData.batchHash, _lastCommittedBatchData.commitment ); } } /// @dev Commits new batches with a system contracts upgrade transaction. /// @param _lastCommittedBatchData The data of the last committed batch. /// @param _newBatchesData An array of batch data that needs to be committed. /// @param _systemContractUpgradeTxHash The transaction hash of the system contract upgrade. function _commitBatchesWithSystemContractsUpgrade( StoredBatchInfo memory _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData, bytes32 _systemContractUpgradeTxHash ) internal { // The system contract upgrade is designed to be executed atomically with the new bootloader, a default account, // ZKP verifier, and other system parameters. Hence, we ensure that the upgrade transaction is // carried out within the first batch committed after the upgrade. // While the logic of the contract ensures that the s.l2SystemContractsUpgradeBatchNumber is 0 when this function is called, // this check is added just in case. Since it is a hot read, it does not incur noticeable gas cost. if (s.l2SystemContractsUpgradeBatchNumber != 0) { revert UpgradeBatchNumberIsNotZero(); } // Save the batch number where the upgrade transaction was executed. s.l2SystemContractsUpgradeBatchNumber = _newBatchesData[0].batchNumber; // We disable this check because calldata array length is cheap. // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _newBatchesData.length; i = i.uncheckedInc()) { // The upgrade transaction must only be included in the first batch. bytes32 expectedUpgradeTxHash = i == 0 ? _systemContractUpgradeTxHash : bytes32(0); _lastCommittedBatchData = _commitOneBatch( _lastCommittedBatchData, _newBatchesData[i], expectedUpgradeTxHash ); s.storedBatchHashes[_lastCommittedBatchData.batchNumber] = _hashStoredBatchInfo(_lastCommittedBatchData); emit BlockCommit( _lastCommittedBatchData.batchNumber, _lastCommittedBatchData.batchHash, _lastCommittedBatchData.commitment ); } } /// @dev Pops the priority operations from the priority queue and returns a rolling hash of operations function _collectOperationsFromPriorityQueue(uint256 _nPriorityOps) internal returns (bytes32 concatHash) { concatHash = EMPTY_STRING_KECCAK; for (uint256 i = 0; i < _nPriorityOps; i = i.uncheckedInc()) { PriorityOperation memory priorityOp = s.priorityQueue.popFront(); concatHash = keccak256(abi.encode(concatHash, priorityOp.canonicalTxHash)); } } /// @dev Executes one batch /// @dev 1. Processes all pending operations (Complete priority requests) /// @dev 2. Finalizes batch on Ethereum /// @dev _executedBatchIdx is an index in the array of the batches that we want to execute together function _executeOneBatch(StoredBatchInfo memory _storedBatch, uint256 _executedBatchIdx) internal { uint256 currentBatchNumber = _storedBatch.batchNumber; if (currentBatchNumber != s.totalBatchesExecuted + _executedBatchIdx + 1) { revert NonSequentialBatch(); } if (_hashStoredBatchInfo(_storedBatch) != s.storedBatchHashes[currentBatchNumber]) { revert BatchHashMismatch(s.storedBatchHashes[currentBatchNumber], _hashStoredBatchInfo(_storedBatch)); } bytes32 priorityOperationsHash = _collectOperationsFromPriorityQueue(_storedBatch.numberOfLayer1Txs); if (priorityOperationsHash != _storedBatch.priorityOperationsHash) { revert PriorityOperationsRollingHashMismatch(); } // Save root hash of L2 -> L1 logs tree s.l2LogsRootHashes[currentBatchNumber] = _storedBatch.l2LogsTreeRoot; } /// @inheritdoc IExecutor function executeBatchesSharedBridge( uint256, StoredBatchInfo[] calldata _batchesData ) external nonReentrant onlyValidator { _executeBatches(_batchesData); } /// @inheritdoc IExecutor function executeBatches(StoredBatchInfo[] calldata _batchesData) external nonReentrant onlyValidator { _executeBatches(_batchesData); } function _executeBatches(StoredBatchInfo[] calldata _batchesData) internal { uint256 nBatches = _batchesData.length; for (uint256 i = 0; i < nBatches; i = i.uncheckedInc()) { _executeOneBatch(_batchesData[i], i); emit BlockExecution(_batchesData[i].batchNumber, _batchesData[i].batchHash, _batchesData[i].commitment); } uint256 newTotalBatchesExecuted = s.totalBatchesExecuted + nBatches; s.totalBatchesExecuted = newTotalBatchesExecuted; if (newTotalBatchesExecuted > s.totalBatchesVerified) { revert CantExecuteUnprovenBatches(); } uint256 batchWhenUpgradeHappened = s.l2SystemContractsUpgradeBatchNumber; if (batchWhenUpgradeHappened != 0 && batchWhenUpgradeHappened <= newTotalBatchesExecuted) { delete s.l2SystemContractsUpgradeTxHash; delete s.l2SystemContractsUpgradeBatchNumber; } } /// @inheritdoc IExecutor function proveBatches( StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) external nonReentrant onlyValidator { _proveBatches(_prevBatch, _committedBatches, _proof); } /// @inheritdoc IExecutor function proveBatchesSharedBridge( uint256, // _chainId StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) external nonReentrant onlyValidator { _proveBatches(_prevBatch, _committedBatches, _proof); } function _proveBatches( StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) internal { // Save the variables into the stack to save gas on reading them later uint256 currentTotalBatchesVerified = s.totalBatchesVerified; uint256 committedBatchesLength = _committedBatches.length; // Initialize the array, that will be used as public input to the ZKP uint256[] memory proofPublicInput = new uint256[](committedBatchesLength); // Check that the batch passed by the validator is indeed the first unverified batch if (_hashStoredBatchInfo(_prevBatch) != s.storedBatchHashes[currentTotalBatchesVerified]) { revert BatchHashMismatch( s.storedBatchHashes[currentTotalBatchesVerified], _hashStoredBatchInfo(_prevBatch) ); } bytes32 prevBatchCommitment = _prevBatch.commitment; for (uint256 i = 0; i < committedBatchesLength; i = i.uncheckedInc()) { currentTotalBatchesVerified = currentTotalBatchesVerified.uncheckedInc(); if (_hashStoredBatchInfo(_committedBatches[i]) != s.storedBatchHashes[currentTotalBatchesVerified]) { revert BatchHashMismatch( s.storedBatchHashes[currentTotalBatchesVerified], _hashStoredBatchInfo(_committedBatches[i]) ); } bytes32 currentBatchCommitment = _committedBatches[i].commitment; proofPublicInput[i] = _getBatchProofPublicInput(prevBatchCommitment, currentBatchCommitment); prevBatchCommitment = currentBatchCommitment; } if (currentTotalBatchesVerified > s.totalBatchesCommitted) { revert VerifiedBatchesExceedsCommittedBatches(); } _verifyProof(proofPublicInput, _proof); emit BlocksVerification(s.totalBatchesVerified, currentTotalBatchesVerified); s.totalBatchesVerified = currentTotalBatchesVerified; } function _verifyProof(uint256[] memory proofPublicInput, ProofInput calldata _proof) internal view { // We can only process 1 batch proof at a time. if (proofPublicInput.length != 1) { revert CanOnlyProcessOneBatch(); } bool successVerifyProof = s.verifier.verify( proofPublicInput, _proof.serializedProof, _proof.recursiveAggregationInput ); if (!successVerifyProof) { revert InvalidProof(); } } /// @dev Gets zk proof public input function _getBatchProofPublicInput( bytes32 _prevBatchCommitment, bytes32 _currentBatchCommitment ) internal pure returns (uint256) { return uint256(keccak256(abi.encodePacked(_prevBatchCommitment, _currentBatchCommitment))) >> PUBLIC_INPUT_SHIFT; } /// @inheritdoc IExecutor function revertBatches(uint256 _newLastBatch) external nonReentrant onlyValidatorOrStateTransitionManager { _revertBatches(_newLastBatch); } /// @inheritdoc IExecutor function revertBatchesSharedBridge(uint256, uint256 _newLastBatch) external nonReentrant onlyValidator { _revertBatches(_newLastBatch); } function _revertBatches(uint256 _newLastBatch) internal { if (s.totalBatchesCommitted <= _newLastBatch) { revert RevertedBatchNotAfterNewLastBatch(); } if (_newLastBatch < s.totalBatchesExecuted) { revert CantRevertExecutedBatch(); } if (_newLastBatch < s.totalBatchesVerified) { s.totalBatchesVerified = _newLastBatch; } s.totalBatchesCommitted = _newLastBatch; // Reset the batch number of the executed system contracts upgrade transaction if the batch // where the system contracts upgrade was committed is among the reverted batches. if (s.l2SystemContractsUpgradeBatchNumber > _newLastBatch) { delete s.l2SystemContractsUpgradeBatchNumber; } emit BlocksRevert(s.totalBatchesCommitted, s.totalBatchesVerified, s.totalBatchesExecuted); } /// @dev Creates batch commitment from its data function _createBatchCommitment( CommitBatchInfo calldata _newBatchData, bytes32 _stateDiffHash, bytes32[] memory _blobCommitments, bytes32[] memory _blobHashes ) internal view returns (bytes32) { bytes32 passThroughDataHash = keccak256(_batchPassThroughData(_newBatchData)); bytes32 metadataHash = keccak256(_batchMetaParameters()); bytes32 auxiliaryOutputHash = keccak256( _batchAuxiliaryOutput(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes) ); return keccak256(abi.encode(passThroughDataHash, metadataHash, auxiliaryOutputHash)); } function _batchPassThroughData(CommitBatchInfo calldata _batch) internal pure returns (bytes memory) { return abi.encodePacked( // solhint-disable-next-line func-named-parameters _batch.indexRepeatedStorageChanges, _batch.newStateRoot, uint64(0), // index repeated storage changes in zkPorter bytes32(0) // zkPorter batch hash ); } function _batchMetaParameters() internal view returns (bytes memory) { bytes32 l2DefaultAccountBytecodeHash = s.l2DefaultAccountBytecodeHash; return abi.encodePacked( s.zkPorterIsAvailable, s.l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, // VM 1.5.0 requires us to pass the EVM simulator code hash. For now it is the same as the default account. l2DefaultAccountBytecodeHash ); } function _batchAuxiliaryOutput( CommitBatchInfo calldata _batch, bytes32 _stateDiffHash, bytes32[] memory _blobCommitments, bytes32[] memory _blobHashes ) internal pure returns (bytes memory) { if (_batch.systemLogs.length > MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES) { revert SystemLogsSizeTooBig(); } bytes32 l2ToL1LogsHash = keccak256(_batch.systemLogs); return // solhint-disable-next-line func-named-parameters abi.encodePacked( l2ToL1LogsHash, _stateDiffHash, _batch.bootloaderHeapInitialContentsHash, _batch.eventsQueueStateHash, _encodeBlobAuxiliaryOutput(_blobCommitments, _blobHashes) ); } /// @dev Encodes the commitment to blobs to be used in the auxiliary output of the batch commitment /// @param _blobCommitments - the commitments to the blobs /// @param _blobHashes - the hashes of the blobs /// @param blobAuxOutputWords - The circuit commitment to the blobs split into 32-byte words function _encodeBlobAuxiliaryOutput( bytes32[] memory _blobCommitments, bytes32[] memory _blobHashes ) internal pure returns (bytes32[] memory blobAuxOutputWords) { // These invariants should be checked by the caller of this function, but we double check // just in case. if (_blobCommitments.length != MAX_NUMBER_OF_BLOBS || _blobHashes.length != MAX_NUMBER_OF_BLOBS) { revert InvalidNumberOfBlobs(MAX_NUMBER_OF_BLOBS, _blobCommitments.length, _blobHashes.length); } // for each blob we have: // linear hash (hash of preimage from system logs) and // output hash of blob commitments: keccak(versioned hash || opening point || evaluation value) // These values will all be bytes32(0) when we submit pubdata via calldata instead of blobs. // // For now, only up to 6 blobs are supported by the contract, while 16 are required by the circuits. // All the unfilled blobs will have their commitment as 0, including the case when we use only 1 blob. blobAuxOutputWords = new bytes32[](2 * TOTAL_BLOBS_IN_COMMITMENT); for (uint256 i = 0; i < MAX_NUMBER_OF_BLOBS; ++i) { blobAuxOutputWords[i * 2] = _blobHashes[i]; blobAuxOutputWords[i * 2 + 1] = _blobCommitments[i]; } } /// @notice Returns the keccak hash of the ABI-encoded StoredBatchInfo function _hashStoredBatchInfo(StoredBatchInfo memory _storedBatchInfo) internal pure returns (bytes32) { return keccak256(abi.encode(_storedBatchInfo)); } /// @notice Returns true if the bit at index {_index} is 1 function _checkBit(uint256 _bitMap, uint8 _index) internal pure returns (bool) { return (_bitMap & (1 << _index)) > 0; } /// @notice Sets the given bit in {_num} at index {_index} to 1. function _setBit(uint256 _bitMap, uint8 _index) internal pure returns (uint256) { return _bitMap | (1 << _index); } /// @notice Calls the point evaluation precompile and verifies the output /// Verify p(z) = y given commitment that corresponds to the polynomial p(x) and a KZG proof. /// Also verify that the provided commitment matches the provided versioned_hash. /// function _pointEvaluationPrecompile( bytes32 _versionedHash, bytes32 _openingPoint, bytes calldata _openingValueCommitmentProof ) internal view { bytes memory precompileInput = abi.encodePacked(_versionedHash, _openingPoint, _openingValueCommitmentProof); (bool success, bytes memory data) = POINT_EVALUATION_PRECOMPILE_ADDR.staticcall(precompileInput); // We verify that the point evaluation precompile call was successful by testing the latter 32 bytes of the // response is equal to BLS_MODULUS as defined in https://eips.ethereum.org/EIPS/eip-4844#point-evaluation-precompile if (!success) { revert PointEvalCallFailed(precompileInput); } (, uint256 result) = abi.decode(data, (uint256, uint256)); if (result != BLS_MODULUS) { revert PointEvalFailed(abi.encode(result)); } } /// @dev Verifies that the blobs contain the correct data by calling the point evaluation precompile. For the precompile we need: /// versioned hash || opening point || opening value || commitment || proof /// the _pubdataCommitments will contain the last 4 values, the versioned hash is pulled from the BLOBHASH opcode /// pubdataCommitments is a list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes)) = 144 bytes function _verifyBlobInformation( bytes calldata _pubdataCommitments, bytes32[] memory _blobHashes ) internal view returns (bytes32[] memory blobCommitments) { uint256 versionedHashIndex = 0; if (_pubdataCommitments.length == 0) { revert PubdataCommitmentsEmpty(); } if (_pubdataCommitments.length > PUBDATA_COMMITMENT_SIZE * MAX_NUMBER_OF_BLOBS) { revert PubdataCommitmentsTooBig(); } if (_pubdataCommitments.length % PUBDATA_COMMITMENT_SIZE != 0) { revert InvalidPubdataCommitmentsSize(); } blobCommitments = new bytes32[](MAX_NUMBER_OF_BLOBS); // We disable this check because calldata array length is cheap. // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _pubdataCommitments.length; i += PUBDATA_COMMITMENT_SIZE) { bytes32 blobVersionedHash = _getBlobVersionedHash(versionedHashIndex); if (blobVersionedHash == bytes32(0)) { revert EmptyBlobVersionHash(versionedHashIndex); } // First 16 bytes is the opening point. While we get the point as 16 bytes, the point evaluation precompile // requires it to be 32 bytes. The blob commitment must use the opening point as 16 bytes though. bytes32 openingPoint = bytes32( uint256(uint128(bytes16(_pubdataCommitments[i:i + PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET]))) ); _pointEvaluationPrecompile( blobVersionedHash, openingPoint, _pubdataCommitments[i + PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET:i + PUBDATA_COMMITMENT_SIZE] ); // Take the hash of the versioned hash || opening point || claimed value blobCommitments[versionedHashIndex] = keccak256( abi.encodePacked(blobVersionedHash, _pubdataCommitments[i:i + PUBDATA_COMMITMENT_COMMITMENT_OFFSET]) ); ++versionedHashIndex; } // This check is required because we want to ensure that there aren't any extra blobs trying to be published. // Calling the BLOBHASH opcode with an index > # blobs - 1 yields bytes32(0) bytes32 versionedHash = _getBlobVersionedHash(versionedHashIndex); if (versionedHash != bytes32(0)) { revert NonEmptyBlobVersionHash(versionedHashIndex); } // We verify that for each set of blobHash/blobCommitment are either both empty // or there are values for both. for (uint256 i = 0; i < MAX_NUMBER_OF_BLOBS; ++i) { if ( (_blobHashes[i] == bytes32(0) && blobCommitments[i] != bytes32(0)) || (_blobHashes[i] != bytes32(0) && blobCommitments[i] == bytes32(0)) ) { revert BlobHashCommitmentError(i, _blobHashes[i] == bytes32(0), blobCommitments[i] == bytes32(0)); } } } function _getBlobVersionedHash(uint256 _index) internal view virtual returns (bytes32 versionedHash) { assembly { versionedHash := blobhash(_index) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev `keccak256("")` bytes32 constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; /// @dev Bytes in raw L2 log /// @dev Equal to the bytes size of the tuple - (uint8 ShardId, bool isService, uint16 txNumberInBatch, address sender, /// bytes32 key, bytes32 value) uint256 constant L2_TO_L1_LOG_SERIALIZE_SIZE = 88; /// @dev The maximum length of the bytes array with L2 -> L1 logs uint256 constant MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES = 4 + L2_TO_L1_LOG_SERIALIZE_SIZE * 512; /// @dev The value of default leaf hash for L2 -> L1 logs Merkle tree /// @dev An incomplete fixed-size tree is filled with this value to be a full binary tree /// @dev Actually equal to the `keccak256(new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE))` bytes32 constant L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = 0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba; // TODO: change constant to the real root hash of empty Merkle tree (SMA-184) bytes32 constant DEFAULT_L2_LOGS_TREE_ROOT_HASH = bytes32(0); /// @dev Denotes the type of the ZKsync transaction that came from L1. uint256 constant PRIORITY_OPERATION_L2_TX_TYPE = 255; /// @dev Denotes the type of the ZKsync transaction that is used for system upgrades. uint256 constant SYSTEM_UPGRADE_L2_TX_TYPE = 254; /// @dev The maximal allowed difference between protocol minor versions in an upgrade. The 100 gap is needed /// in case a protocol version has been tested on testnet, but then not launched on mainnet, e.g. /// due to a bug found. /// We are allowed to jump at most 100 minor versions at a time. The major version is always expected to be 0. uint256 constant MAX_ALLOWED_MINOR_VERSION_DELTA = 100; /// @dev The amount of time in seconds the validator has to process the priority transaction /// NOTE: The constant is set to zero for the Alpha release period uint256 constant PRIORITY_EXPIRATION = 0 days; /// @dev Timestamp - seconds since unix epoch. uint256 constant COMMIT_TIMESTAMP_NOT_OLDER = 3 days; /// @dev Maximum available error between real commit batch timestamp and analog used in the verifier (in seconds) /// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 12 seconds) uint256 constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 1 hours; /// @dev Shift to apply to verify public input before verifying. uint256 constant PUBLIC_INPUT_SHIFT = 32; /// @dev The maximum number of L2 gas that a user can request for an L2 transaction uint256 constant MAX_GAS_PER_TRANSACTION = 80_000_000; /// @dev Even though the price for 1 byte of pubdata is 16 L1 gas, we have a slightly increased /// value. uint256 constant L1_GAS_PER_PUBDATA_BYTE = 17; /// @dev The intrinsic cost of the L1->l2 transaction in computational L2 gas uint256 constant L1_TX_INTRINSIC_L2_GAS = 167_157; /// @dev The intrinsic cost of the L1->l2 transaction in pubdata uint256 constant L1_TX_INTRINSIC_PUBDATA = 88; /// @dev The minimal base price for L1 transaction uint256 constant L1_TX_MIN_L2_GAS_BASE = 173_484; /// @dev The number of L2 gas the transaction starts costing more with each 544 bytes of encoding uint256 constant L1_TX_DELTA_544_ENCODING_BYTES = 1656; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473; /// @dev The number of L2 gas an L1->L2 transaction gains with each new factory dependency uint256 constant L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64; /// @dev The number of pubdata an L1->L2 transaction requires with each new factory dependency uint256 constant MAX_NEW_FACTORY_DEPS = 32; /// @dev The L2 gasPricePerPubdata required to be used in bridges. uint256 constant REQUIRED_L2_GAS_PRICE_PER_PUBDATA = 800; /// @dev The mask which should be applied to the packed batch and L2 block timestamp in order /// to obtain the L2 block timestamp. Applying this mask is equivalent to calculating modulo 2**128 uint256 constant PACKED_L2_BLOCK_TIMESTAMP_MASK = 0xffffffffffffffffffffffffffffffff; /// @dev Address of the point evaluation precompile used for EIP-4844 blob verification. address constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A); /// @dev The overhead for a transaction slot in L2 gas. /// It is roughly equal to 80kk/MAX_TRANSACTIONS_IN_BATCH, i.e. how many gas would an L1->L2 transaction /// need to pay to compensate for the batch being closed. /// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate /// the operator in case the batch is closed because of tx slots filling up. uint256 constant TX_SLOT_OVERHEAD_L2_GAS = 10000; /// @dev The overhead for each byte of the bootloader memory that the encoding of the transaction. /// It is roughly equal to 80kk/BOOTLOADER_MEMORY_FOR_TXS, i.e. how many gas would an L1->L2 transaction /// need to pay to compensate for the batch being closed. /// @dev It is expected that the L1 contracts will enforce that the L2 gas price will be high enough to compensate /// the operator in case the batch is closed because of the memory for transactions being filled up. uint256 constant MEMORY_OVERHEAD_GAS = 10; /// @dev The maximum gas limit for a priority transaction in L2. uint256 constant PRIORITY_TX_MAX_GAS_LIMIT = 72_000_000; address constant ETH_TOKEN_ADDRESS = address(1); bytes32 constant TWO_BRIDGES_MAGIC_VALUE = bytes32(uint256(keccak256("TWO_BRIDGES_MAGIC_VALUE")) - 1); /// @dev https://eips.ethereum.org/EIPS/eip-1352 address constant BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS = address(uint160(type(uint16).max));
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // 0x1ff9d522 error AddressAlreadyUsed(address addr); // 0x86bb51b8 error AddressHasNoCode(address); // 0x1eee5481 error AddressTooLow(address); // 0x6afd6c20 error BadReturnData(); // 0x6ef9a972 error BaseTokenGasPriceDenominatorNotSet(); // 0x55ad3fd3 error BatchHashMismatch(bytes32 expected, bytes32 actual); // 0x2078a6a0 error BatchNotExecuted(uint256 batchNumber); // 0xbd4455ff error BatchNumberMismatch(uint256 expectedBatchNumber, uint256 providedBatchNumber); // 0xafd53e2f error BlobHashCommitmentError(uint256 index, bool blobHashEmpty, bool blobCommitmentEmpty); // 0x6cf12312 error BridgeHubAlreadyRegistered(); // 0xcf102c5a error CalldataLengthTooBig(); // 0xe85392f9 error CanOnlyProcessOneBatch(); // 0x00c6ead2 error CantExecuteUnprovenBatches(); // 0xe18cb383 error CantRevertExecutedBatch(); // 0x78d2ed02 error ChainAlreadyLive(); // 0x8f620a06 error ChainIdTooBig(); // 0xf7a01e4d error DelegateCallFailed(bytes returnData); // 0x0a8ed92c error DenominatorIsZero(); // 0xc7c9660f error DepositDoesNotExist(); // 0xad2fa98e error DepositExists(); // 0x79cacff1 error DepositFailed(); // 0xae08e4af error DepositIncorrectAmount(uint256 expectedAmt, uint256 providedAmt); // 0x0e7ee319 error DiamondAlreadyFrozen(); // 0x682dabb4 error DiamondFreezeIncorrectState(); // 0xa7151b9a error DiamondNotFrozen(); // 0xfc7ab1d3 error EmptyBlobVersionHash(uint256 index); // 0x95b66fe9 error EmptyDeposit(); // 0xac4a3f98 error FacetExists(bytes4 selector, address); // 0x79e12cc3 error FacetIsFrozen(bytes4 func); // 0xc91cf3b1 error GasPerPubdataMismatch(); // 0x6d4a7df8 error GenesisBatchCommitmentZero(); // 0x7940c83f error GenesisBatchHashZero(); // 0xb4fc6835 error GenesisIndexStorageZero(); // 0x3a1a8589 error GenesisUpgradeZero(); // 0xd356e6ba error HashedLogIsDefault(); // 0x0b08d5be error HashMismatch(bytes32 expected, bytes32 actual); // 0xb615c2b1 error HyperchainLimitReached(); // 0x826fb11e error InsufficientChainBalance(); // 0x356680b7 error InsufficientFunds(); // 0x7a47c9a2 error InvalidChainId(); // 0x4fbe5dba error InvalidDelay(); // 0x0af806e0 error InvalidHash(); // 0xc1780bd6 error InvalidLogSender(address sender, uint256 logKey); // 0xd8e9405c error InvalidNumberOfBlobs(uint256 expected, uint256 numCommitments, uint256 numHashes); // 0x09bde339 error InvalidProof(); // 0x5428eae7 error InvalidProtocolVersion(); // 0x53e6d04d error InvalidPubdataCommitmentsSize(); // 0x5513177c error InvalidPubdataHash(bytes32 expectedHash, bytes32 provided); // 0x9094af7e error InvalidPubdataLength(); // 0xc5d09071 error InvalidPubdataMode(); // 0x6f1cf752 error InvalidPubdataPricingMode(); // 0x12ba286f error InvalidSelector(bytes4 func); // 0x5cb29523 error InvalidTxType(uint256 txType); // 0x5f1aa154 error InvalidUpgradeTxn(UpgradeTxVerifyParam); // 0xaa7feadc error InvalidValue(); // 0xa4f62e33 error L2BridgeNotDeployed(uint256 chainId); // 0xff8811ff error L2BridgeNotSet(uint256 chainId); // 0xcb5e4247 error L2BytecodeHashMismatch(bytes32 expected, bytes32 provided); // 0xfb5c22e6 error L2TimestampTooBig(); // 0xd2c011d6 error L2UpgradeNonceNotEqualToNewProtocolVersion(uint256 nonce, uint256 protocolVersion); // 0x97e1359e error L2WithdrawalMessageWrongLength(uint256 messageLen); // 0x32eb8b2f error LegacyMethodIsSupportedOnlyForEra(); // 0xe37d2c02 error LengthIsNotDivisibleBy32(uint256 length); // 0x1b6825bb error LogAlreadyProcessed(uint8); // 0x43e266b0 error MalformedBytecode(BytecodeError); // 0x59170bf0 error MalformedCalldata(); // 0x16509b9a error MalformedMessage(); // 0x9bb54c35 error MerkleIndexOutOfBounds(); // 0x8e23ac1a error MerklePathEmpty(); // 0x1c500385 error MerklePathOutOfBounds(); // 0xfa44b527 error MissingSystemLogs(uint256 expected, uint256 actual); // 0x4a094431 error MsgValueMismatch(uint256 expectedMsgValue, uint256 providedMsgValue); // 0xb385a3da error MsgValueTooLow(uint256 required, uint256 provided); // 0x72ea85ad error NewProtocolMajorVersionNotZero(); // 0x79cc2d22 error NoCallsProvided(); // 0xa6fef710 error NoFunctionsForDiamondCut(); // 0xcab098d8 error NoFundsTransferred(); // 0x92290acc error NonEmptyBlobVersionHash(uint256 index); // 0xc21b1ab7 error NonEmptyCalldata(); // 0x536ec84b error NonEmptyMsgValue(); // 0xd018e08e error NonIncreasingTimestamp(); // 0x0105f9c0 error NonSequentialBatch(); // 0x4ef79e5a error NonZeroAddress(address); // 0xdd629f86 error NotEnoughGas(); // 0xdd7e3621 error NotInitializedReentrancyGuard(); // 0xf3ed9dfa error OnlyEraSupported(); // 0x1a21feed error OperationExists(); // 0xeda2fbb1 error OperationMustBePending(); // 0xe1c1ff37 error OperationMustBeReady(); // 0xd7f50a9d error PatchCantSetUpgradeTxn(); // 0x962fd7d0 error PatchUpgradeCantSetBootloader(); // 0x559cc34e error PatchUpgradeCantSetDefaultAccount(); // 0x8d5851de error PointEvalCallFailed(bytes); // 0x4daa985d error PointEvalFailed(bytes); // 0x9b48e060 error PreviousOperationNotExecuted(); // 0x5c598b60 error PreviousProtocolMajorVersionNotZero(); // 0xa0f47245 error PreviousUpgradeNotCleaned(); // 0x101ba748 error PreviousUpgradeNotFinalized(bytes32 txHash); // 0xd5a99014 error PriorityOperationsRollingHashMismatch(); // 0x1a4d284a error PriorityTxPubdataExceedsMaxPubDataPerBatch(); // 0xa461f651 error ProtocolIdMismatch(uint256 expectedProtocolVersion, uint256 providedProtocolId); // 0x64f94ec2 error ProtocolIdNotGreater(); // 0xd328c12a error ProtocolVersionMinorDeltaTooBig(uint256 limit, uint256 proposed); // 0x88d7b498 error ProtocolVersionTooSmall(); // 0x53dee67b error PubdataCommitmentsEmpty(); // 0x7734c31a error PubdataCommitmentsTooBig(); // 0x959f26fb error PubdataGreaterThanLimit(uint256 limit, uint256 length); // 0x2a4a14df error PubdataPerBatchIsLessThanTxn(); // 0x63c36549 error QueueIsEmpty(); // 0xab143c06 error Reentrancy(); // 0x667d17de error RemoveFunctionFacetAddressNotZero(address facet); // 0xa2d4b16c error RemoveFunctionFacetAddressZero(); // 0x3580370c error ReplaceFunctionFacetAddressZero(); // 0xdab52f4b error RevertedBatchBeforeNewBatch(); // 0x9a67c1cb error RevertedBatchNotAfterNewLastBatch(); // 0xd3b6535b error SelectorsMustAllHaveSameFreezability(); // 0x7774d2f9 error SharedBridgeValueNotSet(SharedBridgeKey); // 0xc1d9246c error SharedBridgeBalanceMismatch(); // 0x856d5b77 error SharedBridgeNotSet(); // 0xcac5fc40 error SharedBridgeValueAlreadySet(SharedBridgeKey); // 0xdf3a8fdd error SlotOccupied(); // 0xd0bc70cf error STMAlreadyRegistered(); // 0x09865e10 error STMNotRegistered(); // 0xae43b424 error SystemLogsSizeTooBig(); // 0x08753982 error TimeNotReached(uint256 expectedTimestamp, uint256 actualTimestamp); // 0x2d50c33b error TimestampError(); // 0x4f4b634e error TokenAlreadyRegistered(address token); // 0xddef98d7 error TokenNotRegistered(address token); // 0x06439c6b error TokenNotSupported(address token); // 0x23830e28 error TokensWithFeesNotSupported(); // 0xf640f0e5 error TooManyBlobs(); // 0x76da24b9 error TooManyFactoryDeps(); // 0xf0b4e88f error TooMuchGas(); // 0x00c5a6a9 error TransactionNotAllowed(); // 0x4c991078 error TxHashMismatch(); // 0x2e311df8 error TxnBodyGasLimitNotEnoughGas(); // 0x8e4a23d6 error Unauthorized(address caller); // 0xe52478c7 error UndefinedDiamondCutAction(); // 0x07218375 error UnexpectedNumberOfFactoryDeps(); // 0x6aa39880 error UnexpectedSystemLog(uint256 logKey); // 0xf093c2e5 error UpgradeBatchNumberIsNotZero(); // 0x47b3b145 error ValidateTxnNotEnoughGas(); // 0x626ade30 error ValueMismatch(uint256 expected, uint256 actual); // 0xe1022469 error VerifiedBatchesExceedsCommittedBatches(); // 0x2dbdba00 error VerifyProofCommittedVerifiedMismatch(); // 0xae899454 error WithdrawalAlreadyFinalized(); // 0x27fcd9d1 error WithdrawalFailed(); // 0x750b219c error WithdrawFailed(); // 0x15e8e429 error WrongMagicValue(uint256 expectedMagicValue, uint256 providedMagicValue); // 0xd92e233d error ZeroAddress(); // 0x669567ea error ZeroBalance(); // 0xc84885d4 error ZeroChainId(); enum SharedBridgeKey { PostUpgradeFirstBatch, LegacyBridgeFirstBatch, LegacyBridgeLastDepositBatch, LegacyBridgeLastDepositTxn } enum BytecodeError { Version, NumberOfWords, Length, WordsMustBeOdd } enum UpgradeTxVerifyParam { From, To, Paymaster, Value, MaxFeePerGas, MaxPriorityFeePerGas, Reserved0, Reserved1, Reserved2, Reserved3, Signature, PaymasterInput, ReservedDynamic }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev The formal address of the initial program of the system: the bootloader address constant L2_BOOTLOADER_ADDRESS = address(0x8001); /// @dev The address of the known code storage system contract address constant L2_KNOWN_CODE_STORAGE_SYSTEM_CONTRACT_ADDR = address(0x8004); /// @dev The address of the L2 deployer system contract. address constant L2_DEPLOYER_SYSTEM_CONTRACT_ADDR = address(0x8006); /// @dev The special reserved L2 address. It is located in the system contracts space but doesn't have deployed /// bytecode. /// @dev The L2 deployer system contract allows changing bytecodes on any address if the `msg.sender` is this address. /// @dev So, whenever the governor wants to redeploy system contracts, it just initiates the L1 upgrade call deployer /// system contract /// via the L1 -> L2 transaction with `sender == L2_FORCE_DEPLOYER_ADDR`. For more details see the /// `diamond-initializers` contracts. address constant L2_FORCE_DEPLOYER_ADDR = address(0x8007); /// @dev The address of the special smart contract that can send arbitrary length message as an L2 log address constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = address(0x8008); /// @dev The address of the eth token system contract address constant L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR = address(0x800a); /// @dev The address of the context system contract address constant L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR = address(0x800b); /// @dev The address of the pubdata chunk publisher contract address constant L2_PUBDATA_CHUNK_PUBLISHER_ADDR = address(0x8011);
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /** * @author Matter Labs * @custom:security-contact [email protected] * @notice The library for unchecked math. */ library UncheckedMath { function uncheckedInc(uint256 _number) internal pure returns (uint256) { unchecked { return _number + 1; } } function uncheckedAdd(uint256 _lhs, uint256 _rhs) internal pure returns (uint256) { unchecked { return _lhs + _rhs; } } }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /** * @author Matter Labs * @custom:security-contact [email protected] * @dev The library provides a set of functions that help read data from an "abi.encodePacked" byte array. * @dev Each of the functions accepts the `bytes memory` and the offset where data should be read and returns a value of a certain type. * * @dev WARNING! * 1) Functions don't check the length of the bytes array, so it can go out of bounds. * The user of the library must check for bytes length before using any functions from the library! * * 2) Read variables are not cleaned up - https://docs.soliditylang.org/en/v0.8.16/internals/variable_cleanup.html. * Using data in inline assembly can lead to unexpected behavior! */ library UnsafeBytes { function readUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32 result, uint256 offset) { assembly { offset := add(_start, 4) result := mload(add(_bytes, offset)) } } function readAddress(bytes memory _bytes, uint256 _start) internal pure returns (address result, uint256 offset) { assembly { offset := add(_start, 20) result := mload(add(_bytes, offset)) } } function readUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256 result, uint256 offset) { assembly { offset := add(_start, 32) result := mload(add(_bytes, offset)) } } function readBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32 result, uint256 offset) { assembly { offset := add(_start, 32) result := mload(add(_bytes, offset)) } } }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @dev The enum that represents the transaction execution status /// @param Failure The transaction execution failed /// @param Success The transaction execution succeeded enum TxStatus { Failure, Success } /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter /// All other values are not used but are reserved for the future /// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address. /// This field is required formally but does not have any special meaning /// @param txNumberInBatch The L2 transaction number in a Batch, in which the log was sent /// @param sender The L2 address which sent the log /// @param key The 32 bytes of information that was sent in the log /// @param value The 32 bytes of information that was sent in the log // Both `key` and `value` are arbitrary 32-bytes selected by the log sender struct L2Log { uint8 l2ShardId; bool isService; uint16 txNumberInBatch; address sender; bytes32 key; bytes32 value; } /// @dev An arbitrary length message passed from L2 /// @notice Under the hood it is `L2Log` sent from the special system L2 contract /// @param txNumberInBatch The L2 transaction number in a Batch, in which the message was sent /// @param sender The address of the L2 account from which the message was passed /// @param data An arbitrary length message struct L2Message { uint16 txNumberInBatch; address sender; bytes data; } /// @dev Internal structure that contains the parameters for the writePriorityOp /// internal function. /// @param txId The id of the priority transaction. /// @param l2GasPrice The gas price for the l2 priority operation. /// @param expirationTimestamp The timestamp by which the priority operation must be processed by the operator. /// @param request The external calldata request for the priority operation. struct WritePriorityOpParams { uint256 txId; uint256 l2GasPrice; uint64 expirationTimestamp; BridgehubL2TransactionRequest request; } /// @dev Structure that includes all fields of the L2 transaction /// @dev The hash of this structure is the "canonical L2 transaction hash" and can /// be used as a unique identifier of a tx /// @param txType The tx type number, depending on which the L2 transaction can be /// interpreted differently /// @param from The sender's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param to The recipient's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param gasLimit The L2 gas limit for L2 transaction. Analog to the `gasLimit` on an /// L1 transactions /// @param gasPerPubdataByteLimit Maximum number of L2 gas that will cost one byte of pubdata /// (every piece of data that will be stored on L1 as calldata) /// @param maxFeePerGas The absolute maximum sender willing to pay per unit of L2 gas to get /// the transaction included in a Batch. Analog to the EIP-1559 `maxFeePerGas` on an L1 transactions /// @param maxPriorityFeePerGas The additional fee that is paid directly to the validator /// to incentivize them to include the transaction in a Batch. Analog to the EIP-1559 /// `maxPriorityFeePerGas` on an L1 transactions /// @param paymaster The address of the EIP-4337 paymaster, that will pay fees for the /// transaction. `uint256` type for possible address format changes and maintaining backward compatibility /// @param nonce The nonce of the transaction. For L1->L2 transactions it is the priority /// operation Id /// @param value The value to pass with the transaction /// @param reserved The fixed-length fields for usage in a future extension of transaction /// formats /// @param data The calldata that is transmitted for the transaction call /// @param signature An abstract set of bytes that are used for transaction authorization /// @param factoryDeps The set of L2 bytecode hashes whose preimages were shown on L1 /// @param paymasterInput The arbitrary-length data that is used as a calldata to the paymaster pre-call /// @param reservedDynamic The arbitrary-length field for usage in a future extension of transaction formats struct L2CanonicalTransaction { uint256 txType; uint256 from; uint256 to; uint256 gasLimit; uint256 gasPerPubdataByteLimit; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; uint256 paymaster; uint256 nonce; uint256 value; // In the future, we might want to add some // new fields to the struct. The `txData` struct // is to be passed to account and any changes to its structure // would mean a breaking change to these accounts. To prevent this, // we should keep some fields as "reserved" // It is also recommended that their length is fixed, since // it would allow easier proof integration (in case we will need // some special circuit for preprocessing transactions) uint256[4] reserved; bytes data; bytes signature; uint256[] factoryDeps; bytes paymasterInput; // Reserved dynamic type for the future use-case. Using it should be avoided, // But it is still here, just in case we want to enable some additional functionality bytes reservedDynamic; } /// @param sender The sender's address. /// @param contractAddressL2 The address of the contract on L2 to call. /// @param valueToMint The amount of base token that should be minted on L2 as the result of this transaction. /// @param l2Value The msg.value of the L2 transaction. /// @param l2Calldata The calldata for the L2 transaction. /// @param l2GasLimit The limit of the L2 gas for the L2 transaction /// @param l2GasPerPubdataByteLimit The price for a single pubdata byte in L2 gas. /// @param factoryDeps The array of L2 bytecodes that the tx depends on. /// @param refundRecipient The recipient of the refund for the transaction on L2. If the transaction fails, then /// this address will receive the `l2Value`. // solhint-disable-next-line gas-struct-packing struct BridgehubL2TransactionRequest { address sender; address contractL2; uint256 mintValue; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {SlotOccupied, NotInitializedReentrancyGuard, Reentrancy} from "./L1ContractErrors.sol"; /** * @custom:security-contact [email protected] * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. * * _Since v2.5.0:_ this module is now much more gas efficient, given net gas * metering changes introduced in the Istanbul hardfork. */ abstract contract ReentrancyGuard { /// @dev Address of lock flag variable. /// @dev Flag is placed at random memory location to not interfere with Storage contract. // keccak256("ReentrancyGuard") - 1; uint256 private constant LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4; // solhint-disable-next-line max-line-length // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/566a774222707e424896c0c390a84dc3c13bdcb2/contracts/security/ReentrancyGuard.sol // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; modifier reentrancyGuardInitializer() { _initializeReentrancyGuard(); _; } function _initializeReentrancyGuard() private { uint256 lockSlotOldValue; // Storing an initial non-zero value makes deployment a bit more // expensive but in exchange every call to nonReentrant // will be cheaper. assembly { lockSlotOldValue := sload(LOCK_FLAG_ADDRESS) sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED) } // Check that storage slot for reentrancy guard is empty to rule out possibility of slot conflict if (lockSlotOldValue != 0) { revert SlotOccupied(); } } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { uint256 _status; assembly { _status := sload(LOCK_FLAG_ADDRESS) } if (_status == 0) { revert NotInitializedReentrancyGuard(); } // On the first call to nonReentrant, _NOT_ENTERED will be true if (_status != _NOT_ENTERED) { revert Reentrancy(); } // Any calls to nonReentrant after this point will fail assembly { sstore(LOCK_FLAG_ADDRESS, _ENTERED) } _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) assembly { sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {ZkSyncHyperchainStorage} from "../ZkSyncHyperchainStorage.sol"; import {ReentrancyGuard} from "../../../common/ReentrancyGuard.sol"; import {Unauthorized} from "../../../common/L1ContractErrors.sol"; /// @title Base contract containing functions accessible to the other facets. /// @author Matter Labs /// @custom:security-contact [email protected] contract ZkSyncHyperchainBase is ReentrancyGuard { // slither-disable-next-line uninitialized-state ZkSyncHyperchainStorage internal s; /// @notice Checks that the message sender is an active admin modifier onlyAdmin() { if (msg.sender != s.admin) { revert Unauthorized(msg.sender); } _; } /// @notice Checks if validator is active modifier onlyValidator() { if (!s.validators[msg.sender]) { revert Unauthorized(msg.sender); } _; } modifier onlyStateTransitionManager() { if (msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyBridgehub() { if (msg.sender != s.bridgehub) { revert Unauthorized(msg.sender); } _; } modifier onlyAdminOrStateTransitionManager() { if (msg.sender != s.admin && msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyValidatorOrStateTransitionManager() { if (!s.validators[msg.sender] && msg.sender != s.stateTransitionManager) { revert Unauthorized(msg.sender); } _; } modifier onlyBaseTokenBridge() { if (msg.sender != s.baseTokenBridge) { revert Unauthorized(msg.sender); } _; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IVerifier, VerifierParams} from "../chain-interfaces/IVerifier.sol"; import {PriorityQueue} from "../../state-transition/libraries/PriorityQueue.sol"; /// @notice Indicates whether an upgrade is initiated and if yes what type /// @param None Upgrade is NOT initiated /// @param Transparent Fully transparent upgrade is initiated, upgrade data is publicly known /// @param Shadow Shadow upgrade is initiated, upgrade data is hidden enum UpgradeState { None, Transparent, Shadow } /// @dev Logically separated part of the storage structure, which is responsible for everything related to proxy /// upgrades and diamond cuts /// @param proposedUpgradeHash The hash of the current upgrade proposal, zero if there is no active proposal /// @param state Indicates whether an upgrade is initiated and if yes what type /// @param securityCouncil Address which has the permission to approve instant upgrades (expected to be a Gnosis /// multisig) /// @param approvedBySecurityCouncil Indicates whether the security council has approved the upgrade /// @param proposedUpgradeTimestamp The timestamp when the upgrade was proposed, zero if there are no active proposals /// @param currentProposalId The serial number of proposed upgrades, increments when proposing a new one struct UpgradeStorage { bytes32 proposedUpgradeHash; UpgradeState state; address securityCouncil; bool approvedBySecurityCouncil; uint40 proposedUpgradeTimestamp; uint40 currentProposalId; } /// @notice The struct that describes whether users will be charged for pubdata for L1->L2 transactions. /// @param Rollup The users are charged for pubdata & it is priced based on the gas price on Ethereum. /// @param Validium The pubdata is considered free with regard to the L1 gas price. enum PubdataPricingMode { Rollup, Validium } /// @notice The fee params for L1->L2 transactions for the network. /// @param pubdataPricingMode How the users will charged for pubdata in L1->L2 transactions. /// @param batchOverheadL1Gas The amount of L1 gas required to process the batch (except for the calldata). /// @param maxPubdataPerBatch The maximal number of pubdata that can be emitted per batch. /// @param priorityTxMaxPubdata The maximal amount of pubdata a priority transaction is allowed to publish. /// It can be slightly less than maxPubdataPerBatch in order to have some margin for the bootloader execution. /// @param minimalL2GasPrice The minimal L2 gas price to be used by L1->L2 transactions. It should represent /// the price that a single unit of compute costs. struct FeeParams { PubdataPricingMode pubdataPricingMode; uint32 batchOverheadL1Gas; uint32 maxPubdataPerBatch; uint32 maxL2GasPerBatch; uint32 priorityTxMaxPubdata; uint64 minimalL2GasPrice; } /// @dev storing all storage variables for hyperchain diamond facets /// NOTE: It is used in a proxy, so it is possible to add new variables to the end /// but NOT to modify already existing variables or change their order. /// NOTE: variables prefixed with '__DEPRECATED_' are deprecated and shouldn't be used. /// Their presence is maintained for compatibility and to prevent storage collision. // solhint-disable-next-line gas-struct-packing struct ZkSyncHyperchainStorage { /// @dev Storage of variables needed for deprecated diamond cut facet uint256[7] __DEPRECATED_diamondCutStorage; /// @notice Address which will exercise critical changes to the Diamond Proxy (upgrades, freezing & unfreezing). Replaced by STM address __DEPRECATED_governor; /// @notice Address that the governor proposed as one that will replace it address __DEPRECATED_pendingGovernor; /// @notice List of permitted validators mapping(address validatorAddress => bool isValidator) validators; /// @dev Verifier contract. Used to verify aggregated proof for batches IVerifier verifier; /// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch /// (batch 0 is genesis) uint256 totalBatchesExecuted; /// @notice Total number of proved batches i.e. batches[totalBatchesProved] points at the latest proved batch uint256 totalBatchesVerified; /// @notice Total number of committed batches i.e. batches[totalBatchesCommitted] points at the latest committed /// batch uint256 totalBatchesCommitted; /// @dev Stored hashed StoredBatch for batch number mapping(uint256 batchNumber => bytes32 batchHash) storedBatchHashes; /// @dev Stored root hashes of L2 -> L1 logs mapping(uint256 batchNumber => bytes32 l2LogsRootHash) l2LogsRootHashes; /// @dev Container that stores transactions requested from L1 PriorityQueue.Queue priorityQueue; /// @dev The smart contract that manages the list with permission to call contract functions address __DEPRECATED_allowList; VerifierParams __DEPRECATED_verifierParams; /// @notice Bytecode hash of bootloader program. /// @dev Used as an input to zkp-circuit. bytes32 l2BootloaderBytecodeHash; /// @notice Bytecode hash of default account (bytecode for EOA). /// @dev Used as an input to zkp-circuit. bytes32 l2DefaultAccountBytecodeHash; /// @dev Indicates that the porter may be touched on L2 transactions. /// @dev Used as an input to zkp-circuit. bool zkPorterIsAvailable; /// @dev The maximum number of the L2 gas that a user can request for L1 -> L2 transactions /// @dev This is the maximum number of L2 gas that is available for the "body" of the transaction, i.e. /// without overhead for proving the batch. uint256 priorityTxMaxGasLimit; /// @dev Storage of variables needed for upgrade facet UpgradeStorage __DEPRECATED_upgrades; /// @dev A mapping L2 batch number => message number => flag. /// @dev The L2 -> L1 log is sent for every withdrawal, so this mapping is serving as /// a flag to indicate that the message was already processed. /// @dev Used to indicate that eth withdrawal was already processed mapping(uint256 l2BatchNumber => mapping(uint256 l2ToL1MessageNumber => bool isFinalized)) isEthWithdrawalFinalized; /// @dev The most recent withdrawal time and amount reset uint256 __DEPRECATED_lastWithdrawalLimitReset; /// @dev The accumulated withdrawn amount during the withdrawal limit window uint256 __DEPRECATED_withdrawnAmountInWindow; /// @dev A mapping user address => the total deposited amount by the user mapping(address => uint256) __DEPRECATED_totalDepositedAmountPerUser; /// @dev Stores the protocol version. Note, that the protocol version may not only encompass changes to the /// smart contracts, but also to the node behavior. uint256 protocolVersion; /// @dev Hash of the system contract upgrade transaction. If 0, then no upgrade transaction needs to be done. bytes32 l2SystemContractsUpgradeTxHash; /// @dev Batch number where the upgrade transaction has happened. If 0, then no upgrade transaction has happened /// yet. uint256 l2SystemContractsUpgradeBatchNumber; /// @dev Address which will exercise non-critical changes to the Diamond Proxy (changing validator set & unfreezing) address admin; /// @notice Address that the admin proposed as one that will replace admin role address pendingAdmin; /// @dev Fee params used to derive gasPrice for the L1->L2 transactions. For L2 transactions, /// the bootloader gives enough freedom to the operator. FeeParams feeParams; /// @dev Address of the blob versioned hash getter smart contract used for EIP-4844 versioned hashes. address blobVersionedHashRetriever; /// @dev The chainId of the chain uint256 chainId; /// @dev The address of the bridgehub address bridgehub; /// @dev The address of the StateTransitionManager address stateTransitionManager; /// @dev The address of the baseToken contract. Eth is address(1) address baseToken; /// @dev The address of the baseTokenbridge. Eth also uses the shared bridge address baseTokenBridge; /// @notice gasPriceMultiplier for each baseToken, so that each L1->L2 transaction pays for its transaction on the destination /// we multiply by the nominator, and divide by the denominator uint128 baseTokenGasPriceMultiplierNominator; uint128 baseTokenGasPriceMultiplierDenominator; /// @dev The optional address of the contract that has to be used for transaction filtering/whitelisting address transactionFilterer; }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.sol"; /// @dev Enum used by L2 System Contracts to differentiate logs. enum SystemLogKey { L2_TO_L1_LOGS_TREE_ROOT_KEY, TOTAL_L2_TO_L1_PUBDATA_KEY, STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, NUMBER_OF_LAYER_1_TXS_KEY, BLOB_ONE_HASH_KEY, BLOB_TWO_HASH_KEY, BLOB_THREE_HASH_KEY, BLOB_FOUR_HASH_KEY, BLOB_FIVE_HASH_KEY, BLOB_SIX_HASH_KEY, EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY } /// @dev Enum used to determine the source of pubdata. At first we will support calldata and blobs but this can be extended. enum PubdataSource { Calldata, Blob } struct LogProcessingOutput { uint256 numberOfLayer1Txs; bytes32 chainedPriorityTxsHash; bytes32 previousBatchHash; bytes32 pubdataHash; bytes32 stateDiffHash; bytes32 l2LogsTreeRoot; uint256 packedBatchAndL2BlockTimestamp; bytes32[] blobHashes; } /// @dev Total number of bytes in a blob. Blob = 4096 field elements * 31 bytes per field element /// @dev EIP-4844 defines it as 131_072 but we use 4096 * 31 within our circuits to always fit within a field element /// @dev Our circuits will prove that a EIP-4844 blob and our internal blob are the same. uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Offset used to pull Address From Log. Equal to 4 (bytes for isService) uint256 constant L2_LOG_ADDRESS_OFFSET = 4; /// @dev Offset used to pull Key From Log. Equal to 4 (bytes for isService) + 20 (bytes for address) uint256 constant L2_LOG_KEY_OFFSET = 24; /// @dev Offset used to pull Value From Log. Equal to 4 (bytes for isService) + 20 (bytes for address) + 32 (bytes for key) uint256 constant L2_LOG_VALUE_OFFSET = 56; /// @dev BLS Modulus value defined in EIP-4844 and the magic value returned from a successful call to the /// point evaluation precompile uint256 constant BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513; /// @dev Packed pubdata commitments. /// @dev Format: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes)) = 144 bytes uint256 constant PUBDATA_COMMITMENT_SIZE = 144; /// @dev Offset in pubdata commitment of blobs for claimed value uint256 constant PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET = 16; /// @dev Offset in pubdata commitment of blobs for kzg commitment uint256 constant PUBDATA_COMMITMENT_COMMITMENT_OFFSET = 48; /// @dev Max number of blobs currently supported uint256 constant MAX_NUMBER_OF_BLOBS = 6; /// @dev The number of blobs that must be present in the commitment to a batch. /// It represents the maximal number of blobs that circuits can support and can be larger /// than the maximal number of blobs supported by the contract (`MAX_NUMBER_OF_BLOBS`). uint256 constant TOTAL_BLOBS_IN_COMMITMENT = 16; /// @title The interface of the ZKsync Executor contract capable of processing events emitted in the ZKsync protocol. /// @author Matter Labs /// @custom:security-contact [email protected] interface IExecutor is IZkSyncHyperchainBase { /// @notice Rollup batch stored data /// @param batchNumber Rollup batch number /// @param batchHash Hash of L2 batch /// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more /// @param numberOfLayer1Txs Number of priority operations to be processed /// @param priorityOperationsHash Hash of all priority operations from this batch /// @param l2LogsTreeRoot Root hash of tree that contains L2 -> L1 messages from this batch /// @param timestamp Rollup batch timestamp, have the same format as Ethereum batch constant /// @param commitment Verified input for the ZKsync circuit // solhint-disable-next-line gas-struct-packing struct StoredBatchInfo { uint64 batchNumber; bytes32 batchHash; uint64 indexRepeatedStorageChanges; uint256 numberOfLayer1Txs; bytes32 priorityOperationsHash; bytes32 l2LogsTreeRoot; uint256 timestamp; bytes32 commitment; } /// @notice Data needed to commit new batch /// @param batchNumber Number of the committed batch /// @param timestamp Unix timestamp denoting the start of the batch execution /// @param indexRepeatedStorageChanges The serial number of the shortcut index that's used as a unique identifier for storage keys that were used twice or more /// @param newStateRoot The state root of the full state tree /// @param numberOfLayer1Txs Number of priority operations to be processed /// @param priorityOperationsHash Hash of all priority operations from this batch /// @param bootloaderHeapInitialContentsHash Hash of the initial contents of the bootloader heap. In practice it serves as the commitment to the transactions in the batch. /// @param eventsQueueStateHash Hash of the events queue state. In practice it serves as the commitment to the events in the batch. /// @param systemLogs concatenation of all L2 -> L1 system logs in the batch /// @param pubdataCommitments Packed pubdata commitments/data. /// @dev pubdataCommitments format: This will always start with a 1 byte pubdataSource flag. Current allowed values are 0 (calldata) or 1 (blobs) /// kzg: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes) = 144 bytes /// calldata: pubdataCommitments.length - 1 - 32 bytes of pubdata /// and 32 bytes appended to serve as the blob commitment part for the aux output part of the batch commitment /// @dev For 2 blobs we will be sending 288 bytes of calldata instead of the full amount for pubdata. /// @dev When using calldata, we only need to send one blob commitment since the max number of bytes in calldata fits in a single blob and we can pull the /// linear hash from the system logs struct CommitBatchInfo { uint64 batchNumber; uint64 timestamp; uint64 indexRepeatedStorageChanges; bytes32 newStateRoot; uint256 numberOfLayer1Txs; bytes32 priorityOperationsHash; bytes32 bootloaderHeapInitialContentsHash; bytes32 eventsQueueStateHash; bytes systemLogs; bytes pubdataCommitments; } /// @notice Recursive proof input data (individual commitments are constructed onchain) struct ProofInput { uint256[] recursiveAggregationInput; uint256[] serializedProof; } /// @notice Function called by the operator to commit new batches. It is responsible for: /// - Verifying the correctness of their timestamps. /// - Processing their L2->L1 logs. /// - Storing batch commitments. /// @param _lastCommittedBatchData Stored data of the last committed batch. /// @param _newBatchesData Data of the new batches to be committed. function commitBatches( StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external; /// @notice same as `commitBatches` but with the chainId so ValidatorTimelock can sort the inputs. function commitBatchesSharedBridge( uint256 _chainId, StoredBatchInfo calldata _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external; /// @notice Batches commitment verification. /// @dev Only verifies batch commitments without any other processing. /// @param _prevBatch Stored data of the last committed batch. /// @param _committedBatches Stored data of the committed batches. /// @param _proof The zero knowledge proof. function proveBatches( StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) external; /// @notice same as `proveBatches` but with the chainId so ValidatorTimelock can sort the inputs. function proveBatchesSharedBridge( uint256 _chainId, StoredBatchInfo calldata _prevBatch, StoredBatchInfo[] calldata _committedBatches, ProofInput calldata _proof ) external; /// @notice The function called by the operator to finalize (execute) batches. It is responsible for: /// - Processing all pending operations (commpleting priority requests). /// - Finalizing this batch (i.e. allowing to withdraw funds from the system) /// @param _batchesData Data of the batches to be executed. function executeBatches(StoredBatchInfo[] calldata _batchesData) external; /// @notice same as `executeBatches` but with the chainId so ValidatorTimelock can sort the inputs. function executeBatchesSharedBridge(uint256 _chainId, StoredBatchInfo[] calldata _batchesData) external; /// @notice Reverts unexecuted batches /// @param _newLastBatch batch number after which batches should be reverted /// NOTE: Doesn't delete the stored data about batches, but only decreases /// counters that are responsible for the number of batches function revertBatches(uint256 _newLastBatch) external; /// @notice same as `revertBatches` but with the chainId so ValidatorTimelock can sort the inputs. function revertBatchesSharedBridge(uint256 _chainId, uint256 _newLastBatch) external; /// @notice Event emitted when a batch is committed /// @param batchNumber Number of the batch committed /// @param batchHash Hash of the L2 batch /// @param commitment Calculated input for the ZKsync circuit /// @dev It has the name "BlockCommit" and not "BatchCommit" due to backward compatibility considerations event BlockCommit(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment); /// @notice Event emitted when batches are verified /// @param previousLastVerifiedBatch Batch number of the previous last verified batch /// @param currentLastVerifiedBatch Batch number of the current last verified batch /// @dev It has the name "BlocksVerification" and not "BatchesVerification" due to backward compatibility considerations event BlocksVerification(uint256 indexed previousLastVerifiedBatch, uint256 indexed currentLastVerifiedBatch); /// @notice Event emitted when a batch is executed /// @param batchNumber Number of the batch executed /// @param batchHash Hash of the L2 batch /// @param commitment Verified input for the ZKsync circuit /// @dev It has the name "BlockExecution" and not "BatchExecution" due to backward compatibility considerations event BlockExecution(uint256 indexed batchNumber, bytes32 indexed batchHash, bytes32 indexed commitment); /// @notice Event emitted when batches are reverted /// @param totalBatchesCommitted Total number of committed batches after the revert /// @param totalBatchesVerified Total number of verified batches after the revert /// @param totalBatchesExecuted Total number of executed batches /// @dev It has the name "BlocksRevert" and not "BatchesRevert" due to backward compatibility considerations event BlocksRevert(uint256 totalBatchesCommitted, uint256 totalBatchesVerified, uint256 totalBatchesExecuted); }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @notice Part of the configuration parameters of ZKP circuits struct VerifierParams { bytes32 recursionNodeLevelVkHash; bytes32 recursionLeafLevelVkHash; bytes32 recursionCircuitsSetVksHash; } /// @title The interface of the Verifier contract, responsible for the zero knowledge proof verification. /// @author Matter Labs /// @custom:security-contact [email protected] interface IVerifier { /// @dev Verifies a zk-SNARK proof. /// @return A boolean value indicating whether the zk-SNARK proof is valid. /// Note: The function may revert execution instead of returning false in some cases. function verify( uint256[] calldata _publicInputs, uint256[] calldata _proof, uint256[] calldata _recursiveAggregationInput ) external view returns (bool); /// @notice Calculates a keccak256 hash of the runtime loaded verification keys. /// @return vkHash The keccak256 hash of the loaded verification keys. function verificationKeyHash() external pure returns (bytes32); }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the zkSync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; /// @title The interface of the ZKsync contract, responsible for the main ZKsync logic. /// @author Matter Labs /// @custom:security-contact [email protected] interface IZkSyncHyperchainBase { /// @return Returns facet name. function getName() external view returns (string memory); }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {Diamond} from "./libraries/Diamond.sol"; import {L2CanonicalTransaction} from "../common/Messaging.sol"; import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol"; /// @notice Struct that holds all data needed for initializing STM Proxy. /// @dev We use struct instead of raw parameters in `initialize` function to prevent "Stack too deep" error /// @param owner The address who can manage non-critical updates in the contract /// @param validatorTimelock The address that serves as consensus, i.e. can submit blocks to be processed /// @param chainCreationParams The struct that contains the fields that define how a new chain should be created /// @param protocolVersion The initial protocol version on the newly deployed chain struct StateTransitionManagerInitializeData { address owner; address validatorTimelock; ChainCreationParams chainCreationParams; uint256 protocolVersion; } /// @notice The struct that contains the fields that define how a new chain should be created /// within this STM. /// @param genesisUpgrade The address that is used in the diamond cut initialize address on chain creation /// @param genesisBatchHash Batch hash of the genesis (initial) batch /// @param genesisIndexRepeatedStorageChanges The serial number of the shortcut storage key for the genesis batch /// @param genesisBatchCommitment The zk-proof commitment for the genesis batch /// @param diamondCut The diamond cut for the first upgrade transaction on the newly deployed chain // solhint-disable-next-line gas-struct-packing struct ChainCreationParams { address genesisUpgrade; bytes32 genesisBatchHash; uint64 genesisIndexRepeatedStorageChanges; bytes32 genesisBatchCommitment; Diamond.DiamondCutData diamondCut; } interface IStateTransitionManager { /// @dev Emitted when a new Hyperchain is added event NewHyperchain(uint256 indexed _chainId, address indexed _hyperchainContract); /// @dev emitted when an chain registers and a SetChainIdUpgrade happens event SetChainIdUpgrade( address indexed _hyperchain, L2CanonicalTransaction _l2Transaction, uint256 indexed _protocolVersion ); /// @notice pendingAdmin is changed /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin); /// @notice Admin changed event NewAdmin(address indexed oldAdmin, address indexed newAdmin); /// @notice ValidatorTimelock changed event NewValidatorTimelock(address indexed oldValidatorTimelock, address indexed newValidatorTimelock); /// @notice chain creation parameters changed event NewChainCreationParams( address genesisUpgrade, bytes32 genesisBatchHash, uint64 genesisIndexRepeatedStorageChanges, bytes32 genesisBatchCommitment, bytes32 newInitialCutHash ); /// @notice New UpgradeCutHash event NewUpgradeCutHash(uint256 indexed protocolVersion, bytes32 indexed upgradeCutHash); /// @notice New UpgradeCutData event NewUpgradeCutData(uint256 indexed protocolVersion, Diamond.DiamondCutData diamondCutData); /// @notice New ProtocolVersion event NewProtocolVersion(uint256 indexed oldProtocolVersion, uint256 indexed newProtocolVersion); function BRIDGE_HUB() external view returns (address); function setPendingAdmin(address _newPendingAdmin) external; function acceptAdmin() external; function getAllHyperchains() external view returns (address[] memory); function getAllHyperchainChainIDs() external view returns (uint256[] memory); function getHyperchain(uint256 _chainId) external view returns (address); function storedBatchZero() external view returns (bytes32); function initialCutHash() external view returns (bytes32); function genesisUpgrade() external view returns (address); function upgradeCutHash(uint256 _protocolVersion) external view returns (bytes32); function protocolVersion() external view returns (uint256); function protocolVersionDeadline(uint256 _protocolVersion) external view returns (uint256); function protocolVersionIsActive(uint256 _protocolVersion) external view returns (bool); function initialize(StateTransitionManagerInitializeData calldata _initializeData) external; function setValidatorTimelock(address _validatorTimelock) external; function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external; function getChainAdmin(uint256 _chainId) external view returns (address); function createNewChain( uint256 _chainId, address _baseToken, address _sharedBridge, address _admin, bytes calldata _diamondCut ) external; function registerAlreadyDeployedHyperchain(uint256 _chainId, address _hyperchain) external; function setNewVersionUpgrade( Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion, uint256 _oldProtocolVersionDeadline, uint256 _newProtocolVersion ) external; function setUpgradeDiamondCut(Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion) external; function executeUpgrade(uint256 _chainId, Diamond.DiamondCutData calldata _diamondCut) external; function setPriorityTxMaxGasLimit(uint256 _chainId, uint256 _maxGasLimit) external; function freezeChain(uint256 _chainId) external; function unfreezeChain(uint256 _chainId) external; function setTokenMultiplier(uint256 _chainId, uint128 _nominator, uint128 _denominator) external; function changeFeeParams(uint256 _chainId, FeeParams calldata _newFeeParams) external; function setValidator(uint256 _chainId, address _validator, bool _active) external; function setPorterAvailability(uint256 _chainId, bool _zkPorterIsAvailable) external; function upgradeChainFromVersion( uint256 _chainId, uint256 _oldProtocolVersion, Diamond.DiamondCutData calldata _diamondCut ) external; function getSemverProtocolVersion() external view returns (uint32, uint32, uint32); }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol"; import {UncheckedMath} from "../../common/libraries/UncheckedMath.sol"; import {NoFunctionsForDiamondCut, UndefinedDiamondCutAction, AddressHasNoCode, FacetExists, RemoveFunctionFacetAddressZero, SelectorsMustAllHaveSameFreezability, NonEmptyCalldata, ReplaceFunctionFacetAddressZero, RemoveFunctionFacetAddressNotZero, DelegateCallFailed} from "../../common/L1ContractErrors.sol"; /// @author Matter Labs /// @custom:security-contact [email protected] /// @notice The helper library for managing the EIP-2535 diamond proxy. library Diamond { using UncheckedMath for uint256; using SafeCast for uint256; /// @dev Magic value that should be returned by diamond cut initialize contracts. /// @dev Used to distinguish calls to contracts that were supposed to be used as diamond initializer from other contracts. bytes32 internal constant DIAMOND_INIT_SUCCESS_RETURN_VALUE = 0x33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a2; // keccak256("diamond.zksync.init") - 1 /// @dev Storage position of `DiamondStorage` structure. bytes32 private constant DIAMOND_STORAGE_POSITION = 0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b; // keccak256("diamond.standard.diamond.storage") - 1; event DiamondCut(FacetCut[] facetCuts, address initAddress, bytes initCalldata); /// @dev Utility struct that contains associated facet & meta information of selector /// @param facetAddress address of the facet which is connected with selector /// @param selectorPosition index in `FacetToSelectors.selectors` array, where is selector stored /// @param isFreezable denotes whether the selector can be frozen. struct SelectorToFacet { address facetAddress; uint16 selectorPosition; bool isFreezable; } /// @dev Utility struct that contains associated selectors & meta information of facet /// @param selectors list of all selectors that belong to the facet /// @param facetPosition index in `DiamondStorage.facets` array, where is facet stored struct FacetToSelectors { bytes4[] selectors; uint16 facetPosition; } /// @notice The structure that holds all diamond proxy associated parameters /// @dev According to the EIP-2535 should be stored on a special storage key - `DIAMOND_STORAGE_POSITION` /// @param selectorToFacet A mapping from the selector to the facet address and its meta information /// @param facetToSelectors A mapping from facet address to its selectors with meta information /// @param facets The array of all unique facet addresses that belong to the diamond proxy /// @param isFrozen Denotes whether the diamond proxy is frozen and all freezable facets are not accessible struct DiamondStorage { mapping(bytes4 selector => SelectorToFacet selectorInfo) selectorToFacet; mapping(address facetAddress => FacetToSelectors facetInfo) facetToSelectors; address[] facets; bool isFrozen; } /// @dev Parameters for diamond changes that touch one of the facets /// @param facet The address of facet that's affected by the cut /// @param action The action that is made on the facet /// @param isFreezable Denotes whether the facet & all their selectors can be frozen /// @param selectors An array of unique selectors that belongs to the facet address // solhint-disable-next-line gas-struct-packing struct FacetCut { address facet; Action action; bool isFreezable; bytes4[] selectors; } /// @dev Structure of the diamond proxy changes /// @param facetCuts The set of changes (adding/removing/replacement) of implementation contracts /// @param initAddress The address that's delegate called after setting up new facet changes /// @param initCalldata Calldata for the delegate call to `initAddress` struct DiamondCutData { FacetCut[] facetCuts; address initAddress; bytes initCalldata; } /// @dev Type of change over diamond: add/replace/remove facets enum Action { Add, Replace, Remove } /// @return diamondStorage The pointer to the storage where all specific diamond proxy parameters stored function getDiamondStorage() internal pure returns (DiamondStorage storage diamondStorage) { bytes32 position = DIAMOND_STORAGE_POSITION; assembly { diamondStorage.slot := position } } /// @dev Add/replace/remove any number of selectors and optionally execute a function with delegatecall /// @param _diamondCut Diamond's facet changes and the parameters to optional initialization delegatecall function diamondCut(DiamondCutData memory _diamondCut) internal { FacetCut[] memory facetCuts = _diamondCut.facetCuts; address initAddress = _diamondCut.initAddress; bytes memory initCalldata = _diamondCut.initCalldata; uint256 facetCutsLength = facetCuts.length; for (uint256 i = 0; i < facetCutsLength; i = i.uncheckedInc()) { Action action = facetCuts[i].action; address facet = facetCuts[i].facet; bool isFacetFreezable = facetCuts[i].isFreezable; bytes4[] memory selectors = facetCuts[i].selectors; if (selectors.length == 0) { revert NoFunctionsForDiamondCut(); } if (action == Action.Add) { _addFunctions(facet, selectors, isFacetFreezable); } else if (action == Action.Replace) { _replaceFunctions(facet, selectors, isFacetFreezable); } else if (action == Action.Remove) { _removeFunctions(facet, selectors); } else { revert UndefinedDiamondCutAction(); } } _initializeDiamondCut(initAddress, initCalldata); emit DiamondCut(facetCuts, initAddress, initCalldata); } /// @dev Add new functions to the diamond proxy /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array function _addFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private { DiamondStorage storage ds = getDiamondStorage(); // Facet with no code cannot be added. // This check also verifies that the facet does not have zero address, since it is the // address with which 0x00000000 selector is associated. if (_facet.code.length == 0) { revert AddressHasNoCode(_facet); } // Add facet to the list of facets if the facet address is new one _saveFacetIfNew(_facet); uint256 selectorsLength = _selectors.length; for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) { bytes4 selector = _selectors[i]; SelectorToFacet memory oldFacet = ds.selectorToFacet[selector]; if (oldFacet.facetAddress != address(0)) { revert FacetExists(selector, oldFacet.facetAddress); } _addOneFunction(_facet, selector, _isFacetFreezable); } } /// @dev Change associated facets to already known function selectors /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array function _replaceFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private { DiamondStorage storage ds = getDiamondStorage(); // Facet with no code cannot be added. // This check also verifies that the facet does not have zero address, since it is the // address with which 0x00000000 selector is associated. if (_facet.code.length == 0) { revert AddressHasNoCode(_facet); } uint256 selectorsLength = _selectors.length; for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) { bytes4 selector = _selectors[i]; SelectorToFacet memory oldFacet = ds.selectorToFacet[selector]; // it is impossible to replace the facet with zero address if (oldFacet.facetAddress == address(0)) { revert ReplaceFunctionFacetAddressZero(); } _removeOneFunction(oldFacet.facetAddress, selector); // Add facet to the list of facets if the facet address is a new one _saveFacetIfNew(_facet); _addOneFunction(_facet, selector, _isFacetFreezable); } } /// @dev Remove association with function and facet /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array function _removeFunctions(address _facet, bytes4[] memory _selectors) private { DiamondStorage storage ds = getDiamondStorage(); // facet address must be zero if (_facet != address(0)) { revert RemoveFunctionFacetAddressNotZero(_facet); } uint256 selectorsLength = _selectors.length; for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) { bytes4 selector = _selectors[i]; SelectorToFacet memory oldFacet = ds.selectorToFacet[selector]; // Can't delete a non-existent facet if (oldFacet.facetAddress == address(0)) { revert RemoveFunctionFacetAddressZero(); } _removeOneFunction(oldFacet.facetAddress, selector); } } /// @dev Add address to the list of known facets if it is not on the list yet /// NOTE: should be called ONLY before adding a new selector associated with the address function _saveFacetIfNew(address _facet) private { DiamondStorage storage ds = getDiamondStorage(); uint256 selectorsLength = ds.facetToSelectors[_facet].selectors.length; // If there are no selectors associated with facet then save facet as new one if (selectorsLength == 0) { ds.facetToSelectors[_facet].facetPosition = ds.facets.length.toUint16(); ds.facets.push(_facet); } } /// @dev Add one function to the already known facet /// NOTE: It is expected but NOT enforced that: /// - `_facet` is NON-ZERO address /// - `_facet` is already stored address in `DiamondStorage.facets` /// - `_selector` is NOT associated by another facet function _addOneFunction(address _facet, bytes4 _selector, bool _isSelectorFreezable) private { DiamondStorage storage ds = getDiamondStorage(); uint16 selectorPosition = (ds.facetToSelectors[_facet].selectors.length).toUint16(); // if selectorPosition is nonzero, it means it is not a new facet // so the freezability of the first selector must be matched to _isSelectorFreezable // so all the selectors in a facet will have the same freezability if (selectorPosition != 0) { bytes4 selector0 = ds.facetToSelectors[_facet].selectors[0]; if (_isSelectorFreezable != ds.selectorToFacet[selector0].isFreezable) { revert SelectorsMustAllHaveSameFreezability(); } } ds.selectorToFacet[_selector] = SelectorToFacet({ facetAddress: _facet, selectorPosition: selectorPosition, isFreezable: _isSelectorFreezable }); ds.facetToSelectors[_facet].selectors.push(_selector); } /// @dev Remove one associated function with facet /// NOTE: It is expected but NOT enforced that `_facet` is NON-ZERO address function _removeOneFunction(address _facet, bytes4 _selector) private { DiamondStorage storage ds = getDiamondStorage(); // Get index of `FacetToSelectors.selectors` of the selector and last element of array uint256 selectorPosition = ds.selectorToFacet[_selector].selectorPosition; uint256 lastSelectorPosition = ds.facetToSelectors[_facet].selectors.length - 1; // If the selector is not at the end of the array then move the last element to the selector position if (selectorPosition != lastSelectorPosition) { bytes4 lastSelector = ds.facetToSelectors[_facet].selectors[lastSelectorPosition]; ds.facetToSelectors[_facet].selectors[selectorPosition] = lastSelector; ds.selectorToFacet[lastSelector].selectorPosition = selectorPosition.toUint16(); } // Remove last element from the selectors array ds.facetToSelectors[_facet].selectors.pop(); // Finally, clean up the association with facet delete ds.selectorToFacet[_selector]; // If there are no selectors for facet then remove the facet from the list of known facets if (lastSelectorPosition == 0) { _removeFacet(_facet); } } /// @dev remove facet from the list of known facets /// NOTE: It is expected but NOT enforced that there are no selectors associated with `_facet` function _removeFacet(address _facet) private { DiamondStorage storage ds = getDiamondStorage(); // Get index of `DiamondStorage.facets` of the facet and last element of array uint256 facetPosition = ds.facetToSelectors[_facet].facetPosition; uint256 lastFacetPosition = ds.facets.length - 1; // If the facet is not at the end of the array then move the last element to the facet position if (facetPosition != lastFacetPosition) { address lastFacet = ds.facets[lastFacetPosition]; ds.facets[facetPosition] = lastFacet; ds.facetToSelectors[lastFacet].facetPosition = facetPosition.toUint16(); } // Remove last element from the facets array ds.facets.pop(); } /// @dev Delegates call to the initialization address with provided calldata /// @dev Used as a final step of diamond cut to execute the logic of the initialization for changed facets function _initializeDiamondCut(address _init, bytes memory _calldata) private { if (_init == address(0)) { // Non-empty calldata for zero address if (_calldata.length != 0) { revert NonEmptyCalldata(); } } else { // Do not check whether `_init` is a contract since later we check that it returns data. (bool success, bytes memory data) = _init.delegatecall(_calldata); if (!success) { // If the returndata is too small, we still want to produce some meaningful error if (data.length < 4) { revert DelegateCallFailed(data); } assembly { revert(add(data, 0x20), mload(data)) } } // Check that called contract returns magic value to make sure that contract logic // supposed to be used as diamond cut initializer. if (data.length != 32) { revert DelegateCallFailed(data); } if (abi.decode(data, (bytes32)) != DIAMOND_INIT_SUCCESS_RETURN_VALUE) { revert DelegateCallFailed(data); } } } }
// SPDX-License-Identifier: MIT // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.21; import {QueueIsEmpty} from "../../common/L1ContractErrors.sol"; /// @notice The structure that contains meta information of the L2 transaction that was requested from L1 /// @dev The weird size of fields was selected specifically to minimize the structure storage size /// @param canonicalTxHash Hashed L2 transaction data that is needed to process it /// @param expirationTimestamp Expiration timestamp for this request (must be satisfied before) /// @param layer2Tip Additional payment to the validator as an incentive to perform the operation struct PriorityOperation { bytes32 canonicalTxHash; uint64 expirationTimestamp; uint192 layer2Tip; } /// @author Matter Labs /// @custom:security-contact [email protected] /// @dev The library provides the API to interact with the priority queue container /// @dev Order of processing operations from queue - FIFO (Fist in - first out) library PriorityQueue { using PriorityQueue for Queue; /// @notice Container that stores priority operations /// @param data The inner mapping that saves priority operation by its index /// @param head The pointer to the first unprocessed priority operation, equal to the tail if the queue is empty /// @param tail The pointer to the free slot struct Queue { mapping(uint256 priorityOpId => PriorityOperation priorityOp) data; uint256 tail; uint256 head; } /// @notice Returns zero if and only if no operations were processed from the queue /// @return Index of the oldest priority operation that wasn't processed yet function getFirstUnprocessedPriorityTx(Queue storage _queue) internal view returns (uint256) { return _queue.head; } /// @return The total number of priority operations that were added to the priority queue, including all processed ones function getTotalPriorityTxs(Queue storage _queue) internal view returns (uint256) { return _queue.tail; } /// @return The total number of unprocessed priority operations in a priority queue function getSize(Queue storage _queue) internal view returns (uint256) { return uint256(_queue.tail - _queue.head); } /// @return Whether the priority queue contains no operations function isEmpty(Queue storage _queue) internal view returns (bool) { return _queue.tail == _queue.head; } /// @notice Add the priority operation to the end of the priority queue function pushBack(Queue storage _queue, PriorityOperation memory _operation) internal { // Save value into the stack to avoid double reading from the storage uint256 tail = _queue.tail; _queue.data[tail] = _operation; _queue.tail = tail + 1; } /// @return The first unprocessed priority operation from the queue function front(Queue storage _queue) internal view returns (PriorityOperation memory) { // priority queue is empty if (_queue.isEmpty()) { revert QueueIsEmpty(); } return _queue.data[_queue.head]; } /// @notice Remove the first unprocessed priority operation from the queue /// @return priorityOperation that was popped from the priority queue function popFront(Queue storage _queue) internal returns (PriorityOperation memory priorityOperation) { // priority queue is empty if (_queue.isEmpty()) { revert QueueIsEmpty(); } // Save value into the stack to avoid double reading from the storage uint256 head = _queue.head; priorityOperation = _queue.data[head]; delete _queue.data[head]; _queue.head = head + 1; } }
{ "optimizer": { "enabled": true, "runs": 9999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"BatchHashMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedBatchNumber","type":"uint256"},{"internalType":"uint256","name":"providedBatchNumber","type":"uint256"}],"name":"BatchNumberMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bool","name":"blobHashEmpty","type":"bool"},{"internalType":"bool","name":"blobCommitmentEmpty","type":"bool"}],"name":"BlobHashCommitmentError","type":"error"},{"inputs":[],"name":"CalldataLengthTooBig","type":"error"},{"inputs":[],"name":"CanOnlyProcessOneBatch","type":"error"},{"inputs":[],"name":"CantExecuteUnprovenBatches","type":"error"},{"inputs":[],"name":"CantRevertExecutedBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"EmptyBlobVersionHash","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"}],"name":"HashMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"logKey","type":"uint256"}],"name":"InvalidLogSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"numCommitments","type":"uint256"},{"internalType":"uint256","name":"numHashes","type":"uint256"}],"name":"InvalidNumberOfBlobs","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidProtocolVersion","type":"error"},{"inputs":[],"name":"InvalidPubdataCommitmentsSize","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expectedHash","type":"bytes32"},{"internalType":"bytes32","name":"provided","type":"bytes32"}],"name":"InvalidPubdataHash","type":"error"},{"inputs":[],"name":"InvalidPubdataLength","type":"error"},{"inputs":[],"name":"InvalidPubdataMode","type":"error"},{"inputs":[],"name":"L2TimestampTooBig","type":"error"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"LogAlreadyProcessed","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"MissingSystemLogs","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"NonEmptyBlobVersionHash","type":"error"},{"inputs":[],"name":"NonIncreasingTimestamp","type":"error"},{"inputs":[],"name":"NonSequentialBatch","type":"error"},{"inputs":[],"name":"NotInitializedReentrancyGuard","type":"error"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"PointEvalCallFailed","type":"error"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"PointEvalFailed","type":"error"},{"inputs":[],"name":"PriorityOperationsRollingHashMismatch","type":"error"},{"inputs":[],"name":"PubdataCommitmentsEmpty","type":"error"},{"inputs":[],"name":"PubdataCommitmentsTooBig","type":"error"},{"inputs":[],"name":"QueueIsEmpty","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"RevertedBatchNotAfterNewLastBatch","type":"error"},{"inputs":[],"name":"SystemLogsSizeTooBig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedTimestamp","type":"uint256"},{"internalType":"uint256","name":"actualTimestamp","type":"uint256"}],"name":"TimeNotReached","type":"error"},{"inputs":[],"name":"TimestampError","type":"error"},{"inputs":[],"name":"TooManyBlobs","type":"error"},{"inputs":[],"name":"TxHashMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"logKey","type":"uint256"}],"name":"UnexpectedSystemLog","type":"error"},{"inputs":[],"name":"UpgradeBatchNumberIsNotZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"ValueMismatch","type":"error"},{"inputs":[],"name":"VerifiedBatchesExceedsCommittedBatches","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"batchNumber","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"BlockCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"batchNumber","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"BlockExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalBatchesCommitted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBatchesVerified","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBatchesExecuted","type":"uint256"}],"name":"BlocksRevert","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"previousLastVerifiedBatch","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"currentLastVerifiedBatch","type":"uint256"}],"name":"BlocksVerification","type":"event"},{"inputs":[{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo","name":"_lastCommittedBatchData","type":"tuple"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"bootloaderHeapInitialContentsHash","type":"bytes32"},{"internalType":"bytes32","name":"eventsQueueStateHash","type":"bytes32"},{"internalType":"bytes","name":"systemLogs","type":"bytes"},{"internalType":"bytes","name":"pubdataCommitments","type":"bytes"}],"internalType":"struct IExecutor.CommitBatchInfo[]","name":"_newBatchesData","type":"tuple[]"}],"name":"commitBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo","name":"_lastCommittedBatchData","type":"tuple"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"bytes32","name":"newStateRoot","type":"bytes32"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"bootloaderHeapInitialContentsHash","type":"bytes32"},{"internalType":"bytes32","name":"eventsQueueStateHash","type":"bytes32"},{"internalType":"bytes","name":"systemLogs","type":"bytes"},{"internalType":"bytes","name":"pubdataCommitments","type":"bytes"}],"internalType":"struct IExecutor.CommitBatchInfo[]","name":"_newBatchesData","type":"tuple[]"}],"name":"commitBatchesSharedBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo[]","name":"_batchesData","type":"tuple[]"}],"name":"executeBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo[]","name":"_batchesData","type":"tuple[]"}],"name":"executeBatchesSharedBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo","name":"_prevBatch","type":"tuple"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo[]","name":"_committedBatches","type":"tuple[]"},{"components":[{"internalType":"uint256[]","name":"recursiveAggregationInput","type":"uint256[]"},{"internalType":"uint256[]","name":"serializedProof","type":"uint256[]"}],"internalType":"struct IExecutor.ProofInput","name":"_proof","type":"tuple"}],"name":"proveBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo","name":"_prevBatch","type":"tuple"},{"components":[{"internalType":"uint64","name":"batchNumber","type":"uint64"},{"internalType":"bytes32","name":"batchHash","type":"bytes32"},{"internalType":"uint64","name":"indexRepeatedStorageChanges","type":"uint64"},{"internalType":"uint256","name":"numberOfLayer1Txs","type":"uint256"},{"internalType":"bytes32","name":"priorityOperationsHash","type":"bytes32"},{"internalType":"bytes32","name":"l2LogsTreeRoot","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"internalType":"struct IExecutor.StoredBatchInfo[]","name":"_committedBatches","type":"tuple[]"},{"components":[{"internalType":"uint256[]","name":"recursiveAggregationInput","type":"uint256[]"},{"internalType":"uint256[]","name":"serializedProof","type":"uint256[]"}],"internalType":"struct IExecutor.ProofInput","name":"_proof","type":"tuple"}],"name":"proveBatchesSharedBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLastBatch","type":"uint256"}],"name":"revertBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_newLastBatch","type":"uint256"}],"name":"revertBatchesSharedBridge","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b506137e28061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063701f58c51161007257806397c09d341161005857806397c09d3414610156578063c37533bb14610169578063c3d93e7c1461017c575f80fd5b8063701f58c5146101305780637f61885c14610143575f80fd5b80630f23da43146100a357806317d7de7c146100b85780636edd4f121461010a5780636f497ac61461011d575b5f80fd5b6100b66100b1366004612e2a565b61018f565b005b6100f46040518060400160405280600d81526020017f4578656375746f7246616365740000000000000000000000000000000000000081525081565b6040516101019190612eb5565b60405180910390f35b6100b6610118366004612f27565b6102ca565b6100b661012b366004612fc1565b610412565b6100b661013e366004613009565b61054a565b6100b661015136600461305e565b610660565b6100b66101643660046130d7565b610770565b6100b66101773660046130ee565b6108cb565b6100b661018a366004613170565b610a07565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036101eb576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610225576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610298576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6102a182610b15565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610326576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610360576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166103ce576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6103e76103e0368690038601866131f8565b8484610bfa565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f81900361046e576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146104a8576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610516576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6105208383610dc1565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036105a6576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146105e0576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff1661064e576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6105206103e0368690038601866131f8565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036106bc576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146106f6576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610764576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6103e785858585610f1b565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036107cc576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610806576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff161580156108615750602a5473ffffffffffffffffffffffffffffffffffffffff163314155b1561089a576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6108a382610b15565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610927576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610961576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166109cf576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6109db85858585610f1b565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610a63576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610a9d576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610b0b576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6102a18383610dc1565b600d548110610b50576040517f9a67c1cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54811015610b8c576040517fe18cb38300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c54811015610b9c57600c8190555b600d819055602354811015610bb0575f6023555b600d54600c54600b5460408051938452602084019290925282820152517f8bd4b15ea7d1bc41ea9abc3fc487ccb89cd678a00786584714faa9d751c84ee59181900360600190a150565b602a546021546040517fdef9d6af00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163def9d6af91610c559160040190815260200190565b602060405180830381865afa158015610c70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9491906132b9565b610cca576040517f5428eae700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610d04576040517fe85392f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0d836110fa565b600d545f908152600e602052604090205414610d7857600d545f908152600e6020526040902054610d3d846110fa565b6040517f55ad3fd30000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161028f565b602254801580610d89575060235415155b15610d9e57610d9984848461118a565b610daa565b610daa84848484611233565b600d54610db8908390613305565b600d5550505050565b805f5b81811015610e9f57610dfe848483818110610de157610de1613318565b90506101000201803603810190610df891906131f8565b82611361565b838382818110610e1057610e10613318565b9050610100020160e00135848483818110610e2d57610e2d613318565b9050610100020160200135858584818110610e4a57610e4a613318565b610e61926020610100909202019081019150613345565b67ffffffffffffffff167f2402307311a4d6604e4e7b4c8a15a7e1213edb39c16a31efa70afb06030d316560405160405180910390a4600101610dc4565b50600b545f90610eb0908390613305565b600b819055600c54909150811115610ef3576040517ec6ead200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6023548015801590610f055750818111155b15610f14575f60228190556023555b5050505050565b600c54825f8167ffffffffffffffff811115610f3957610f396131af565b604051908082528060200260200182016040528015610f62578160200160208202803683370190505b505f848152600e6020526040902054909150610f8b610f86368a90038a018a6131f8565b6110fa565b14610fb0575f838152600e6020526040902054610d3d610f86368a90038a018a6131f8565b60e08701355f5b8381101561107957600185015f818152600e6020526040902054909550611000898984818110610fe957610fe9613318565b90506101000201803603810190610f8691906131f8565b14611028575f858152600e6020526040902054610d3d898984818110610fe957610fe9613318565b5f88888381811061103b5761103b613318565b9050610100020160e001359050611052838261145d565b84838151811061106457611064613318565b60209081029190910101529150600101610fb7565b50600d548411156110b6576040517fe102246900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110c0828661149f565b600c546040518591907f22c9005dd88c18b552a1cd7e8b3b937fcde9ca69213c1f658f54d572e4877a81905f90a3505050600c5550505050565b5f8160405160200161116d91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604051602081830303815290604052805190602001209050919050565b5f5b8181101561122d576111c2848484848181106111aa576111aa613318565b90506020028101906111bc919061335e565b5f6115af565b93506111cd846110fa565b845167ffffffffffffffff9081165f908152600e602090815260408083209490945560e088015190880151885194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a460010161118c565b50505050565b6023541561126d576040517ff093c2e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82825f81811061127f5761127f613318565b9050602002810190611291919061335e565b61129f906020810190613345565b67ffffffffffffffff166023555f5b82811015610f14575f81156112c3575f6112c5565b825b90506112f5868686858181106112dd576112dd613318565b90506020028101906112ef919061335e565b836115af565b9550611300866110fa565b865167ffffffffffffffff9081165f908152600e602090815260408083209490945560e08a0151908a01518a5194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a4506001016112ae565b8151600b5467ffffffffffffffff9091169061137e908390613305565b611389906001613305565b81146113c1576040517f0105f9c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f818152600e60205260409020546113d8846110fa565b146113f4575f818152600e6020526040902054610d3d846110fa565b5f6114028460600151611b9d565b905083608001518114611441576040517fd5a9901400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060a0909201515f928352600f60205260409092209190915550565b5f6020838360405160200161147c929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c901c90505b92915050565b81516001146114da576040517fe85392f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a545f9073ffffffffffffffffffffffffffffffffffffffff166387d9d02384611508602086018661339a565b611512878061339a565b6040518663ffffffff1660e01b8152600401611532959493929190613447565b602060405180830381865afa15801561154d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157191906132b9565b9050806115aa576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915283516115fc9060016134b7565b67ffffffffffffffff166116136020850185613345565b67ffffffffffffffff161461168257835161162f9060016134b7565b61163c6020850185613345565b6040517fbd4455ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161028f565b5f6116916101208501856134d8565b5f8181106116a1576116a1613318565b60265492013560f81c92505060ff1660018160018111156116c4576116c4613539565b141580156116d4575060ff821615155b80156116e4575060ff8216600114155b1561171b576040517fc5d0907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6117268686611c23565b60408051600680825260e082019092529192505f91906020820160c080368337019050509050600183600181111561176057611760613539565b03611802576117736101208801886134d8565b90506001146117ae576040517fcf102c5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075b600c60ff8216116117fc5760e08301515f906117ce600784613566565b60ff16815181106117e1576117e1613318565b60209081029190910101526117f58161357f565b90506117b1565b506119be565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff85160161185c5761185561183d6101208901896134d8565b61184b91600190829061359d565b8460e001516123c4565b90506119be565b60ff84166119be576201f0006118766101208901896134d8565b905011156118b0576040517f9094af7e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6118bf6101208901896134d8565b60019060206118d26101208d018d6134d8565b6118dd9291506135c4565b926118ea9392919061359d565b6040516118f89291906135d7565b604051809103902090508083606001511461194f5760608301516040517f5513177c00000000000000000000000000000000000000000000000000000000815261028f918391600401918252602082015260400190565b61195d6101208901896134d8565b602061196d6101208c018c6134d8565b6119789291506135c4565b906119876101208c018c6134d8565b61199594909392915061359d565b61199e916135e6565b825f815181106119b0576119b0613318565b602002602001018181525050505b8160400151886020015114611a1457816040015188602001516040517f0b08d5be00000000000000000000000000000000000000000000000000000000815260040161028f929190918252602082015260400190565b8660a00135826020015114611a685760208201516040517f0b08d5be000000000000000000000000000000000000000000000000000000008152600481019190915260a0880135602482015260440161028f565b8151608088013514611ab65781516040517f626ade3000000000000000000000000000000000000000000000000000000000815260048101919091526080880135602482015260440161028f565b60c0820151611ae390611acf60408a0160208b01613345565b67ffffffffffffffff168a60c0015161273d565b5f611af8888460800151848660e00151612869565b60408051610100810190915290915080611b1560208b018b613345565b67ffffffffffffffff16815260608a0180356020830152604091820191611b3e91908c01613345565b67ffffffffffffffff168152602001896080013581526020018960a0013581526020018460a001518152602001896020016020810190611b7e9190613345565b67ffffffffffffffff1681526020019190915298975050505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f5b82811015611c1d575f611bd36010612927565b8051604051919250611bf391859190602001918252602082015260400190565b60405160208183030381529060405280519060200120925050611c168160010190565b9050611bc0565b50919050565b6040805161010080820183525f8083526020830181905292820183905260608083018490526080830184905260a0830184905260c0830184905260e0830152909190611c71908501856134d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525092935060069250611cb0915050565b604051908082528060200260200182016040528015611cd9578160200160208202803683370190505b5060e083015280515f90815b81811015612324575f611d0b85611cfd600485613305565b601491810182015192910190565b5090505f611d2c86611d1e601886613305565b602091810182015192910190565b5090505f611d3f87611d1e603887613305565b509050600160ff83161b861615611d87576040517f1b6825bb00000000000000000000000000000000000000000000000000000000815260ff8316600482015260240161028f565b600160ff83161b8617955081611e135773ffffffffffffffffffffffffffffffffffffffff831661800814611e07576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60a08801819052612319565b60018203611e975773ffffffffffffffffffffffffffffffffffffffff831661800814611e8b576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60608801819052612319565b60028203611f1b5773ffffffffffffffffffffffffffffffffffffffff831661800814611f0f576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60808801819052612319565b60038203611f9f5773ffffffffffffffffffffffffffffffffffffffff831661800b14611f93576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60c08801819052612319565b600482036120235773ffffffffffffffffffffffffffffffffffffffff831661800b14612017576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60408801819052612319565b600582036120a75773ffffffffffffffffffffffffffffffffffffffff83166180011461209b576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60208801819052612319565b600682036121275773ffffffffffffffffffffffffffffffffffffffff83166180011461211f576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b808852612319565b600782101580156121395750600c8211155b156122255773ffffffffffffffffffffffffffffffffffffffff8316618011146121ae576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b5f6121ba600784613566565b905060068160ff16106121f9576040517ff640f0e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818960e001518260ff168151811061221357612213613318565b60200260200101818152505050612319565b600d82036122db5773ffffffffffffffffffffffffffffffffffffffff83166180011461229d576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b8089146122d6576040517f4c99107800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612319565b600d821115612319576040517f6aa398800000000000000000000000000000000000000000000000000000000081526004810183905260240161028f565b505050605801611ce5565b50846123755781611fff14612370576040517ffa44b527000000000000000000000000000000000000000000000000000000008152611fff60048201526024810183905260440161028f565b6123bb565b81613fff146123bb576040517ffa44b527000000000000000000000000000000000000000000000000000000008152613fff60048201526024810183905260440161028f565b50505092915050565b60605f838103612400576040517f53dee67b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61240c60066090613622565b841115612445576040517f7734c31a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612450609085613639565b15612487576040517f53e6d04d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600680825260e08201909252906020820160c0803683370190505091505f5b848110156125ca578149806124ee576040517ffc7ab1d30000000000000000000000000000000000000000000000000000000081526004810184905260240161028f565b5f8783886124fd601083613305565b9261250a9392919061359d565b61251391613671565b60801c905061254882828a8a61252a601089613305565b9061253660908a613305565b926125439392919061359d565b612a11565b81888489612557603083613305565b926125649392919061359d565b604051602001612576939291906136b9565b6040516020818303038152906040528051906020012085858151811061259e5761259e613318565b60209081029190910101526125b2846136d2565b935050506090816125c39190613305565b90506124aa565b5080498015612608576040517f92290acc0000000000000000000000000000000000000000000000000000000081526004810183905260240161028f565b5f5b6006811015612733575f801b85828151811061262857612628613318565b602002602001015114801561265857505f801b84828151811061264d5761264d613318565b602002602001015114155b806126a357505f801b85828151811061267357612673613318565b6020026020010151141580156126a357505f801b84828151811061269957612699613318565b6020026020010151145b1561272b57805f801b8683815181106126be576126be613318565b6020026020010151145f801b8684815181106126dc576126dc613318565b60209081029190910101516040517fafd53e2f0000000000000000000000000000000000000000000000000000000081526004810194909452911515602484015214604482015260640161028f565b60010161260a565b5050509392505050565b608083901c82811461277b576040517f2d50c33b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082106127b4576040517fd018e08e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416816127d56203f480426135c4565b111561282457816127e96203f480426135c4565b6040517f087539820000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161028f565b612830610e1042613305565b811115610f14576040517ffb5c22e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8061287486612b90565b8051906020012090505f6128cb60185460195460175460405160ff909216151560f81b6020830152602182015260418101829052606181018290526060919060810160405160208183030381529060405291505090565b8051906020012090505f6128e188888888612c01565b8051602091820120604080519283018690528201849052606082018190529150608001604051602081830303815290604052805190602001209350505050949350505050565b604080516060810182525f80825260208201819052918101919091526002820154600183015403612984576040517f63c3654900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060028101545f818152602083815260408083208151606081018352815481526001808301805467ffffffffffffffff81168488015268010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff16948301949094528686529387905290849055929055909190612a03908290613305565b836002018190555050919050565b5f84848484604051602001612a299493929190613709565b60405160208183030381529060405290505f80600a73ffffffffffffffffffffffffffffffffffffffff1683604051612a629190613729565b5f60405180830381855afa9150503d805f8114612a9a576040519150601f19603f3d011682016040523d82523d5f602084013e612a9f565b606091505b509150915081612add57826040517f8d5851de00000000000000000000000000000000000000000000000000000000815260040161028f9190612eb5565b5f81806020019051810190612af2919061373a565b9150507f73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff000000018114612b8657604080516020810183905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f4daa985d00000000000000000000000000000000000000000000000000000000825261028f91600401612eb5565b5050505050505050565b6060612ba182820160408401613345565b60405160c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166020820152606083013560288201525f6048820181905260508201526070016040516020818303038152906040529050919050565b6060612c106058610200613622565b612c1b906004613305565b612c296101008701876134d8565b90501115612c63576040517fae43b42400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c726101008701876134d8565b604051612c809291906135d7565b6040518091039020905080858760c001358860e00135612ca08888612cce565b604051602001612cb495949392919061375c565b604051602081830303815290604052915050949350505050565b606060068351141580612ce357506006825114155b15612d2e57825182516040517fd8e9405c000000000000000000000000000000000000000000000000000000008152600660048201526024810192909252604482015260640161028f565b612d3a60106002613622565b67ffffffffffffffff811115612d5257612d526131af565b604051908082528060200260200182016040528015612d7b578160200160208202803683370190505b5090505f5b6006811015612e2357828181518110612d9b57612d9b613318565b602002602001015182826002612db19190613622565b81518110612dc157612dc1613318565b602002602001018181525050838181518110612ddf57612ddf613318565b602002602001015182826002612df59190613622565b612e00906001613305565b81518110612e1057612e10613318565b6020908102919091010152600101612d80565b5092915050565b5f8060408385031215612e3b575f80fd5b50508035926020909101359150565b5f5b83811015612e64578181015183820152602001612e4c565b50505f910152565b5f8151808452612e83816020860160208601612e4a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612ec76020830184612e6c565b9392505050565b5f6101008284031215611c1d575f80fd5b5f8083601f840112612eef575f80fd5b50813567ffffffffffffffff811115612f06575f80fd5b6020830191508360208260051b8501011115612f20575f80fd5b9250929050565b5f805f806101408587031215612f3b575f80fd5b84359350612f4c8660208701612ece565b925061012085013567ffffffffffffffff811115612f68575f80fd5b612f7487828801612edf565b95989497509550505050565b5f8083601f840112612f90575f80fd5b50813567ffffffffffffffff811115612fa7575f80fd5b6020830191508360208260081b8501011115612f20575f80fd5b5f805f60408486031215612fd3575f80fd5b83359250602084013567ffffffffffffffff811115612ff0575f80fd5b612ffc86828701612f80565b9497909650939450505050565b5f805f610120848603121561301c575f80fd5b6130268585612ece565b925061010084013567ffffffffffffffff811115613042575f80fd5b612ffc86828701612edf565b5f60408284031215611c1d575f80fd5b5f805f806101408587031215613072575f80fd5b61307c8686612ece565b935061010085013567ffffffffffffffff80821115613099575f80fd5b6130a588838901612f80565b90955093506101208701359150808211156130be575f80fd5b506130cb8782880161304e565b91505092959194509250565b5f602082840312156130e7575f80fd5b5035919050565b5f805f805f6101608688031215613103575f80fd5b853594506131148760208801612ece565b935061012086013567ffffffffffffffff80821115613131575f80fd5b61313d89838a01612f80565b9095509350610140880135915080821115613156575f80fd5b506131638882890161304e565b9150509295509295909350565b5f8060208385031215613181575f80fd5b823567ffffffffffffffff811115613197575f80fd5b6131a385828601612f80565b90969095509350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b803567ffffffffffffffff811681146131f3575f80fd5b919050565b5f61010080838503121561320a575f80fd5b6040519081019067ffffffffffffffff82118183101715613252577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b8160405261325f846131dc565b815260208401356020820152613277604085016131dc565b6040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e084013560e0820152809250505092915050565b5f602082840312156132c9575f80fd5b81518015158114612ec7575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611499576114996132d8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215613355575f80fd5b612ec7826131dc565b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613390575f80fd5b9190910192915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126133cd575f80fd5b83018035915067ffffffffffffffff8211156133e7575f80fd5b6020019150600581901b3603821315612f20575f80fd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561342e575f80fd5b8260051b80836020870137939093016020019392505050565b606080825286519082018190525f906020906080840190828a01845b8281101561347f57815184529284019290840190600101613463565b505050838103602085015261349581888a6133fe565b91505082810360408401526134ab8185876133fe565b98975050505050505050565b67ffffffffffffffff818116838216019080821115612e2357612e236132d8565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261350b575f80fd5b83018035915067ffffffffffffffff821115613525575f80fd5b602001915036819003821315612f20575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60ff8281168282160390811115611499576114996132d8565b5f60ff821660ff8103613594576135946132d8565b60010192915050565b5f80858511156135ab575f80fd5b838611156135b7575f80fd5b5050820193919092039150565b81810381811115611499576114996132d8565b818382375f9101908152919050565b80356020831015611499577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b8082028115828204841417611499576114996132d8565b5f8261366c577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081358181169160108510156136b15780818660100360031b1b83161692505b505092915050565b838152818360208301375f910160200190815292915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613702576137026132d8565b5060010190565b848152836020820152818360408301375f91016040019081529392505050565b5f8251613390818460208701612e4a565b5f806040838503121561374b575f80fd5b505080516020909101519092909150565b8581525f6020866020840152856040840152846060840152608083018451602086015f5b8281101561379c57815184529284019290840190600101613780565b50919a995050505050505050505056fea26469706673582212207954c631350351c91c2323f477635727cc5f13d0752ee1f0dffd18e8256c95fe64736f6c63430008180033
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063701f58c51161007257806397c09d341161005857806397c09d3414610156578063c37533bb14610169578063c3d93e7c1461017c575f80fd5b8063701f58c5146101305780637f61885c14610143575f80fd5b80630f23da43146100a357806317d7de7c146100b85780636edd4f121461010a5780636f497ac61461011d575b5f80fd5b6100b66100b1366004612e2a565b61018f565b005b6100f46040518060400160405280600d81526020017f4578656375746f7246616365740000000000000000000000000000000000000081525081565b6040516101019190612eb5565b60405180910390f35b6100b6610118366004612f27565b6102ca565b6100b661012b366004612fc1565b610412565b6100b661013e366004613009565b61054a565b6100b661015136600461305e565b610660565b6100b66101643660046130d7565b610770565b6100b66101773660046130ee565b6108cb565b6100b661018a366004613170565b610a07565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036101eb576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610225576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610298576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6102a182610b15565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610326576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610360576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166103ce576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6103e76103e0368690038601866131f8565b8484610bfa565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f81900361046e576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146104a8576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610516576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6105208383610dc1565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036105a6576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146105e0576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff1661064e576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6105206103e0368690038601866131f8565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036106bc576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181146106f6576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610764576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6103e785858585610f1b565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f8190036107cc576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610806576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff161580156108615750602a5473ffffffffffffffffffffffffffffffffffffffff163314155b1561089a576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6108a382610b15565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610927576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610961576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166109cf576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6109db85858585610f1b565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4545f819003610a63576040517fdd7e362100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610a9d576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610b0b576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161028f565b6102a18383610dc1565b600d548110610b50576040517f9a67c1cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54811015610b8c576040517fe18cb38300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c54811015610b9c57600c8190555b600d819055602354811015610bb0575f6023555b600d54600c54600b5460408051938452602084019290925282820152517f8bd4b15ea7d1bc41ea9abc3fc487ccb89cd678a00786584714faa9d751c84ee59181900360600190a150565b602a546021546040517fdef9d6af00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163def9d6af91610c559160040190815260200190565b602060405180830381865afa158015610c70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c9491906132b9565b610cca576040517f5428eae700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114610d04576040517fe85392f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0d836110fa565b600d545f908152600e602052604090205414610d7857600d545f908152600e6020526040902054610d3d846110fa565b6040517f55ad3fd30000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161028f565b602254801580610d89575060235415155b15610d9e57610d9984848461118a565b610daa565b610daa84848484611233565b600d54610db8908390613305565b600d5550505050565b805f5b81811015610e9f57610dfe848483818110610de157610de1613318565b90506101000201803603810190610df891906131f8565b82611361565b838382818110610e1057610e10613318565b9050610100020160e00135848483818110610e2d57610e2d613318565b9050610100020160200135858584818110610e4a57610e4a613318565b610e61926020610100909202019081019150613345565b67ffffffffffffffff167f2402307311a4d6604e4e7b4c8a15a7e1213edb39c16a31efa70afb06030d316560405160405180910390a4600101610dc4565b50600b545f90610eb0908390613305565b600b819055600c54909150811115610ef3576040517ec6ead200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6023548015801590610f055750818111155b15610f14575f60228190556023555b5050505050565b600c54825f8167ffffffffffffffff811115610f3957610f396131af565b604051908082528060200260200182016040528015610f62578160200160208202803683370190505b505f848152600e6020526040902054909150610f8b610f86368a90038a018a6131f8565b6110fa565b14610fb0575f838152600e6020526040902054610d3d610f86368a90038a018a6131f8565b60e08701355f5b8381101561107957600185015f818152600e6020526040902054909550611000898984818110610fe957610fe9613318565b90506101000201803603810190610f8691906131f8565b14611028575f858152600e6020526040902054610d3d898984818110610fe957610fe9613318565b5f88888381811061103b5761103b613318565b9050610100020160e001359050611052838261145d565b84838151811061106457611064613318565b60209081029190910101529150600101610fb7565b50600d548411156110b6576040517fe102246900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110c0828661149f565b600c546040518591907f22c9005dd88c18b552a1cd7e8b3b937fcde9ca69213c1f658f54d572e4877a81905f90a3505050600c5550505050565b5f8160405160200161116d91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604051602081830303815290604052805190602001209050919050565b5f5b8181101561122d576111c2848484848181106111aa576111aa613318565b90506020028101906111bc919061335e565b5f6115af565b93506111cd846110fa565b845167ffffffffffffffff9081165f908152600e602090815260408083209490945560e088015190880151885194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a460010161118c565b50505050565b6023541561126d576040517ff093c2e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82825f81811061127f5761127f613318565b9050602002810190611291919061335e565b61129f906020810190613345565b67ffffffffffffffff166023555f5b82811015610f14575f81156112c3575f6112c5565b825b90506112f5868686858181106112dd576112dd613318565b90506020028101906112ef919061335e565b836115af565b9550611300866110fa565b865167ffffffffffffffff9081165f908152600e602090815260408083209490945560e08a0151908a01518a5194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a4506001016112ae565b8151600b5467ffffffffffffffff9091169061137e908390613305565b611389906001613305565b81146113c1576040517f0105f9c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f818152600e60205260409020546113d8846110fa565b146113f4575f818152600e6020526040902054610d3d846110fa565b5f6114028460600151611b9d565b905083608001518114611441576040517fd5a9901400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060a0909201515f928352600f60205260409092209190915550565b5f6020838360405160200161147c929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c901c90505b92915050565b81516001146114da576040517fe85392f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a545f9073ffffffffffffffffffffffffffffffffffffffff166387d9d02384611508602086018661339a565b611512878061339a565b6040518663ffffffff1660e01b8152600401611532959493929190613447565b602060405180830381865afa15801561154d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157191906132b9565b9050806115aa576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915283516115fc9060016134b7565b67ffffffffffffffff166116136020850185613345565b67ffffffffffffffff161461168257835161162f9060016134b7565b61163c6020850185613345565b6040517fbd4455ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161028f565b5f6116916101208501856134d8565b5f8181106116a1576116a1613318565b60265492013560f81c92505060ff1660018160018111156116c4576116c4613539565b141580156116d4575060ff821615155b80156116e4575060ff8216600114155b1561171b576040517fc5d0907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6117268686611c23565b60408051600680825260e082019092529192505f91906020820160c080368337019050509050600183600181111561176057611760613539565b03611802576117736101208801886134d8565b90506001146117ae576040517fcf102c5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075b600c60ff8216116117fc5760e08301515f906117ce600784613566565b60ff16815181106117e1576117e1613318565b60209081029190910101526117f58161357f565b90506117b1565b506119be565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff85160161185c5761185561183d6101208901896134d8565b61184b91600190829061359d565b8460e001516123c4565b90506119be565b60ff84166119be576201f0006118766101208901896134d8565b905011156118b0576040517f9094af7e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6118bf6101208901896134d8565b60019060206118d26101208d018d6134d8565b6118dd9291506135c4565b926118ea9392919061359d565b6040516118f89291906135d7565b604051809103902090508083606001511461194f5760608301516040517f5513177c00000000000000000000000000000000000000000000000000000000815261028f918391600401918252602082015260400190565b61195d6101208901896134d8565b602061196d6101208c018c6134d8565b6119789291506135c4565b906119876101208c018c6134d8565b61199594909392915061359d565b61199e916135e6565b825f815181106119b0576119b0613318565b602002602001018181525050505b8160400151886020015114611a1457816040015188602001516040517f0b08d5be00000000000000000000000000000000000000000000000000000000815260040161028f929190918252602082015260400190565b8660a00135826020015114611a685760208201516040517f0b08d5be000000000000000000000000000000000000000000000000000000008152600481019190915260a0880135602482015260440161028f565b8151608088013514611ab65781516040517f626ade3000000000000000000000000000000000000000000000000000000000815260048101919091526080880135602482015260440161028f565b60c0820151611ae390611acf60408a0160208b01613345565b67ffffffffffffffff168a60c0015161273d565b5f611af8888460800151848660e00151612869565b60408051610100810190915290915080611b1560208b018b613345565b67ffffffffffffffff16815260608a0180356020830152604091820191611b3e91908c01613345565b67ffffffffffffffff168152602001896080013581526020018960a0013581526020018460a001518152602001896020016020810190611b7e9190613345565b67ffffffffffffffff1681526020019190915298975050505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f5b82811015611c1d575f611bd36010612927565b8051604051919250611bf391859190602001918252602082015260400190565b60405160208183030381529060405280519060200120925050611c168160010190565b9050611bc0565b50919050565b6040805161010080820183525f8083526020830181905292820183905260608083018490526080830184905260a0830184905260c0830184905260e0830152909190611c71908501856134d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525092935060069250611cb0915050565b604051908082528060200260200182016040528015611cd9578160200160208202803683370190505b5060e083015280515f90815b81811015612324575f611d0b85611cfd600485613305565b601491810182015192910190565b5090505f611d2c86611d1e601886613305565b602091810182015192910190565b5090505f611d3f87611d1e603887613305565b509050600160ff83161b861615611d87576040517f1b6825bb00000000000000000000000000000000000000000000000000000000815260ff8316600482015260240161028f565b600160ff83161b8617955081611e135773ffffffffffffffffffffffffffffffffffffffff831661800814611e07576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60a08801819052612319565b60018203611e975773ffffffffffffffffffffffffffffffffffffffff831661800814611e8b576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60608801819052612319565b60028203611f1b5773ffffffffffffffffffffffffffffffffffffffff831661800814611f0f576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60808801819052612319565b60038203611f9f5773ffffffffffffffffffffffffffffffffffffffff831661800b14611f93576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60c08801819052612319565b600482036120235773ffffffffffffffffffffffffffffffffffffffff831661800b14612017576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60408801819052612319565b600582036120a75773ffffffffffffffffffffffffffffffffffffffff83166180011461209b576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b60208801819052612319565b600682036121275773ffffffffffffffffffffffffffffffffffffffff83166180011461211f576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b808852612319565b600782101580156121395750600c8211155b156122255773ffffffffffffffffffffffffffffffffffffffff8316618011146121ae576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b5f6121ba600784613566565b905060068160ff16106121f9576040517ff640f0e500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818960e001518260ff168151811061221357612213613318565b60200260200101818152505050612319565b600d82036122db5773ffffffffffffffffffffffffffffffffffffffff83166180011461229d576040517fc1780bd600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810183905260440161028f565b8089146122d6576040517f4c99107800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612319565b600d821115612319576040517f6aa398800000000000000000000000000000000000000000000000000000000081526004810183905260240161028f565b505050605801611ce5565b50846123755781611fff14612370576040517ffa44b527000000000000000000000000000000000000000000000000000000008152611fff60048201526024810183905260440161028f565b6123bb565b81613fff146123bb576040517ffa44b527000000000000000000000000000000000000000000000000000000008152613fff60048201526024810183905260440161028f565b50505092915050565b60605f838103612400576040517f53dee67b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61240c60066090613622565b841115612445576040517f7734c31a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612450609085613639565b15612487576040517f53e6d04d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600680825260e08201909252906020820160c0803683370190505091505f5b848110156125ca578149806124ee576040517ffc7ab1d30000000000000000000000000000000000000000000000000000000081526004810184905260240161028f565b5f8783886124fd601083613305565b9261250a9392919061359d565b61251391613671565b60801c905061254882828a8a61252a601089613305565b9061253660908a613305565b926125439392919061359d565b612a11565b81888489612557603083613305565b926125649392919061359d565b604051602001612576939291906136b9565b6040516020818303038152906040528051906020012085858151811061259e5761259e613318565b60209081029190910101526125b2846136d2565b935050506090816125c39190613305565b90506124aa565b5080498015612608576040517f92290acc0000000000000000000000000000000000000000000000000000000081526004810183905260240161028f565b5f5b6006811015612733575f801b85828151811061262857612628613318565b602002602001015114801561265857505f801b84828151811061264d5761264d613318565b602002602001015114155b806126a357505f801b85828151811061267357612673613318565b6020026020010151141580156126a357505f801b84828151811061269957612699613318565b6020026020010151145b1561272b57805f801b8683815181106126be576126be613318565b6020026020010151145f801b8684815181106126dc576126dc613318565b60209081029190910101516040517fafd53e2f0000000000000000000000000000000000000000000000000000000081526004810194909452911515602484015214604482015260640161028f565b60010161260a565b5050509392505050565b608083901c82811461277b576040517f2d50c33b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8082106127b4576040517fd018e08e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416816127d56203f480426135c4565b111561282457816127e96203f480426135c4565b6040517f087539820000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161028f565b612830610e1042613305565b811115610f14576040517ffb5c22e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8061287486612b90565b8051906020012090505f6128cb60185460195460175460405160ff909216151560f81b6020830152602182015260418101829052606181018290526060919060810160405160208183030381529060405291505090565b8051906020012090505f6128e188888888612c01565b8051602091820120604080519283018690528201849052606082018190529150608001604051602081830303815290604052805190602001209350505050949350505050565b604080516060810182525f80825260208201819052918101919091526002820154600183015403612984576040517f63c3654900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060028101545f818152602083815260408083208151606081018352815481526001808301805467ffffffffffffffff81168488015268010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff16948301949094528686529387905290849055929055909190612a03908290613305565b836002018190555050919050565b5f84848484604051602001612a299493929190613709565b60405160208183030381529060405290505f80600a73ffffffffffffffffffffffffffffffffffffffff1683604051612a629190613729565b5f60405180830381855afa9150503d805f8114612a9a576040519150601f19603f3d011682016040523d82523d5f602084013e612a9f565b606091505b509150915081612add57826040517f8d5851de00000000000000000000000000000000000000000000000000000000815260040161028f9190612eb5565b5f81806020019051810190612af2919061373a565b9150507f73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff000000018114612b8657604080516020810183905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f4daa985d00000000000000000000000000000000000000000000000000000000825261028f91600401612eb5565b5050505050505050565b6060612ba182820160408401613345565b60405160c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166020820152606083013560288201525f6048820181905260508201526070016040516020818303038152906040529050919050565b6060612c106058610200613622565b612c1b906004613305565b612c296101008701876134d8565b90501115612c63576040517fae43b42400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c726101008701876134d8565b604051612c809291906135d7565b6040518091039020905080858760c001358860e00135612ca08888612cce565b604051602001612cb495949392919061375c565b604051602081830303815290604052915050949350505050565b606060068351141580612ce357506006825114155b15612d2e57825182516040517fd8e9405c000000000000000000000000000000000000000000000000000000008152600660048201526024810192909252604482015260640161028f565b612d3a60106002613622565b67ffffffffffffffff811115612d5257612d526131af565b604051908082528060200260200182016040528015612d7b578160200160208202803683370190505b5090505f5b6006811015612e2357828181518110612d9b57612d9b613318565b602002602001015182826002612db19190613622565b81518110612dc157612dc1613318565b602002602001018181525050838181518110612ddf57612ddf613318565b602002602001015182826002612df59190613622565b612e00906001613305565b81518110612e1057612e10613318565b6020908102919091010152600101612d80565b5092915050565b5f8060408385031215612e3b575f80fd5b50508035926020909101359150565b5f5b83811015612e64578181015183820152602001612e4c565b50505f910152565b5f8151808452612e83816020860160208601612e4a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612ec76020830184612e6c565b9392505050565b5f6101008284031215611c1d575f80fd5b5f8083601f840112612eef575f80fd5b50813567ffffffffffffffff811115612f06575f80fd5b6020830191508360208260051b8501011115612f20575f80fd5b9250929050565b5f805f806101408587031215612f3b575f80fd5b84359350612f4c8660208701612ece565b925061012085013567ffffffffffffffff811115612f68575f80fd5b612f7487828801612edf565b95989497509550505050565b5f8083601f840112612f90575f80fd5b50813567ffffffffffffffff811115612fa7575f80fd5b6020830191508360208260081b8501011115612f20575f80fd5b5f805f60408486031215612fd3575f80fd5b83359250602084013567ffffffffffffffff811115612ff0575f80fd5b612ffc86828701612f80565b9497909650939450505050565b5f805f610120848603121561301c575f80fd5b6130268585612ece565b925061010084013567ffffffffffffffff811115613042575f80fd5b612ffc86828701612edf565b5f60408284031215611c1d575f80fd5b5f805f806101408587031215613072575f80fd5b61307c8686612ece565b935061010085013567ffffffffffffffff80821115613099575f80fd5b6130a588838901612f80565b90955093506101208701359150808211156130be575f80fd5b506130cb8782880161304e565b91505092959194509250565b5f602082840312156130e7575f80fd5b5035919050565b5f805f805f6101608688031215613103575f80fd5b853594506131148760208801612ece565b935061012086013567ffffffffffffffff80821115613131575f80fd5b61313d89838a01612f80565b9095509350610140880135915080821115613156575f80fd5b506131638882890161304e565b9150509295509295909350565b5f8060208385031215613181575f80fd5b823567ffffffffffffffff811115613197575f80fd5b6131a385828601612f80565b90969095509350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b803567ffffffffffffffff811681146131f3575f80fd5b919050565b5f61010080838503121561320a575f80fd5b6040519081019067ffffffffffffffff82118183101715613252577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b8160405261325f846131dc565b815260208401356020820152613277604085016131dc565b6040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e084013560e0820152809250505092915050565b5f602082840312156132c9575f80fd5b81518015158114612ec7575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611499576114996132d8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215613355575f80fd5b612ec7826131dc565b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613390575f80fd5b9190910192915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126133cd575f80fd5b83018035915067ffffffffffffffff8211156133e7575f80fd5b6020019150600581901b3603821315612f20575f80fd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561342e575f80fd5b8260051b80836020870137939093016020019392505050565b606080825286519082018190525f906020906080840190828a01845b8281101561347f57815184529284019290840190600101613463565b505050838103602085015261349581888a6133fe565b91505082810360408401526134ab8185876133fe565b98975050505050505050565b67ffffffffffffffff818116838216019080821115612e2357612e236132d8565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261350b575f80fd5b83018035915067ffffffffffffffff821115613525575f80fd5b602001915036819003821315612f20575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60ff8281168282160390811115611499576114996132d8565b5f60ff821660ff8103613594576135946132d8565b60010192915050565b5f80858511156135ab575f80fd5b838611156135b7575f80fd5b5050820193919092039150565b81810381811115611499576114996132d8565b818382375f9101908152919050565b80356020831015611499577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b8082028115828204841417611499576114996132d8565b5f8261366c577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081358181169160108510156136b15780818660100360031b1b83161692505b505092915050565b838152818360208301375f910160200190815292915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613702576137026132d8565b5060010190565b848152836020820152818360408301375f91016040019081529392505050565b5f8251613390818460208701612e4a565b5f806040838503121561374b575f80fd5b505080516020909101519092909150565b8581525f6020866020840152856040840152846060840152608083018451602086015f5b8281101561379c57815184529284019290840190600101613780565b50919a995050505050505050505056fea26469706673582212207954c631350351c91c2323f477635727cc5f13d0752ee1f0dffd18e8256c95fe64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.