Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 6500613 | 27 days ago | IN | 0 ETH | 0.01186137 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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"; // 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) { require(_newBatch.batchNumber == _previousBatch.batchNumber + 1, "f"); // only commit next batch uint8 pubdataSource = uint8(bytes1(_newBatch.pubdataCommitments[0])); PubdataPricingMode pricingMode = s.feeParams.pubdataPricingMode; require( pricingMode == PubdataPricingMode.Validium || pubdataSource == uint8(PubdataSource.Calldata) || pubdataSource == uint8(PubdataSource.Blob), "us" ); // 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 require(_newBatch.pubdataCommitments.length == 1, "EF: v0l"); 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 require(_newBatch.pubdataCommitments.length <= BLOB_SIZE_BYTES, "cz"); require( logOutput.pubdataHash == keccak256(_newBatch.pubdataCommitments[1:_newBatch.pubdataCommitments.length - 32]), "wp" ); blobCommitments[0] = bytes32( _newBatch.pubdataCommitments[_newBatch.pubdataCommitments.length - 32:_newBatch .pubdataCommitments .length] ); } require(_previousBatch.batchHash == logOutput.previousBatchHash, "l"); // Check that the priority operation hash in the L2 logs is as expected require(logOutput.chainedPriorityTxsHash == _newBatch.priorityOperationsHash, "t"); // Check that the number of processed priority operations is as expected require(logOutput.numberOfLayer1Txs == _newBatch.numberOfLayer1Txs, "ta"); // 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; require(batchTimestamp == _expectedBatchTimestamp, "tb"); // While the fact that _previousBatchTimestamp < batchTimestamp is already checked on L2, // we double check it here for clarity require(_previousBatchTimestamp < batchTimestamp, "h3"); 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. require(block.timestamp - COMMIT_TIMESTAMP_NOT_OLDER <= batchTimestamp, "h1"); // New batch timestamp is too small require(lastL2BlockTimestamp <= block.timestamp + COMMIT_TIMESTAMP_APPROXIMATION_DELTA, "h2"); // The last L2 block timestamp is too big } /// @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; // linear traversal of the logs for (uint256 i = 0; i < emittedL2Logs.length; 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 require(!_checkBit(processedLogs, uint8(logKey)), "kp"); 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)) { require(logSender == L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, "lm"); logOutput.l2LogsTreeRoot = logValue; } else if (logKey == uint256(SystemLogKey.TOTAL_L2_TO_L1_PUBDATA_KEY)) { require(logSender == L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, "ln"); logOutput.pubdataHash = logValue; } else if (logKey == uint256(SystemLogKey.STATE_DIFF_HASH_KEY)) { require(logSender == L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, "lb"); logOutput.stateDiffHash = logValue; } else if (logKey == uint256(SystemLogKey.PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY)) { require(logSender == L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, "sc"); logOutput.packedBatchAndL2BlockTimestamp = uint256(logValue); } else if (logKey == uint256(SystemLogKey.PREV_BATCH_HASH_KEY)) { require(logSender == L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, "sv"); logOutput.previousBatchHash = logValue; } else if (logKey == uint256(SystemLogKey.CHAINED_PRIORITY_TXN_HASH_KEY)) { require(logSender == L2_BOOTLOADER_ADDRESS, "bl"); logOutput.chainedPriorityTxsHash = logValue; } else if (logKey == uint256(SystemLogKey.NUMBER_OF_LAYER_1_TXS_KEY)) { require(logSender == L2_BOOTLOADER_ADDRESS, "bk"); logOutput.numberOfLayer1Txs = uint256(logValue); } else if ( logKey >= uint256(SystemLogKey.BLOB_ONE_HASH_KEY) && logKey <= uint256(SystemLogKey.BLOB_SIX_HASH_KEY) ) { require(logSender == L2_PUBDATA_CHUNK_PUBLISHER_ADDR, "pc"); uint8 blobNumber = uint8(logKey) - uint8(SystemLogKey.BLOB_ONE_HASH_KEY); // While the fact that `blobNumber` is a valid blob number is implicitly checked by the fact // that Solidity provides array overflow protection, we still double check it manually in case // we accidentally put `unchecked` at the top of the loop and generally for better error messages. require(blobNumber < MAX_NUMBER_OF_BLOBS, "b6"); logOutput.blobHashes[blobNumber] = logValue; } else if (logKey == uint256(SystemLogKey.EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY)) { require(logSender == L2_BOOTLOADER_ADDRESS, "bu"); require(_expectedSystemContractUpgradeTxHash == logValue, "ut"); } else if (logKey > uint256(SystemLogKey.EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY)) { revert("ul"); } } // 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)) { require(processedLogs == 8191, "b7"); } else { require(processedLogs == 16383, "b8"); } } /// @inheritdoc IExecutor function commitBatches( StoredBatchInfo memory _lastCommittedBatchData, CommitBatchInfo[] calldata _newBatchesData ) external nonReentrant onlyValidator { _commitBatches(_lastCommittedBatchData, _newBatchesData); } /// @inheritdoc IExecutor function commitBatchesSharedBridge( uint256, // _chainId StoredBatchInfo memory _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 require( IStateTransitionManager(s.stateTransitionManager).protocolVersionIsActive(s.protocolVersion), "Executor facet: wrong protocol version" ); // 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. require(_newBatchesData.length == 1, "e4"); // Check that we commit batches after last committed batch require(s.storedBatchHashes[s.totalBatchesCommitted] == _hashStoredBatchInfo(_lastCommittedBatchData), "i"); // incorrect previous batch data 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 { 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 encure noticeable gas cost. require(s.l2SystemContractsUpgradeBatchNumber == 0, "ik"); // Save the batch number where the upgrade transaction was executed. s.l2SystemContractsUpgradeBatchNumber = _newBatchesData[0].batchNumber; 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; require(currentBatchNumber == s.totalBatchesExecuted + _executedBatchIdx + 1, "k"); // Execute batches in order require( _hashStoredBatchInfo(_storedBatch) == s.storedBatchHashes[currentBatchNumber], "exe10" // executing batch should be committed ); bytes32 priorityOperationsHash = _collectOperationsFromPriorityQueue(_storedBatch.numberOfLayer1Txs); require(priorityOperationsHash == _storedBatch.priorityOperationsHash, "x"); // priority operations hash does not match to expected // 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; require(newTotalBatchesExecuted <= s.totalBatchesVerified, "n"); // Can't execute batches more than committed and proven currently. 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 require(_hashStoredBatchInfo(_prevBatch) == s.storedBatchHashes[currentTotalBatchesVerified], "t1"); bytes32 prevBatchCommitment = _prevBatch.commitment; for (uint256 i = 0; i < committedBatchesLength; i = i.uncheckedInc()) { currentTotalBatchesVerified = currentTotalBatchesVerified.uncheckedInc(); require( _hashStoredBatchInfo(_committedBatches[i]) == s.storedBatchHashes[currentTotalBatchesVerified], "o1" ); bytes32 currentBatchCommitment = _committedBatches[i].commitment; proofPublicInput[i] = _getBatchProofPublicInput(prevBatchCommitment, currentBatchCommitment); prevBatchCommitment = currentBatchCommitment; } require(currentTotalBatchesVerified <= s.totalBatchesCommitted, "q"); _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. require(proofPublicInput.length == 1, "t4"); bool successVerifyProof = s.verifier.verify( proofPublicInput, _proof.serializedProof, _proof.recursiveAggregationInput ); require(successVerifyProof, "p"); // Proof verification fail } /// @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 { require(s.totalBatchesCommitted > _newLastBatch, "v1"); // The last committed batch is less than new last batch require(_newLastBatch >= s.totalBatchesExecuted, "v2"); // Already executed batches cannot be reverted 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) { require(_batch.systemLogs.length <= MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES, "pu"); 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. require(_blobCommitments.length == MAX_NUMBER_OF_BLOBS, "b10"); require(_blobHashes.length == MAX_NUMBER_OF_BLOBS, "b11"); // 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 require(success, "failed to call point evaluation precompile"); (, uint256 result) = abi.decode(data, (uint256, uint256)); require(result == BLS_MODULUS, "precompile unexpected output"); } /// @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; require(_pubdataCommitments.length > 0, "pl"); require(_pubdataCommitments.length <= PUBDATA_COMMITMENT_SIZE * MAX_NUMBER_OF_BLOBS, "bd"); require(_pubdataCommitments.length % PUBDATA_COMMITMENT_SIZE == 0, "bs"); blobCommitments = new bytes32[](MAX_NUMBER_OF_BLOBS); for (uint256 i = 0; i < _pubdataCommitments.length; i += PUBDATA_COMMITMENT_SIZE) { bytes32 blobVersionedHash = _getBlobVersionedHash(versionedHashIndex); require(blobVersionedHash != bytes32(0), "vh"); // 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 += 1; } // 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); require(versionedHash == bytes32(0), "lh"); // 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++) { require( (_blobHashes[i] == bytes32(0) && blobCommitments[i] == bytes32(0)) || (_blobHashes[i] != bytes32(0) && blobCommitments[i] != bytes32(0)), "bh" ); } } 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 pragma solidity 0.8.24; /// @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 = 100 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.24; /// @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 pragma solidity 0.8.24; /** * @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 pragma solidity 0.8.24; /** * @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 pragma solidity 0.8.24; /// @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`. struct BridgehubL2TransactionRequest { address sender; address contractL2; uint256 mintValue; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * @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 require(lockSlotOldValue == 0, "1B"); } /** * @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) } // On the first call to nonReentrant, _notEntered will be true require(_status == _NOT_ENTERED, "r1"); // 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"; /// @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() { require(msg.sender == s.admin, "Hyperchain: not admin"); _; } /// @notice Checks if validator is active modifier onlyValidator() { require(s.validators[msg.sender], "Hyperchain: not validator"); _; } modifier onlyStateTransitionManager() { require(msg.sender == s.stateTransitionManager, "Hyperchain: not state transition manager"); _; } modifier onlyBridgehub() { require(msg.sender == s.bridgehub, "Hyperchain: not bridgehub"); _; } modifier onlyAdminOrStateTransitionManager() { require( msg.sender == s.admin || msg.sender == s.stateTransitionManager, "Hyperchain: Only by admin or state transition manager" ); _; } modifier onlyValidatorOrStateTransitionManager() { require( s.validators[msg.sender] || msg.sender == s.stateTransitionManager, "Hyperchain: Only by validator or state transition manager" ); _; } modifier onlyBaseTokenBridge() { require(msg.sender == s.baseTokenBridge, "Hyperchain: Only base token bridge can call this function"); _; } }
// 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. 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 pragma solidity 0.8.24; 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 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 pragma solidity 0.8.24; /// @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: UNLICENSED pragma solidity 0.8.24; /// @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 pragma solidity 0.8.24; 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 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 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 pragma solidity 0.8.24; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {UncheckedMath} from "../../common/libraries/UncheckedMath.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 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; require(selectors.length > 0, "B"); // no functions for diamond cut 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("C"); // undefined diamond cut action } } _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. require(_facet.code.length > 0, "G"); // 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]; require(oldFacet.facetAddress == address(0), "J"); // facet for this selector already exists _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. require(_facet.code.length > 0, "K"); uint256 selectorsLength = _selectors.length; for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) { bytes4 selector = _selectors[i]; SelectorToFacet memory oldFacet = ds.selectorToFacet[selector]; require(oldFacet.facetAddress != address(0), "L"); // it is impossible to replace the facet with zero address _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(); require(_facet == address(0), "a1"); // facet address must be zero uint256 selectorsLength = _selectors.length; for (uint256 i = 0; i < selectorsLength; i = i.uncheckedInc()) { bytes4 selector = _selectors[i]; SelectorToFacet memory oldFacet = ds.selectorToFacet[selector]; require(oldFacet.facetAddress != address(0), "a2"); // Can't delete a non-existent facet _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]; require(_isSelectorFreezable == ds.selectorToFacet[selector0].isFreezable, "J1"); } 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)) { require(_calldata.length == 0, "H"); // Non-empty calldata for zero address } 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("I"); // delegatecall failed } 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. require(data.length == 32, "lp"); require(abi.decode(data, (bytes32)) == DIAMOND_INIT_SUCCESS_RETURN_VALUE, "lp1"); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @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) { require(!_queue.isEmpty(), "D"); // priority queue is empty 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) { require(!_queue.isEmpty(), "s"); // priority queue is empty // 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": {} }
[{"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
608060405234801561000f575f80fd5b506141248061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063701f58c51161007257806397c09d341161005857806397c09d3414610156578063c37533bb14610169578063c3d93e7c1461017c575f80fd5b8063701f58c5146101305780637f61885c14610143575f80fd5b80630f23da43146100a357806317d7de7c146100b85780636edd4f121461010a5780636f497ac61461011d575b5f80fd5b6100b66100b1366004613795565b61018f565b005b6100f46040518060400160405280600d81526020017f4578656375746f7246616365740000000000000000000000000000000000000081525081565b60405161010191906137d7565b60405180910390f35b6100b6610118366004613979565b6102ee565b6100b661012b366004613a13565b61044c565b6100b661013e366004613a5b565b6105a8565b6100b6610151366004613ac1565b6106db565b6100b6610164366004613b3a565b61080f565b6100b6610177366004613b51565b6109b0565b6100b661018a366004613bd3565b610b10565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f723100000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166102bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6102c582610c42565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4546001811461037a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b610421848484610d87565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf454600181146104d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b61057e8383610fe1565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166106d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b61057e848484610d87565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610803576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6104218585858561116c565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4546001811461089b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16806108f35750602a5473ffffffffffffffffffffffffffffffffffffffff1633145b61097f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4879706572636861696e3a204f6e6c792062792076616c696461746f72206f7260448201527f207374617465207472616e736974696f6e206d616e61676572000000000000006064820152608401610217565b61098882610c42565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610ad8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b610ae48585858561116c565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610b9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610c38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6102c58383610fe1565b600d548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600b54811015610d19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76320000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600c54811015610d2957600c8190555b600d819055602354811015610d3d575f6023555b600d54600c54600b5460408051938452602084019290925282820152517f8bd4b15ea7d1bc41ea9abc3fc487ccb89cd678a00786584714faa9d751c84ee59181900360600190a150565b602a546021546040517fdef9d6af00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163def9d6af91610de29160040190815260200190565b602060405180830381865afa158015610dfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e219190613c12565b610ead576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4578656375746f722066616365743a2077726f6e672070726f746f636f6c207660448201527f657273696f6e00000000000000000000000000000000000000000000000000006064820152608401610217565b60018114610f17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f65340000000000000000000000000000000000000000000000000000000000006044820152606401610217565b610f20836113fc565b600d545f908152600e602052604090205414610f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f69000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b602254801580610fa9575060235415155b15610fbe57610fb984848461148c565b610fca565b610fca84848484611535565b600d54610fd8908390613c65565b600d5550505050565b805f5b818110156110bf5761101e84848381811061100157611001613c78565b905061010002018036038101906110189190613ca5565b82611693565b83838281811061103057611030613c78565b9050610100020160e0013584848381811061104d5761104d613c78565b905061010002016020013585858481811061106a5761106a613c78565b611081926020610100909202019081019150613cc0565b67ffffffffffffffff167f2402307311a4d6604e4e7b4c8a15a7e1213edb39c16a31efa70afb06030d316560405160405180910390a4600101610fe4565b50600b545f906110d0908390613c65565b600b819055600c54909150811115611144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6e000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60235480158015906111565750818111155b15611165575f60228190556023555b5050505050565b600c54825f8167ffffffffffffffff81111561118a5761118a613827565b6040519080825280602002602001820160405280156111b3578160200160208202803683370190505b505f848152600e60205260409020549091506111dc6111d7368a90038a018a613ca5565b6113fc565b14611243576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60e08701355f5b8381101561134b57600185015f818152600e602052604090205490955061129389898481811061127c5761127c613c78565b905061010002018036038101906111d79190613ca5565b146112fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6f310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f88888381811061130d5761130d613c78565b9050610100020160e001359050611324838261183a565b84838151811061133657611336613c78565b6020908102919091010152915060010161124a565b50600d548411156113b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f71000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6113c2828661187c565b600c546040518591907f22c9005dd88c18b552a1cd7e8b3b937fcde9ca69213c1f658f54d572e4877a81905f90a3505050600c5550505050565b5f8160405160200161146f91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604051602081830303815290604052805190602001209050919050565b5f5b8181101561152f576114c4848484848181106114ac576114ac613c78565b90506020028101906114be9190613cd9565b5f6119ec565b93506114cf846113fc565b845167ffffffffffffffff9081165f908152600e602090815260408083209490945560e088015190880151885194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a460010161148e565b50505050565b6023541561159f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f696b0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b82825f8181106115b1576115b1613c78565b90506020028101906115c39190613cd9565b6115d1906020810190613cc0565b67ffffffffffffffff166023555f5b82811015611165575f81156115f5575f6115f7565b825b90506116278686868581811061160f5761160f613c78565b90506020028101906116219190613cd9565b836119ec565b9550611632866113fc565b865167ffffffffffffffff9081165f908152600e602090815260408083209490945560e08a0151908a01518a5194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a4506001016115e0565b8151600b5467ffffffffffffffff909116906116b0908390613c65565b6116bb906001613c65565b8114611723576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6b000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f818152600e602052604090205461173a846113fc565b146117a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f65786531300000000000000000000000000000000000000000000000000000006044820152606401610217565b5f6117af84606001516120db565b90508360800151811461181e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f78000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5060a0909201515f928352600f60205260409092209190915550565b5f60208383604051602001611859929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c901c90505b92915050565b81516001146118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74340000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600a545f9073ffffffffffffffffffffffffffffffffffffffff166387d9d023846119156020860186613d15565b61191f8780613d15565b6040518663ffffffff1660e01b815260040161193f959493929190613dc2565b602060405180830381865afa15801561195a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197e9190613c12565b9050806119e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f70000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091528351611a39906001613e32565b67ffffffffffffffff16611a506020850185613cc0565b67ffffffffffffffff1614611ac1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f66000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f611ad0610120850185613e53565b5f818110611ae057611ae0613c78565b60265492013560f81c92505060ff166001816001811115611b0357611b03613eb4565b1480611b10575060ff8216155b80611b1e575060ff82166001145b611b84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f75730000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f611b8f8686612161565b60408051600680825260e082019092529192505f91906020820160c0803683370190505090506001836001811115611bc957611bc9613eb4565b03611c9d57611bdc610120880188613e53565b9050600114611c47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45463a2076306c000000000000000000000000000000000000000000000000006044820152606401610217565b60075b600c60ff821611611c975760e08301515f90611c67600784613ee1565b60ff1681518110611c7a57611c7a613c78565b602090810291909101015280611c8f81613efa565b915050611c4a565b50611ea4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff851601611cf757611cf0611cd8610120890189613e53565b611ce6916001908290613f18565b8460e00151612a9a565b9050611ea4565b60ff8416611ea4576201f000611d11610120890189613e53565b90501115611d7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f637a0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b611d89610120880188613e53565b6001906020611d9c6101208c018c613e53565b611da7929150613f3f565b92611db493929190613f18565b604051611dc2929190613f52565b6040518091039020826060015114611e36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f77700000000000000000000000000000000000000000000000000000000000006044820152606401610217565b611e44610120880188613e53565b6020611e546101208b018b613e53565b611e5f929150613f3f565b90611e6e6101208b018b613e53565b611e7c949093929150613f18565b611e8591613f61565b815f81518110611e9757611e97613c78565b6020026020010181815250505b8160400151886020015114611f15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6c000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8660a00135826020015114611f86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f74000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8151608088013514611ff4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74610000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60c08201516120219061200d60408a0160208b01613cc0565b67ffffffffffffffff168a60c00151612edb565b5f612036888460800151848660e001516130b0565b6040805161010081019091529091508061205360208b018b613cc0565b67ffffffffffffffff16815260608a018035602083015260409182019161207c91908c01613cc0565b67ffffffffffffffff168152602001896080013581526020018960a0013581526020018460a0015181526020018960200160208101906120bc9190613cc0565b67ffffffffffffffff1681526020019190915298975050505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f5b8281101561215b575f612111601061316e565b805160405191925061213191859190602001918252602082015260400190565b604051602081830303815290604052805190602001209250506121548160010190565b90506120fe565b50919050565b6040805161010080820183525f8083526020830181905292820183905260608083018490526080830184905260a0830184905260c0830184905260e08301529091906121af90850185613e53565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929350600692506121ee915050565b604051908082528060200260200182016040528015612217578160200160208202803683370190505b5060e08301525f805b82518110156129b1575f61224784612239600485613c65565b601491810182015192910190565b5090505f6122688561225a601886613c65565b602091810182015192910190565b5090505f61227b8661225a603887613c65565b509050600160ff83161b8516156122ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6b700000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600160ff83161b851794508161238b5773ffffffffffffffffffffffffffffffffffffffff83166180081461237f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c6d0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60a087018190526129a6565b600182036124205773ffffffffffffffffffffffffffffffffffffffff831661800814612414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c6e0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b606087018190526129a6565b600282036124b55773ffffffffffffffffffffffffffffffffffffffff8316618008146124a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c620000000000000000000000000000000000000000000000000000000000006044820152606401610217565b608087018190526129a6565b6003820361254a5773ffffffffffffffffffffffffffffffffffffffff831661800b1461253e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f73630000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60c087018190526129a6565b600482036125df5773ffffffffffffffffffffffffffffffffffffffff831661800b146125d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f73760000000000000000000000000000000000000000000000000000000000006044820152606401610217565b604087018190526129a6565b600582036126745773ffffffffffffffffffffffffffffffffffffffff831661800114612668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f626c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b602087018190526129a6565b600682036127055773ffffffffffffffffffffffffffffffffffffffff8316618001146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f626b0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8087526129a6565b600782101580156127175750600c8211155b156128445773ffffffffffffffffffffffffffffffffffffffff83166180111461279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f70630000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f6127a9600784613ee1565b905060068160ff1610612818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62360000000000000000000000000000000000000000000000000000000000006044820152606401610217565b818860e001518260ff168151811061283257612832613c78565b602002602001018181525050506129a6565b600d820361293b5773ffffffffffffffffffffffffffffffffffffffff8316618001146128cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62750000000000000000000000000000000000000000000000000000000000006044820152606401610217565b808814612936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f75740000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6129a6565b600d8211156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f756c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505050605801612220565b5083612a275780611fff14612a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62370000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612a92565b80613fff14612a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62380000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505092915050565b60605f83612b04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f706c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612b1060066090613f9d565b841115612b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62640000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612b84609085613fb4565b15612beb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62730000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60408051600680825260e08201909252906020820160c0803683370190505091505f5b84811015612d5d57814980612c7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f878388612c8e601083613c65565b92612c9b93929190613f18565b612ca491613fec565b60801c9050612cd982828a8a612cbb601089613c65565b90612cc760908a613c65565b92612cd493929190613f18565b613288565b81888489612ce8603083613c65565b92612cf593929190613f18565b604051602001612d0793929190614032565b60405160208183030381529060405280519060200120858581518110612d2f57612d2f613c78565b6020908102919091010152612d45600185613c65565b93505050609081612d569190613c65565b9050612c0e565b5080498015612dc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f5b6006811015612ed1575f801b858281518110612de857612de8613c78565b6020026020010151148015612e1757505f801b848281518110612e0d57612e0d613c78565b6020026020010151145b80612e6357505f801b858281518110612e3257612e32613c78565b602002602001015114158015612e6357505f801b848281518110612e5857612e58613c78565b602002602001015114155b612ec9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600101612dca565b5050509392505050565b608083901c828114612f49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74620000000000000000000000000000000000000000000000000000000000006044820152606401610217565b808210612fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68330000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6fffffffffffffffffffffffffffffffff841681612fd36283d60042613f3f565b111561303b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b613047610e1042613c65565b811115611165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68320000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f806130bb86613453565b8051906020012090505f61311260185460195460175460405160ff909216151560f81b6020830152602182015260418101829052606181018290526060919060810160405160208183030381529060405291505090565b8051906020012090505f613128888888886134c4565b8051602091820120604080519283018690528201849052606082018190529150608001604051602081830303815290604052805190602001209350505050949350505050565b604080516060810182525f808252602082018190529181019190915260028201546001830154036131fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f73000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5060028101545f818152602083815260408083208151606081018352815481526001808301805467ffffffffffffffff81168488015268010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff1694830194909452868652938790529084905592905590919061327a908290613c65565b836002018190555050919050565b5f848484846040516020016132a0949392919061404b565b60405160208183030381529060405290505f80600a73ffffffffffffffffffffffffffffffffffffffff16836040516132d9919061406b565b5f60405180830381855afa9150503d805f8114613311576040519150601f19603f3d011682016040523d82523d5f602084013e613316565b606091505b5091509150816133a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f6661696c656420746f2063616c6c20706f696e74206576616c756174696f6e2060448201527f707265636f6d70696c65000000000000000000000000000000000000000000006064820152608401610217565b5f818060200190518101906133bd919061407c565b9150507f73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff000000018114613449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f707265636f6d70696c6520756e6578706563746564206f7574707574000000006044820152606401610217565b5050505050505050565b606061346482820160408401613cc0565b60405160c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166020820152606083013560288201525f6048820181905260508201526070016040516020818303038152906040529050919050565b60606134d36058610200613f9d565b6134de906004613c65565b6134ec610100870187613e53565b90501115613556576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f70750000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f613565610100870187613e53565b604051613573929190613f52565b6040518091039020905080858760c001358860e0013561359388886135c1565b6040516020016135a795949392919061409e565b604051602081830303815290604052915050949350505050565b6060600683511461362e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f62313000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6006825114613699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f62313100000000000000000000000000000000000000000000000000000000006044820152606401610217565b6136a560106002613f9d565b67ffffffffffffffff8111156136bd576136bd613827565b6040519080825280602002602001820160405280156136e6578160200160208202803683370190505b5090505f5b600681101561378e5782818151811061370657613706613c78565b60200260200101518282600261371c9190613f9d565b8151811061372c5761372c613c78565b60200260200101818152505083818151811061374a5761374a613c78565b6020026020010151828260026137609190613f9d565b61376b906001613c65565b8151811061377b5761377b613c78565b60209081029190910101526001016136eb565b5092915050565b5f80604083850312156137a6575f80fd5b50508035926020909101359150565b5f5b838110156137cf5781810151838201526020016137b7565b50505f910152565b602081525f82518060208401526137f58160408501602087016137b5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b803567ffffffffffffffff8116811461386b575f80fd5b919050565b5f610100808385031215613882575f80fd5b6040519081019067ffffffffffffffff821181831017156138ca577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b816040528092506138da84613854565b8152602084013560208201526138f260408501613854565b6040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e084013560e0820152505092915050565b5f8083601f840112613941575f80fd5b50813567ffffffffffffffff811115613958575f80fd5b6020830191508360208260051b8501011115613972575f80fd5b9250929050565b5f805f80610140858703121561398d575f80fd5b8435935061399e8660208701613870565b925061012085013567ffffffffffffffff8111156139ba575f80fd5b6139c687828801613931565b95989497509550505050565b5f8083601f8401126139e2575f80fd5b50813567ffffffffffffffff8111156139f9575f80fd5b6020830191508360208260081b8501011115613972575f80fd5b5f805f60408486031215613a25575f80fd5b83359250602084013567ffffffffffffffff811115613a42575f80fd5b613a4e868287016139d2565b9497909650939450505050565b5f805f6101208486031215613a6e575f80fd5b613a788585613870565b925061010084013567ffffffffffffffff811115613a94575f80fd5b613a4e86828701613931565b5f610100828403121561215b575f80fd5b5f6040828403121561215b575f80fd5b5f805f806101408587031215613ad5575f80fd5b613adf8686613aa0565b935061010085013567ffffffffffffffff80821115613afc575f80fd5b613b08888389016139d2565b9095509350610120870135915080821115613b21575f80fd5b50613b2e87828801613ab1565b91505092959194509250565b5f60208284031215613b4a575f80fd5b5035919050565b5f805f805f6101608688031215613b66575f80fd5b85359450613b778760208801613aa0565b935061012086013567ffffffffffffffff80821115613b94575f80fd5b613ba089838a016139d2565b9095509350610140880135915080821115613bb9575f80fd5b50613bc688828901613ab1565b9150509295509295909350565b5f8060208385031215613be4575f80fd5b823567ffffffffffffffff811115613bfa575f80fd5b613c06858286016139d2565b90969095509350505050565b5f60208284031215613c22575f80fd5b81518015158114613c31575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561187657611876613c38565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6101008284031215613cb6575f80fd5b613c318383613870565b5f60208284031215613cd0575f80fd5b613c3182613854565b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613d0b575f80fd5b9190910192915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d48575f80fd5b83018035915067ffffffffffffffff821115613d62575f80fd5b6020019150600581901b3603821315613972575f80fd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613da9575f80fd5b8260051b80836020870137939093016020019392505050565b606080825286519082018190525f906020906080840190828a01845b82811015613dfa57815184529284019290840190600101613dde565b5050508381036020850152613e1081888a613d79565b9150508281036040840152613e26818587613d79565b98975050505050505050565b67ffffffffffffffff81811683821601908082111561378e5761378e613c38565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e86575f80fd5b83018035915067ffffffffffffffff821115613ea0575f80fd5b602001915036819003821315613972575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60ff828116828216039081111561187657611876613c38565b5f60ff821660ff8103613f0f57613f0f613c38565b60010192915050565b5f8085851115613f26575f80fd5b83861115613f32575f80fd5b5050820193919092039150565b8181038181111561187657611876613c38565b818382375f9101908152919050565b80356020831015611876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b808202811582820484141761187657611876613c38565b5f82613fe7577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008135818116916010851015612a925760109490940360031b84901b1690921692915050565b838152818360208301375f910160200190815292915050565b848152836020820152818360408301375f91016040019081529392505050565b5f8251613d0b8184602087016137b5565b5f806040838503121561408d575f80fd5b505080516020909101519092909150565b8581525f6020866020840152856040840152846060840152608083018451602086015f5b828110156140de578151845292840192908401906001016140c2565b50919a995050505050505050505056fea2646970667358221220c87f4252f93953d2d72fe62a7204227121a530e9bd574cd543e3bb7a9525afa664736f6c63430008180033
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c8063701f58c51161007257806397c09d341161005857806397c09d3414610156578063c37533bb14610169578063c3d93e7c1461017c575f80fd5b8063701f58c5146101305780637f61885c14610143575f80fd5b80630f23da43146100a357806317d7de7c146100b85780636edd4f121461010a5780636f497ac61461011d575b5f80fd5b6100b66100b1366004613795565b61018f565b005b6100f46040518060400160405280600d81526020017f4578656375746f7246616365740000000000000000000000000000000000000081525081565b60405161010191906137d7565b60405180910390f35b6100b6610118366004613979565b6102ee565b6100b661012b366004613a13565b61044c565b6100b661013e366004613a5b565b6105a8565b6100b6610151366004613ac1565b6106db565b6100b6610164366004613b3a565b61080f565b6100b6610177366004613b51565b6109b0565b6100b661018a366004613bd3565b610b10565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f723100000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166102bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6102c582610c42565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4546001811461037a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610416576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b610421848484610d87565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf454600181146104d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b61057e8383610fe1565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45550505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff166106d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b61057e848484610d87565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610803576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6104218585858561116c565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4546001811461089b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16806108f35750602a5473ffffffffffffffffffffffffffffffffffffffff1633145b61097f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4879706572636861696e3a204f6e6c792062792076616c696461746f72206f7260448201527f207374617465207472616e736974696f6e206d616e61676572000000000000006064820152608401610217565b61098882610c42565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4555050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610ad8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b610ae48585858561116c565b60017f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455505050505050565b7f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf45460018114610b9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f72310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60027f8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf455335f9081526009602052604090205460ff16610c38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4879706572636861696e3a206e6f742076616c696461746f72000000000000006044820152606401610217565b6102c58383610fe1565b600d548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600b54811015610d19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76320000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600c54811015610d2957600c8190555b600d819055602354811015610d3d575f6023555b600d54600c54600b5460408051938452602084019290925282820152517f8bd4b15ea7d1bc41ea9abc3fc487ccb89cd678a00786584714faa9d751c84ee59181900360600190a150565b602a546021546040517fdef9d6af00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092169163def9d6af91610de29160040190815260200190565b602060405180830381865afa158015610dfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e219190613c12565b610ead576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4578656375746f722066616365743a2077726f6e672070726f746f636f6c207660448201527f657273696f6e00000000000000000000000000000000000000000000000000006064820152608401610217565b60018114610f17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f65340000000000000000000000000000000000000000000000000000000000006044820152606401610217565b610f20836113fc565b600d545f908152600e602052604090205414610f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f69000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b602254801580610fa9575060235415155b15610fbe57610fb984848461148c565b610fca565b610fca84848484611535565b600d54610fd8908390613c65565b600d5550505050565b805f5b818110156110bf5761101e84848381811061100157611001613c78565b905061010002018036038101906110189190613ca5565b82611693565b83838281811061103057611030613c78565b9050610100020160e0013584848381811061104d5761104d613c78565b905061010002016020013585858481811061106a5761106a613c78565b611081926020610100909202019081019150613cc0565b67ffffffffffffffff167f2402307311a4d6604e4e7b4c8a15a7e1213edb39c16a31efa70afb06030d316560405160405180910390a4600101610fe4565b50600b545f906110d0908390613c65565b600b819055600c54909150811115611144576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6e000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60235480158015906111565750818111155b15611165575f60228190556023555b5050505050565b600c54825f8167ffffffffffffffff81111561118a5761118a613827565b6040519080825280602002602001820160405280156111b3578160200160208202803683370190505b505f848152600e60205260409020549091506111dc6111d7368a90038a018a613ca5565b6113fc565b14611243576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60e08701355f5b8381101561134b57600185015f818152600e602052604090205490955061129389898481811061127c5761127c613c78565b905061010002018036038101906111d79190613ca5565b146112fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6f310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f88888381811061130d5761130d613c78565b9050610100020160e001359050611324838261183a565b84838151811061133657611336613c78565b6020908102919091010152915060010161124a565b50600d548411156113b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f71000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6113c2828661187c565b600c546040518591907f22c9005dd88c18b552a1cd7e8b3b937fcde9ca69213c1f658f54d572e4877a81905f90a3505050600c5550505050565b5f8160405160200161146f91905f6101008201905067ffffffffffffffff8084511683526020840151602084015280604085015116604084015250606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015292915050565b604051602081830303815290604052805190602001209050919050565b5f5b8181101561152f576114c4848484848181106114ac576114ac613c78565b90506020028101906114be9190613cd9565b5f6119ec565b93506114cf846113fc565b845167ffffffffffffffff9081165f908152600e602090815260408083209490945560e088015190880151885194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a460010161148e565b50505050565b6023541561159f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f696b0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b82825f8181106115b1576115b1613c78565b90506020028101906115c39190613cd9565b6115d1906020810190613cc0565b67ffffffffffffffff166023555f5b82811015611165575f81156115f5575f6115f7565b825b90506116278686868581811061160f5761160f613c78565b90506020028101906116219190613cd9565b836119ec565b9550611632866113fc565b865167ffffffffffffffff9081165f908152600e602090815260408083209490945560e08a0151908a01518a5194519194909316917f8f2916b2f2d78cc5890ead36c06c0f6d5d112c7e103589947e8e2f0d6eddb76391a4506001016115e0565b8151600b5467ffffffffffffffff909116906116b0908390613c65565b6116bb906001613c65565b8114611723576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6b000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f818152600e602052604090205461173a846113fc565b146117a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f65786531300000000000000000000000000000000000000000000000000000006044820152606401610217565b5f6117af84606001516120db565b90508360800151811461181e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f78000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5060a0909201515f928352600f60205260409092209190915550565b5f60208383604051602001611859929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c901c90505b92915050565b81516001146118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74340000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600a545f9073ffffffffffffffffffffffffffffffffffffffff166387d9d023846119156020860186613d15565b61191f8780613d15565b6040518663ffffffff1660e01b815260040161193f959493929190613dc2565b602060405180830381865afa15801561195a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197e9190613c12565b9050806119e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f70000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091528351611a39906001613e32565b67ffffffffffffffff16611a506020850185613cc0565b67ffffffffffffffff1614611ac1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f66000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f611ad0610120850185613e53565b5f818110611ae057611ae0613c78565b60265492013560f81c92505060ff166001816001811115611b0357611b03613eb4565b1480611b10575060ff8216155b80611b1e575060ff82166001145b611b84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f75730000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f611b8f8686612161565b60408051600680825260e082019092529192505f91906020820160c0803683370190505090506001836001811115611bc957611bc9613eb4565b03611c9d57611bdc610120880188613e53565b9050600114611c47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f45463a2076306c000000000000000000000000000000000000000000000000006044820152606401610217565b60075b600c60ff821611611c975760e08301515f90611c67600784613ee1565b60ff1681518110611c7a57611c7a613c78565b602090810291909101015280611c8f81613efa565b915050611c4a565b50611ea4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff851601611cf757611cf0611cd8610120890189613e53565b611ce6916001908290613f18565b8460e00151612a9a565b9050611ea4565b60ff8416611ea4576201f000611d11610120890189613e53565b90501115611d7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f637a0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b611d89610120880188613e53565b6001906020611d9c6101208c018c613e53565b611da7929150613f3f565b92611db493929190613f18565b604051611dc2929190613f52565b6040518091039020826060015114611e36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f77700000000000000000000000000000000000000000000000000000000000006044820152606401610217565b611e44610120880188613e53565b6020611e546101208b018b613e53565b611e5f929150613f3f565b90611e6e6101208b018b613e53565b611e7c949093929150613f18565b611e8591613f61565b815f81518110611e9757611e97613c78565b6020026020010181815250505b8160400151886020015114611f15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f6c000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8660a00135826020015114611f86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f74000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8151608088013514611ff4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74610000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60c08201516120219061200d60408a0160208b01613cc0565b67ffffffffffffffff168a60c00151612edb565b5f612036888460800151848660e001516130b0565b6040805161010081019091529091508061205360208b018b613cc0565b67ffffffffffffffff16815260608a018035602083015260409182019161207c91908c01613cc0565b67ffffffffffffffff168152602001896080013581526020018960a0013581526020018460a0015181526020018960200160208101906120bc9190613cc0565b67ffffffffffffffff1681526020019190915298975050505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705f5b8281101561215b575f612111601061316e565b805160405191925061213191859190602001918252602082015260400190565b604051602081830303815290604052805190602001209250506121548160010190565b90506120fe565b50919050565b6040805161010080820183525f8083526020830181905292820183905260608083018490526080830184905260a0830184905260c0830184905260e08301529091906121af90850185613e53565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929350600692506121ee915050565b604051908082528060200260200182016040528015612217578160200160208202803683370190505b5060e08301525f805b82518110156129b1575f61224784612239600485613c65565b601491810182015192910190565b5090505f6122688561225a601886613c65565b602091810182015192910190565b5090505f61227b8661225a603887613c65565b509050600160ff83161b8516156122ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6b700000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600160ff83161b851794508161238b5773ffffffffffffffffffffffffffffffffffffffff83166180081461237f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c6d0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60a087018190526129a6565b600182036124205773ffffffffffffffffffffffffffffffffffffffff831661800814612414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c6e0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b606087018190526129a6565b600282036124b55773ffffffffffffffffffffffffffffffffffffffff8316618008146124a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c620000000000000000000000000000000000000000000000000000000000006044820152606401610217565b608087018190526129a6565b6003820361254a5773ffffffffffffffffffffffffffffffffffffffff831661800b1461253e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f73630000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60c087018190526129a6565b600482036125df5773ffffffffffffffffffffffffffffffffffffffff831661800b146125d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f73760000000000000000000000000000000000000000000000000000000000006044820152606401610217565b604087018190526129a6565b600582036126745773ffffffffffffffffffffffffffffffffffffffff831661800114612668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f626c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b602087018190526129a6565b600682036127055773ffffffffffffffffffffffffffffffffffffffff8316618001146126fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f626b0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b8087526129a6565b600782101580156127175750600c8211155b156128445773ffffffffffffffffffffffffffffffffffffffff83166180111461279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f70630000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f6127a9600784613ee1565b905060068160ff1610612818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62360000000000000000000000000000000000000000000000000000000000006044820152606401610217565b818860e001518260ff168151811061283257612832613c78565b602002602001018181525050506129a6565b600d820361293b5773ffffffffffffffffffffffffffffffffffffffff8316618001146128cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62750000000000000000000000000000000000000000000000000000000000006044820152606401610217565b808814612936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f75740000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6129a6565b600d8211156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f756c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505050605801612220565b5083612a275780611fff14612a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62370000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612a92565b80613fff14612a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62380000000000000000000000000000000000000000000000000000000000006044820152606401610217565b505092915050565b60605f83612b04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f706c0000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612b1060066090613f9d565b841115612b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62640000000000000000000000000000000000000000000000000000000000006044820152606401610217565b612b84609085613fb4565b15612beb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62730000000000000000000000000000000000000000000000000000000000006044820152606401610217565b60408051600680825260e08201909252906020820160c0803683370190505091505f5b84811015612d5d57814980612c7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f76680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f878388612c8e601083613c65565b92612c9b93929190613f18565b612ca491613fec565b60801c9050612cd982828a8a612cbb601089613c65565b90612cc760908a613c65565b92612cd493929190613f18565b613288565b81888489612ce8603083613c65565b92612cf593929190613f18565b604051602001612d0793929190614032565b60405160208183030381529060405280519060200120858581518110612d2f57612d2f613c78565b6020908102919091010152612d45600185613c65565b93505050609081612d569190613c65565b9050612c0e565b5080498015612dc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f6c680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f5b6006811015612ed1575f801b858281518110612de857612de8613c78565b6020026020010151148015612e1757505f801b848281518110612e0d57612e0d613c78565b6020026020010151145b80612e6357505f801b858281518110612e3257612e32613c78565b602002602001015114158015612e6357505f801b848281518110612e5857612e58613c78565b602002602001015114155b612ec9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f62680000000000000000000000000000000000000000000000000000000000006044820152606401610217565b600101612dca565b5050509392505050565b608083901c828114612f49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f74620000000000000000000000000000000000000000000000000000000000006044820152606401610217565b808210612fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68330000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6fffffffffffffffffffffffffffffffff841681612fd36283d60042613f3f565b111561303b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68310000000000000000000000000000000000000000000000000000000000006044820152606401610217565b613047610e1042613c65565b811115611165576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f68320000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f806130bb86613453565b8051906020012090505f61311260185460195460175460405160ff909216151560f81b6020830152602182015260418101829052606181018290526060919060810160405160208183030381529060405291505090565b8051906020012090505f613128888888886134c4565b8051602091820120604080519283018690528201849052606082018190529150608001604051602081830303815290604052805190602001209350505050949350505050565b604080516060810182525f808252602082018190529181019190915260028201546001830154036131fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f73000000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5060028101545f818152602083815260408083208151606081018352815481526001808301805467ffffffffffffffff81168488015268010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff1694830194909452868652938790529084905592905590919061327a908290613c65565b836002018190555050919050565b5f848484846040516020016132a0949392919061404b565b60405160208183030381529060405290505f80600a73ffffffffffffffffffffffffffffffffffffffff16836040516132d9919061406b565b5f60405180830381855afa9150503d805f8114613311576040519150601f19603f3d011682016040523d82523d5f602084013e613316565b606091505b5091509150816133a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f6661696c656420746f2063616c6c20706f696e74206576616c756174696f6e2060448201527f707265636f6d70696c65000000000000000000000000000000000000000000006064820152608401610217565b5f818060200190518101906133bd919061407c565b9150507f73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff000000018114613449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f707265636f6d70696c6520756e6578706563746564206f7574707574000000006044820152606401610217565b5050505050505050565b606061346482820160408401613cc0565b60405160c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166020820152606083013560288201525f6048820181905260508201526070016040516020818303038152906040529050919050565b60606134d36058610200613f9d565b6134de906004613c65565b6134ec610100870187613e53565b90501115613556576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f70750000000000000000000000000000000000000000000000000000000000006044820152606401610217565b5f613565610100870187613e53565b604051613573929190613f52565b6040518091039020905080858760c001358860e0013561359388886135c1565b6040516020016135a795949392919061409e565b604051602081830303815290604052915050949350505050565b6060600683511461362e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f62313000000000000000000000000000000000000000000000000000000000006044820152606401610217565b6006825114613699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f62313100000000000000000000000000000000000000000000000000000000006044820152606401610217565b6136a560106002613f9d565b67ffffffffffffffff8111156136bd576136bd613827565b6040519080825280602002602001820160405280156136e6578160200160208202803683370190505b5090505f5b600681101561378e5782818151811061370657613706613c78565b60200260200101518282600261371c9190613f9d565b8151811061372c5761372c613c78565b60200260200101818152505083818151811061374a5761374a613c78565b6020026020010151828260026137609190613f9d565b61376b906001613c65565b8151811061377b5761377b613c78565b60209081029190910101526001016136eb565b5092915050565b5f80604083850312156137a6575f80fd5b50508035926020909101359150565b5f5b838110156137cf5781810151838201526020016137b7565b50505f910152565b602081525f82518060208401526137f58160408501602087016137b5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b803567ffffffffffffffff8116811461386b575f80fd5b919050565b5f610100808385031215613882575f80fd5b6040519081019067ffffffffffffffff821181831017156138ca577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b816040528092506138da84613854565b8152602084013560208201526138f260408501613854565b6040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e084013560e0820152505092915050565b5f8083601f840112613941575f80fd5b50813567ffffffffffffffff811115613958575f80fd5b6020830191508360208260051b8501011115613972575f80fd5b9250929050565b5f805f80610140858703121561398d575f80fd5b8435935061399e8660208701613870565b925061012085013567ffffffffffffffff8111156139ba575f80fd5b6139c687828801613931565b95989497509550505050565b5f8083601f8401126139e2575f80fd5b50813567ffffffffffffffff8111156139f9575f80fd5b6020830191508360208260081b8501011115613972575f80fd5b5f805f60408486031215613a25575f80fd5b83359250602084013567ffffffffffffffff811115613a42575f80fd5b613a4e868287016139d2565b9497909650939450505050565b5f805f6101208486031215613a6e575f80fd5b613a788585613870565b925061010084013567ffffffffffffffff811115613a94575f80fd5b613a4e86828701613931565b5f610100828403121561215b575f80fd5b5f6040828403121561215b575f80fd5b5f805f806101408587031215613ad5575f80fd5b613adf8686613aa0565b935061010085013567ffffffffffffffff80821115613afc575f80fd5b613b08888389016139d2565b9095509350610120870135915080821115613b21575f80fd5b50613b2e87828801613ab1565b91505092959194509250565b5f60208284031215613b4a575f80fd5b5035919050565b5f805f805f6101608688031215613b66575f80fd5b85359450613b778760208801613aa0565b935061012086013567ffffffffffffffff80821115613b94575f80fd5b613ba089838a016139d2565b9095509350610140880135915080821115613bb9575f80fd5b50613bc688828901613ab1565b9150509295509295909350565b5f8060208385031215613be4575f80fd5b823567ffffffffffffffff811115613bfa575f80fd5b613c06858286016139d2565b90969095509350505050565b5f60208284031215613c22575f80fd5b81518015158114613c31575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561187657611876613c38565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6101008284031215613cb6575f80fd5b613c318383613870565b5f60208284031215613cd0575f80fd5b613c3182613854565b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613d0b575f80fd5b9190910192915050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d48575f80fd5b83018035915067ffffffffffffffff821115613d62575f80fd5b6020019150600581901b3603821315613972575f80fd5b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613da9575f80fd5b8260051b80836020870137939093016020019392505050565b606080825286519082018190525f906020906080840190828a01845b82811015613dfa57815184529284019290840190600101613dde565b5050508381036020850152613e1081888a613d79565b9150508281036040840152613e26818587613d79565b98975050505050505050565b67ffffffffffffffff81811683821601908082111561378e5761378e613c38565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e86575f80fd5b83018035915067ffffffffffffffff821115613ea0575f80fd5b602001915036819003821315613972575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60ff828116828216039081111561187657611876613c38565b5f60ff821660ff8103613f0f57613f0f613c38565b60010192915050565b5f8085851115613f26575f80fd5b83861115613f32575f80fd5b5050820193919092039150565b8181038181111561187657611876613c38565b818382375f9101908152919050565b80356020831015611876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b808202811582820484141761187657611876613c38565b5f82613fe7577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008135818116916010851015612a925760109490940360031b84901b1690921692915050565b838152818360208301375f910160200190815292915050565b848152836020820152818360408301375f91016040019081529392505050565b5f8251613d0b8184602087016137b5565b5f806040838503121561408d575f80fd5b505080516020909101519092909150565b8581525f6020866020840152856040840152846060840152608083018451602086015f5b828110156140de578151845292840192908401906001016140c2565b50919a995050505050505050505056fea2646970667358221220c87f4252f93953d2d72fe62a7204227121a530e9bd574cd543e3bb7a9525afa664736f6c63430008180033
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.