creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "src/L1/rollup/IScrollChain.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n\n/// @title IScrollChain\n/// @notice The interface for ScrollChain.\ninterface IScrollChain {\n    /**********\n     * Events *\n     **********/\n\n    /// @notice Emitted when a new batch is committed.\n    /// @param batchIndex The index of the batch.\n    /// @param batchHash The hash of the batch.\n    event CommitBatch(uint256 indexed batchIndex, bytes32 indexed batchHash);\n\n    /// @notice revert a pending batch.\n    /// @param batchIndex The index of the batch.\n    /// @param batchHash The hash of the batch\n    event RevertBatch(uint256 indexed batchIndex, bytes32 indexed batchHash);\n\n    /// @notice Emitted when a batch is finalized.\n    /// @param batchIndex The index of the batch.\n    /// @param batchHash The hash of the batch\n    /// @param stateRoot The state root on layer 2 after this batch.\n    /// @param withdrawRoot The merkle root on layer2 after this batch.\n    event FinalizeBatch(uint256 indexed batchIndex, bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);\n\n    /// @notice Emitted when owner updates the status of sequencer.\n    /// @param account The address of account updated.\n    /// @param status The status of the account updated.\n    event UpdateSequencer(address indexed account, bool status);\n\n    /// @notice Emitted when owner updates the status of prover.\n    /// @param account The address of account updated.\n    /// @param status The status of the account updated.\n    event UpdateProver(address indexed account, bool status);\n\n    /// @notice Emitted when the value of `maxNumTxInChunk` is updated.\n    /// @param oldMaxNumTxInChunk The old value of `maxNumTxInChunk`.\n    /// @param newMaxNumTxInChunk The new value of `maxNumTxInChunk`.\n    event UpdateMaxNumTxInChunk(uint256 oldMaxNumTxInChunk, uint256 newMaxNumTxInChunk);\n\n    /*************************\n     * Public View Functions *\n     *************************/\n\n    /// @return The latest finalized batch index.\n    function lastFinalizedBatchIndex() external view returns (uint256);\n\n    /// @param batchIndex The index of the batch.\n    /// @return The batch hash of a committed batch.\n    function committedBatches(uint256 batchIndex) external view returns (bytes32);\n\n    /// @param batchIndex The index of the batch.\n    /// @return The state root of a committed batch.\n    function finalizedStateRoots(uint256 batchIndex) external view returns (bytes32);\n\n    /// @param batchIndex The index of the batch.\n    /// @return The message root of a committed batch.\n    function withdrawRoots(uint256 batchIndex) external view returns (bytes32);\n\n    /// @param batchIndex The index of the batch.\n    /// @return Whether the batch is finalized by batch index.\n    function isBatchFinalized(uint256 batchIndex) external view returns (bool);\n\n    /*****************************\n     * Public Mutating Functions *\n     *****************************/\n\n    /// @notice Commit a batch of transactions on layer 1.\n    ///\n    /// @param version The version of current batch.\n    /// @param parentBatchHeader The header of parent batch, see the comments of `BatchHeaderV0Codec`.\n    /// @param chunks The list of encoded chunks, see the comments of `ChunkCodec`.\n    /// @param skippedL1MessageBitmap The bitmap indicates whether each L1 message is skipped or not.\n    function commitBatch(\n        uint8 version,\n        bytes calldata parentBatchHeader,\n        bytes[] memory chunks,\n        bytes calldata skippedL1MessageBitmap\n    ) external;\n\n    /// @notice Revert a pending batch.\n    /// @dev one can only revert unfinalized batches.\n    /// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch`.\n    /// @param count The number of subsequent batches to revert, including current batch.\n    function revertBatch(bytes calldata batchHeader, uint256 count) external;\n\n    /// @notice Finalize a committed batch on layer 1.\n    /// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch.\n    /// @param prevStateRoot The state root of parent batch.\n    /// @param postStateRoot The state root of current batch.\n    /// @param withdrawRoot The withdraw trie root of current batch.\n    /// @param aggrProof The aggregation proof for current batch.\n    function finalizeBatchWithProof(\n        bytes calldata batchHeader,\n        bytes32 prevStateRoot,\n        bytes32 postStateRoot,\n        bytes32 withdrawRoot,\n        bytes calldata aggrProof\n    ) external;\n\n    /// @notice Finalize a committed batch (with blob) on layer 1.\n    ///\n    /// @dev Memory layout of `blobDataProof`:\n    /// |    z    |    y    | kzg_commitment | kzg_proof |\n    /// |---------|---------|----------------|-----------|\n    /// | bytes32 | bytes32 |    bytes48     |  bytes48  |\n    ///\n    /// @param batchHeader The header of current batch, see the encoding in comments of `commitBatch.\n    /// @param prevStateRoot The state root of parent batch.\n    /// @param postStateRoot The state root of current batch.\n    /// @param withdrawRoot The withdraw trie root of current batch.\n    /// @param blobDataProof The proof for blob data.\n    /// @param aggrProof The aggregation proof for current batch.\n    function finalizeBatchWithProof4844(\n        bytes calldata batchHeader,\n        bytes32 prevStateRoot,\n        bytes32 postStateRoot,\n        bytes32 withdrawRoot,\n        bytes calldata blobDataProof,\n        bytes calldata aggrProof\n    ) external;\n}\n"
      },
      "src/L1/rollup/MultipleVersionRollupVerifier.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity =0.8.24;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport {IScrollChain} from \"./IScrollChain.sol\";\nimport {IRollupVerifier} from \"../../libraries/verifier/IRollupVerifier.sol\";\nimport {IZkEvmVerifier} from \"../../libraries/verifier/IZkEvmVerifier.sol\";\n\n/// @title MultipleVersionRollupVerifier\n/// @notice Verifies aggregate zk proofs using the appropriate verifier.\ncontract MultipleVersionRollupVerifier is IRollupVerifier, Ownable {\n    /**********\n     * Events *\n     **********/\n\n    /// @notice Emitted when the address of verifier is updated.\n    /// @param version The version of the verifier.\n    /// @param startBatchIndex The start batch index when the verifier will be used.\n    /// @param verifier The address of new verifier.\n    event UpdateVerifier(uint256 version, uint256 startBatchIndex, address verifier);\n\n    /**********\n     * Errors *\n     **********/\n\n    /// @dev Thrown when the given address is `address(0)`.\n    error ErrorZeroAddress();\n\n    /// @dev Thrown when the given start batch index is finalized.\n    error ErrorStartBatchIndexFinalized();\n\n    /// @dev Thrown when the given start batch index is smaller than `latestVerifier.startBatchIndex`.\n    error ErrorStartBatchIndexTooSmall();\n\n    /*************\n     * Constants *\n     *************/\n\n    /// @notice The address of ScrollChain contract.\n    address public immutable scrollChain;\n\n    /***********\n     * Structs *\n     ***********/\n\n    struct Verifier {\n        // The start batch index for the verifier.\n        uint64 startBatchIndex;\n        // The address of zkevm verifier.\n        address verifier;\n    }\n\n    /*************\n     * Variables *\n     *************/\n\n    /// @notice Mapping from verifier version to the list of legacy zkevm verifiers.\n    /// The verifiers are sorted by batchIndex in increasing order.\n    mapping(uint256 => Verifier[]) public legacyVerifiers;\n\n    /// @notice Mapping from verifier version to the latest used zkevm verifier.\n    mapping(uint256 => Verifier) public latestVerifier;\n\n    /***************\n     * Constructor *\n     ***************/\n\n    constructor(\n        address _scrollChain,\n        uint256[] memory _versions,\n        address[] memory _verifiers\n    ) {\n        if (_scrollChain == address(0)) revert ErrorZeroAddress();\n        scrollChain = _scrollChain;\n\n        for (uint256 i = 0; i < _versions.length; i++) {\n            if (_verifiers[i] == address(0)) revert ErrorZeroAddress();\n            latestVerifier[_versions[i]].verifier = _verifiers[i];\n\n            emit UpdateVerifier(_versions[i], 0, _verifiers[i]);\n        }\n    }\n\n    /*************************\n     * Public View Functions *\n     *************************/\n\n    /// @notice Return the number of legacy verifiers.\n    /// @param _version The version of legacy verifiers.\n    /// @return The number of legacy verifiers.\n    function legacyVerifiersLength(uint256 _version) external view returns (uint256) {\n        return legacyVerifiers[_version].length;\n    }\n\n    /// @notice Compute the verifier should be used for specific batch.\n    /// @param _version The version of verifier to query.\n    /// @param _batchIndex The batch index to query.\n    /// @return The address of verifier.\n    function getVerifier(uint256 _version, uint256 _batchIndex) public view returns (address) {\n        // Normally, we will use the latest verifier.\n        Verifier memory _verifier = latestVerifier[_version];\n\n        if (_verifier.startBatchIndex > _batchIndex) {\n            uint256 _length = legacyVerifiers[_version].length;\n            // In most case, only last few verifier will be used by `ScrollChain`.\n            // So, we use linear search instead of binary search.\n            unchecked {\n                for (uint256 i = _length; i > 0; --i) {\n                    _verifier = legacyVerifiers[_version][i - 1];\n                    if (_verifier.startBatchIndex <= _batchIndex) break;\n                }\n            }\n        }\n\n        return _verifier.verifier;\n    }\n\n    /*****************************\n     * Public Mutating Functions *\n     *****************************/\n\n    /// @inheritdoc IRollupVerifier\n    function verifyAggregateProof(\n        uint256 _batchIndex,\n        bytes calldata _aggrProof,\n        bytes32 _publicInputHash\n    ) external view override {\n        address _verifier = getVerifier(0, _batchIndex);\n\n        IZkEvmVerifier(_verifier).verify(_aggrProof, _publicInputHash);\n    }\n\n    /// @inheritdoc IRollupVerifier\n    function verifyAggregateProof(\n        uint256 _version,\n        uint256 _batchIndex,\n        bytes calldata _aggrProof,\n        bytes32 _publicInputHash\n    ) external view override {\n        address _verifier = getVerifier(_version, _batchIndex);\n\n        IZkEvmVerifier(_verifier).verify(_aggrProof, _publicInputHash);\n    }\n\n    /************************\n     * Restricted Functions *\n     ************************/\n\n    /// @notice Update the address of zkevm verifier.\n    /// @param _version The version of the verifier.\n    /// @param _startBatchIndex The start batch index when the verifier will be used.\n    /// @param _verifier The address of new verifier.\n    function updateVerifier(\n        uint256 _version,\n        uint64 _startBatchIndex,\n        address _verifier\n    ) external onlyOwner {\n        if (_startBatchIndex <= IScrollChain(scrollChain).lastFinalizedBatchIndex())\n            revert ErrorStartBatchIndexFinalized();\n\n        Verifier memory _latestVerifier = latestVerifier[_version];\n        if (_startBatchIndex < _latestVerifier.startBatchIndex) revert ErrorStartBatchIndexTooSmall();\n        if (_verifier == address(0)) revert ErrorZeroAddress();\n\n        if (_latestVerifier.startBatchIndex < _startBatchIndex) {\n            // don't push when it is the first update of the version.\n            if (_latestVerifier.verifier != address(0)) {\n                legacyVerifiers[_version].push(_latestVerifier);\n            }\n            _latestVerifier.startBatchIndex = _startBatchIndex;\n        }\n        _latestVerifier.verifier = _verifier;\n\n        latestVerifier[_version] = _latestVerifier;\n\n        emit UpdateVerifier(_version, _startBatchIndex, _verifier);\n    }\n}\n"
      },
      "src/libraries/verifier/IRollupVerifier.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n\n/// @title IRollupVerifier\n/// @notice The interface for rollup verifier.\ninterface IRollupVerifier {\n    /// @notice Verify aggregate zk proof.\n    /// @param batchIndex The batch index to verify.\n    /// @param aggrProof The aggregated proof.\n    /// @param publicInputHash The public input hash.\n    function verifyAggregateProof(\n        uint256 batchIndex,\n        bytes calldata aggrProof,\n        bytes32 publicInputHash\n    ) external view;\n\n    /// @notice Verify aggregate zk proof.\n    /// @param version The version of verifier to use.\n    /// @param batchIndex The batch index to verify.\n    /// @param aggrProof The aggregated proof.\n    /// @param publicInputHash The public input hash.\n    function verifyAggregateProof(\n        uint256 version,\n        uint256 batchIndex,\n        bytes calldata aggrProof,\n        bytes32 publicInputHash\n    ) external view;\n}\n"
      },
      "src/libraries/verifier/IZkEvmVerifier.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n\ninterface IZkEvmVerifier {\n    /// @notice Verify aggregate zk proof.\n    /// @param aggrProof The aggregated proof.\n    /// @param publicInputHash The public input hash.\n    function verify(bytes calldata aggrProof, bytes32 publicInputHash) external view;\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "cancun",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}