creation_sourcecode: {{
    "language": "Solidity",
    "settings": {
      "evmVersion": "paris",
      "libraries": {},
      "metadata": {
        "bytecodeHash": "ipfs",
        "useLiteralContent": true
      },
      "optimizer": {
        "enabled": true,
        "runs": 800
      },
      "remappings": [],
      "viaIR": true,
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    },
    "sources": {
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "contracts/core/BrevisRequest.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\nimport \"../lib/FeeVault.sol\";\nimport \"../interface/IBrevisProof.sol\";\nimport \"../interface/IBrevisApp.sol\";\nimport \"../interface/IBrevisEigen.sol\";\n\ncontract BrevisRequest is FeeVault {\n    uint256 public requestTimeout;\n    IBrevisProof public brevisProof;\n    IBrevisEigen public brevisEigen;\n\n    enum RequestStatus {\n        Pending,\n        ZkAttested,\n        OpSubmitted,\n        OpQueryDataSubmitted,\n        OpDisputing,\n        OpDisputed,\n        OpAttested,\n        Refunded\n    }\n\n    enum Option {\n        ZkMode,\n        OpMode_MIMC,\n        OpMode_KECCAK\n    }\n\n    struct Request {\n        uint256 deadline;\n        uint256 fee;\n        address refundee;\n        IBrevisApp callback;\n        RequestStatus status;\n        Option option;\n    }\n    mapping(bytes32 => Request) public requests;\n\n    event RequestTimeoutUpdated(uint256 from, uint256 to);\n    event RequestSent(\n        bytes32 requestId,\n        address sender,\n        uint256 fee,\n        IBrevisApp callback,\n        Option option\n    );\n    event RequestFulfilled(bytes32 requestId);\n    event RequestRefunded(bytes32 requestId);\n\n    constructor(\n        address _feeCollector,\n        IBrevisProof _brevisProof,\n        IBrevisEigen _brevisEigen\n    ) FeeVault(_feeCollector) {\n        brevisProof = _brevisProof;\n        brevisEigen = _brevisEigen;\n    }\n\n    // this is only to be called by Proxy via delegateCall as initOwner will require _owner is 0\n    function init(\n        address _feeCollector,\n        IBrevisProof _brevisProof,\n        IBrevisEigen _brevisEigen\n    ) external {\n        initOwner();\n        feeCollector = _feeCollector;\n        brevisProof = _brevisProof;\n        brevisEigen = _brevisEigen;\n    }\n\n    function setBrevisEigen(IBrevisEigen _brevisEigen) external onlyOwner {\n        brevisEigen = _brevisEigen;\n    }\n\n    function sendRequest(\n        bytes32 _requestId,\n        address _refundee,\n        IBrevisApp _callback,\n        Option _option\n    ) external payable {\n        require(requests[_requestId].deadline == 0, \"request already in queue\");\n        require(_refundee != address(0), \"refundee not provided\");\n        requests[_requestId] = Request(\n            block.timestamp + requestTimeout,\n            msg.value,\n            _refundee,\n            _callback,\n            RequestStatus.Pending,\n            _option\n        );\n        emit RequestSent(_requestId, msg.sender, msg.value, _callback, _option);\n    }\n\n    // zk mode\n    function fulfillRequest(\n        bytes32 _requestId,\n        uint64 _chainId,\n        bytes calldata _proof,\n        bytes calldata _appCircuitOutput\n    ) external {\n        require(\n            !IBrevisProof(brevisProof).hasProof(_requestId),\n            \"proof already generated\"\n        );\n\n        bytes32 reqIdFromProof = IBrevisProof(brevisProof).submitProof(\n            _chainId,\n            _proof\n        ); // will be reverted when proof is not valid\n        require(_requestId == reqIdFromProof, \"requestId and proof not match\");\n        requests[_requestId].status = RequestStatus.ZkAttested;\n\n        emit RequestFulfilled(_requestId);\n\n        address app = address(requests[_requestId].callback);\n        if (app != address(0)) {\n            // No matter if the call is success or not. The relayer should set correct gas limit.\n            // If the call exceeds the gasleft(), as the proof data is saved ahead,\n            // anyone can still call the app.callback directly to proceed\n            app.call(\n                abi.encodeWithSelector(\n                    IBrevisApp.brevisCallback.selector,\n                    _requestId,\n                    _appCircuitOutput\n                )\n            );\n        }\n    }\n\n    function refund(bytes32 _requestId) public {\n        require(block.timestamp > requests[_requestId].deadline);\n        require(\n            !IBrevisProof(brevisProof).hasProof(_requestId),\n            \"proof already generated\"\n        );\n        require(requests[_requestId].deadline != 0, \"request not in queue\");\n        requests[_requestId].deadline = 0; //reset deadline, then user is able to send request again\n        (bool sent, ) = requests[_requestId].refundee.call{\n            value: requests[_requestId].fee,\n            gas: 50000\n        }(\"\");\n        require(sent, \"send native failed\");\n        requests[_requestId].status = RequestStatus.Refunded;\n        emit RequestRefunded(_requestId);\n    }\n\n    function setRequestTimeout(uint256 _timeout) external onlyOwner {\n        uint256 oldTimeout = requestTimeout;\n        requestTimeout = _timeout;\n        emit RequestTimeoutUpdated(oldTimeout, _timeout);\n    }\n\n    // op/avs mode\n    enum AskForType {\n        NULL,\n        QueryData,\n        Proof\n    }\n\n    struct RequestExt {\n        uint256 canChallengeBefore;\n        AskForType askFor;\n        uint256 shouldRespondBefore;\n    }\n    mapping(bytes32 => RequestExt) public requestExts;\n    mapping(bytes32 => bytes32) public keccakToMimc;\n\n    uint256 public challengeWindow; // in seconds\n    uint256 public responseTimeout;\n    event ChallengeWindowUpdated(uint256 from, uint256 to);\n    event ResponseTimeoutUpdated(uint256 from, uint256 to);\n\n    function setChallengeWindow(uint256 _challengeWindow) external onlyOwner {\n        uint256 oldChallengeWindow = challengeWindow;\n        challengeWindow = _challengeWindow;\n        emit ChallengeWindowUpdated(oldChallengeWindow, _challengeWindow);\n    }\n\n    function setResponseTimeout(uint256 _responseTimeout) external onlyOwner {\n        uint256 oldResponseTimeout = responseTimeout;\n        responseTimeout = _responseTimeout;\n        emit ResponseTimeoutUpdated(oldResponseTimeout, _responseTimeout);\n    }\n\n    function queryRequestStatus(\n        bytes32 _requestId\n    ) external view returns (RequestStatus) {\n        if (\n            (requests[_requestId].status == RequestStatus.OpSubmitted ||\n                requests[_requestId].status ==\n                RequestStatus.OpQueryDataSubmitted) &&\n            requestExts[_requestId].canChallengeBefore <= block.timestamp\n        ) {\n            return RequestStatus.OpAttested;\n        }\n\n        if (\n            requests[_requestId].status == RequestStatus.OpDisputing &&\n            requestExts[_requestId].shouldRespondBefore <= block.timestamp\n        ) {\n            return RequestStatus.OpDisputed;\n        }\n\n        return requests[_requestId].status;\n    }\n\n    event OpRequestsFulfilled(bytes32[] requestIds, bytes[] queryURLs);\n\n    // Op functions\n    function fulfillOpRequests(\n        bytes32[] calldata _requestIds,\n        bytes[] calldata _queryURLs\n    ) external {\n        require(_requestIds.length > 0, \"invalid requestIds\");\n        require(_requestIds.length == _queryURLs.length);\n\n        // must already verified in brevisEigen\n        brevisEigen.mustVerified(_requestIds);\n\n        for (uint i = 0; i < _requestIds.length; i++) {\n            bytes32 reqId = _requestIds[i];\n            require(\n                !IBrevisProof(brevisProof).hasProof(reqId),\n                \"proof already generated\"\n            );\n            brevisProof.submitOpResult(reqId);\n            requests[reqId].status = RequestStatus.OpSubmitted;\n            requestExts[reqId].canChallengeBefore =\n                block.timestamp +\n                challengeWindow;\n        }\n\n        emit OpRequestsFulfilled(_requestIds, _queryURLs);\n    }\n\n    event AskFor(bytes32 indexed requestId, AskForType askFor, address from);\n    event QueryDataPost(bytes32 indexed requestId);\n    event ProofPost(bytes32 indexed requestId);\n\n    function askForQueryData(bytes32) external payable {\n        revert(\"not implemented\");\n    }\n\n    function postQueryData(bytes32, bytes calldata) external pure {\n        revert(\"not implemented\");\n    }\n\n    // after postQueryData with OpMode_MIMC\n    function challengeQueryData(bytes calldata) external pure {\n        revert(\"not implemented\");\n    }\n\n    function askForProof(bytes32) external payable {\n        revert(\"not implemented\");\n    }\n\n    function postProof(bytes32, uint64, bytes calldata) external pure {\n        revert(\"not implemented\");\n    }\n}\n"
      },
      "contracts/interface/IBrevisApp.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\nimport \"../lib/Lib.sol\";\n\ninterface IBrevisApp {\n    function brevisCallback(bytes32 _requestId, bytes calldata _appCircuitOutput) external;\n}\n"
      },
      "contracts/interface/IBrevisEigen.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\ninterface IBrevisEigen {\n    function mustVerified(bytes32[] calldata reqIds) external;\n}\n"
      },
      "contracts/interface/IBrevisProof.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\nimport \"../lib/Lib.sol\";\n\ninterface IBrevisProof {\n    function submitProof(\n        uint64 _chainId,\n        bytes calldata _proofWithPubInputs\n    ) external returns (bytes32 _requestId);\n\n    function hasProof(bytes32 _requestId) external view returns (bool);\n\n    // return appCommitHash and appVkHash\n    function getProofAppData(\n        bytes32 _requestId\n    ) external view returns (bytes32, bytes32);\n\n    function submitOpResult(bytes32 _requestId) external;\n\n    function validateOpRequest(\n        bytes32 _requestId,\n        uint64 _chainId,\n        Brevis.ExtractInfos calldata _info\n    ) external view;\n}\n"
      },
      "contracts/lib/FeeVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity ^0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./Ownable.sol\";\n\n/**\n * @title Allows the owner to set fee collector and allows fee collectors to collect fees\n */\ncontract FeeVault is Ownable {\n    using SafeERC20 for IERC20;\n\n    address public feeCollector;\n\n    event FeeCollectorUpdated(address from, address to);\n\n    constructor(address _feeCollector) {\n        feeCollector = _feeCollector;\n    }\n\n    modifier onlyFeeCollector() {\n        require(msg.sender == feeCollector, \"not fee collector\");\n        _;\n    }\n\n    function collectFee(\n        uint256 _amount,\n        address _to\n    ) external onlyFeeCollector {\n        (bool sent, ) = _to.call{value: _amount, gas: 50000}(\"\");\n        require(sent, \"send native failed\");\n    }\n\n    function setFeeCollector(address _feeCollector) external onlyOwner {\n        address oldFeeCollector = feeCollector;\n        feeCollector = _feeCollector;\n        emit FeeCollectorUpdated(oldFeeCollector, _feeCollector);\n    }\n\n    receive() external payable {}\n}\n"
      },
      "contracts/lib/Lib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.18;\n\nimport \"solidity-rlp/contracts/RLPReader.sol\";\n\nlibrary Brevis {\n    struct ReceiptInfo {\n        uint64 blkNum;\n        uint64 receiptIndex; // ReceiptIndex in the block\n        LogInfo[] logs;\n    }\n\n    struct LogInfo {\n        uint64 logIndex; // LogIndex of the field\n        bytes32 value;\n        bool valueFromTopic;\n        uint64 valueIndex; // index of the fields in topic or data\n        address contractAddress;\n        bytes32 logTopic0;\n    }\n\n    struct StorageInfo {\n        bytes32 blockHash;\n        address account;\n        bytes32 slot;\n        bytes32 slotValue;\n        uint64 blockNumber;\n    }\n\n    struct TransactionInfo {\n        bytes32 txHash;\n        bytes32 hashOfRawTxData;\n        bytes32 blockHash;\n        uint64 blockNumber;\n    }\n\n    struct ExtractInfos {\n        ReceiptInfo[] receipts;\n        StorageInfo[] stores;\n        TransactionInfo[] txs;\n    }\n\n    // retrieved from proofData, to align the logs with circuit...\n    struct ProofData {\n        bytes32 commitHash;\n        bytes32 appCommitHash; // zk-program computing circuit commit hash\n        bytes32 appVkHash; // zk-program computing circuit Verify Key hash\n        bytes32 smtRoot; // for zk-program computing proof only\n    }\n}\n\nlibrary Tx {\n    using RLPReader for bytes;\n    using RLPReader for uint;\n    using RLPReader for RLPReader.RLPItem;\n\n    struct TxInfo {\n        uint64 chainId;\n        uint64 nonce;\n        uint256 gasTipCap;\n        uint256 gasFeeCap;\n        uint256 gas;\n        address to;\n        uint256 value;\n        bytes data;\n        address from; // calculate from V R S\n    }\n\n    // support DynamicFeeTxType for now\n    function decodeTx(\n        bytes calldata txRaw\n    ) public pure returns (TxInfo memory info) {\n        uint8 txType = uint8(txRaw[0]);\n        require(txType == 2, \"not a DynamicFeeTxType\");\n\n        bytes memory rlpData = txRaw[1:];\n        RLPReader.RLPItem[] memory values = rlpData.toRlpItem().toList();\n        info.chainId = uint64(values[0].toUint());\n        info.nonce = uint64(values[1].toUint());\n        info.gasTipCap = values[2].toUint();\n        info.gasFeeCap = values[3].toUint();\n        info.gas = values[4].toUint();\n        info.to = values[5].toAddress();\n        info.value = values[6].toUint();\n        info.data = values[7].toBytes();\n\n        (uint8 v, bytes32 r, bytes32 s) = (\n            uint8(values[9].toUint()),\n            bytes32(values[10].toBytes()),\n            bytes32(values[11].toBytes())\n        );\n        // remove r,s,v and adjust length field\n        bytes memory unsignedTxRaw;\n        uint16 unsignedTxRawDataLength;\n        uint8 prefix = uint8(txRaw[1]);\n        uint8 lenBytes = prefix - 0xf7; // assume lenBytes won't larger than 2, means the tx rlp data size won't exceed 2^16\n        if (lenBytes == 1) {\n            unsignedTxRawDataLength = uint8(bytes1(txRaw[2:3])) - 67; //67 is the bytes of r,s,v\n        } else {\n            unsignedTxRawDataLength =\n                uint16(bytes2(txRaw[2:2 + lenBytes])) -\n                67;\n        }\n        if (unsignedTxRawDataLength <= 55) {\n            unsignedTxRaw = abi.encodePacked(\n                txRaw[:2],\n                txRaw[3:txRaw.length - 67]\n            );\n            unsignedTxRaw[1] = bytes1(0xc0 + uint8(unsignedTxRawDataLength));\n        } else {\n            if (unsignedTxRawDataLength <= 255) {\n                unsignedTxRaw = abi.encodePacked(\n                    txRaw[0],\n                    bytes1(0xf8),\n                    bytes1(uint8(unsignedTxRawDataLength)),\n                    txRaw[2 + lenBytes:txRaw.length - 67]\n                );\n            } else {\n                unsignedTxRaw = abi.encodePacked(\n                    txRaw[0],\n                    bytes1(0xf9),\n                    bytes2(unsignedTxRawDataLength),\n                    txRaw[2 + lenBytes:txRaw.length - 67]\n                );\n            }\n        }\n        info.from = recover(keccak256(unsignedTxRaw), r, s, v);\n    }\n\n    function recover(\n        bytes32 message,\n        bytes32 r,\n        bytes32 s,\n        uint8 v\n    ) internal pure returns (address) {\n        if (v < 27) {\n            v += 27;\n        }\n        return ecrecover(message, v, r, s);\n    }\n}\n"
      },
      "contracts/lib/Ownable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity ^0.8.18;\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 *\n * This adds a normal func that setOwner if _owner is address(0). So we can't allow\n * renounceOwnership. So we can support Proxy based upgradable contract\n */\nabstract contract Ownable {\n    address private _owner;\n\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _setOwner(msg.sender);\n    }\n\n    /**\n     * @dev Only to be called by inherit contracts, in their init func called by Proxy\n     * we require _owner == address(0), which is only possible when it's a delegateCall\n     * because constructor sets _owner in contract state.\n     */\n    function initOwner() internal {\n        require(_owner == address(0), \"owner already set\");\n        _setOwner(msg.sender);\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 called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == msg.sender, \"Ownable: caller is not the owner\");\n        _;\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(\n            newOwner != address(0),\n            \"Ownable: new owner is the zero address\"\n        );\n        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "solidity-rlp/contracts/RLPReader.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * @author Hamdi Allam hamdi.allam97@gmail.com\n * Please reach out with any questions or concerns\n */\npragma solidity >=0.5.10 <0.9.0;\n\nlibrary RLPReader {\n    uint8 constant STRING_SHORT_START = 0x80;\n    uint8 constant STRING_LONG_START = 0xb8;\n    uint8 constant LIST_SHORT_START = 0xc0;\n    uint8 constant LIST_LONG_START = 0xf8;\n    uint8 constant WORD_SIZE = 32;\n\n    struct RLPItem {\n        uint256 len;\n        uint256 memPtr;\n    }\n\n    struct Iterator {\n        RLPItem item; // Item that's being iterated over.\n        uint256 nextPtr; // Position of the next item in the list.\n    }\n\n    /*\n     * @dev Returns the next element in the iteration. Reverts if it has not next element.\n     * @param self The iterator.\n     * @return The next element in the iteration.\n     */\n    function next(Iterator memory self) internal pure returns (RLPItem memory) {\n        require(hasNext(self));\n\n        uint256 ptr = self.nextPtr;\n        uint256 itemLength = _itemLength(ptr);\n        self.nextPtr = ptr + itemLength;\n\n        return RLPItem(itemLength, ptr);\n    }\n\n    /*\n     * @dev Returns true if the iteration has more elements.\n     * @param self The iterator.\n     * @return true if the iteration has more elements.\n     */\n    function hasNext(Iterator memory self) internal pure returns (bool) {\n        RLPItem memory item = self.item;\n        return self.nextPtr < item.memPtr + item.len;\n    }\n\n    /*\n     * @param item RLP encoded bytes\n     */\n    function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {\n        uint256 memPtr;\n        assembly {\n            memPtr := add(item, 0x20)\n        }\n\n        return RLPItem(item.length, memPtr);\n    }\n\n    /*\n     * @dev Create an iterator. Reverts if item is not a list.\n     * @param self The RLP item.\n     * @return An 'Iterator' over the item.\n     */\n    function iterator(RLPItem memory self) internal pure returns (Iterator memory) {\n        require(isList(self));\n\n        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);\n        return Iterator(self, ptr);\n    }\n\n    /*\n     * @param the RLP item.\n     */\n    function rlpLen(RLPItem memory item) internal pure returns (uint256) {\n        return item.len;\n    }\n\n    /*\n     * @param the RLP item.\n     * @return (memPtr, len) pair: location of the item's payload in memory.\n     */\n    function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) {\n        uint256 offset = _payloadOffset(item.memPtr);\n        uint256 memPtr = item.memPtr + offset;\n        uint256 len = item.len - offset; // data length\n        return (memPtr, len);\n    }\n\n    /*\n     * @param the RLP item.\n     */\n    function payloadLen(RLPItem memory item) internal pure returns (uint256) {\n        (, uint256 len) = payloadLocation(item);\n        return len;\n    }\n\n    /*\n     * @param the RLP item containing the encoded list.\n     */\n    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {\n        require(isList(item));\n\n        uint256 items = numItems(item);\n        RLPItem[] memory result = new RLPItem[](items);\n\n        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);\n        uint256 dataLen;\n        for (uint256 i = 0; i < items; i++) {\n            dataLen = _itemLength(memPtr);\n            result[i] = RLPItem(dataLen, memPtr);\n            memPtr = memPtr + dataLen;\n        }\n\n        return result;\n    }\n\n    // @return indicator whether encoded payload is a list. negate this function call for isData.\n    function isList(RLPItem memory item) internal pure returns (bool) {\n        if (item.len == 0) return false;\n\n        uint8 byte0;\n        uint256 memPtr = item.memPtr;\n        assembly {\n            byte0 := byte(0, mload(memPtr))\n        }\n\n        if (byte0 < LIST_SHORT_START) return false;\n        return true;\n    }\n\n    /*\n     * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.\n     * @return keccak256 hash of RLP encoded bytes.\n     */\n    function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) {\n        uint256 ptr = item.memPtr;\n        uint256 len = item.len;\n        bytes32 result;\n        assembly {\n            result := keccak256(ptr, len)\n        }\n        return result;\n    }\n\n    /*\n     * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.\n     * @return keccak256 hash of the item payload.\n     */\n    function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) {\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\n        bytes32 result;\n        assembly {\n            result := keccak256(memPtr, len)\n        }\n        return result;\n    }\n\n    /** RLPItem conversions into data types **/\n\n    // @returns raw rlp encoding in bytes\n    function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {\n        bytes memory result = new bytes(item.len);\n        if (result.length == 0) return result;\n\n        uint256 ptr;\n        assembly {\n            ptr := add(0x20, result)\n        }\n\n        copy(item.memPtr, ptr, item.len);\n        return result;\n    }\n\n    // any non-zero byte except \"0x80\" is considered true\n    function toBoolean(RLPItem memory item) internal pure returns (bool) {\n        require(item.len == 1);\n        uint256 result;\n        uint256 memPtr = item.memPtr;\n        assembly {\n            result := byte(0, mload(memPtr))\n        }\n\n        // SEE Github Issue #5.\n        // Summary: Most commonly used RLP libraries (i.e Geth) will encode\n        // \"0\" as \"0x80\" instead of as \"0\". We handle this edge case explicitly\n        // here.\n        if (result == 0 || result == STRING_SHORT_START) {\n            return false;\n        } else {\n            return true;\n        }\n    }\n\n    function toAddress(RLPItem memory item) internal pure returns (address) {\n        // 1 byte for the length prefix\n        require(item.len == 21);\n\n        return address(uint160(toUint(item)));\n    }\n\n    function toUint(RLPItem memory item) internal pure returns (uint256) {\n        require(item.len > 0 && item.len <= 33);\n\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\n\n        uint256 result;\n        assembly {\n            result := mload(memPtr)\n\n            // shift to the correct location if neccesary\n            if lt(len, 32) {\n                result := div(result, exp(256, sub(32, len)))\n            }\n        }\n\n        return result;\n    }\n\n    // enforces 32 byte length\n    function toUintStrict(RLPItem memory item) internal pure returns (uint256) {\n        // one byte prefix\n        require(item.len == 33);\n\n        uint256 result;\n        uint256 memPtr = item.memPtr + 1;\n        assembly {\n            result := mload(memPtr)\n        }\n\n        return result;\n    }\n\n    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {\n        require(item.len > 0);\n\n        (uint256 memPtr, uint256 len) = payloadLocation(item);\n        bytes memory result = new bytes(len);\n\n        uint256 destPtr;\n        assembly {\n            destPtr := add(0x20, result)\n        }\n\n        copy(memPtr, destPtr, len);\n        return result;\n    }\n\n    /*\n     * Private Helpers\n     */\n\n    // @return number of payload items inside an encoded list.\n    function numItems(RLPItem memory item) private pure returns (uint256) {\n        if (item.len == 0) return 0;\n\n        uint256 count = 0;\n        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);\n        uint256 endPtr = item.memPtr + item.len;\n        while (currPtr < endPtr) {\n            currPtr = currPtr + _itemLength(currPtr); // skip over an item\n            count++;\n        }\n\n        return count;\n    }\n\n    // @return entire rlp item byte length\n    function _itemLength(uint256 memPtr) private pure returns (uint256) {\n        uint256 itemLen;\n        uint256 byte0;\n        assembly {\n            byte0 := byte(0, mload(memPtr))\n        }\n\n        if (byte0 < STRING_SHORT_START) {\n            itemLen = 1;\n        } else if (byte0 < STRING_LONG_START) {\n            itemLen = byte0 - STRING_SHORT_START + 1;\n        } else if (byte0 < LIST_SHORT_START) {\n            assembly {\n                let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is\n                memPtr := add(memPtr, 1) // skip over the first byte\n\n                /* 32 byte word size */\n                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len\n                itemLen := add(dataLen, add(byteLen, 1))\n            }\n        } else if (byte0 < LIST_LONG_START) {\n            itemLen = byte0 - LIST_SHORT_START + 1;\n        } else {\n            assembly {\n                let byteLen := sub(byte0, 0xf7)\n                memPtr := add(memPtr, 1)\n\n                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length\n                itemLen := add(dataLen, add(byteLen, 1))\n            }\n        }\n\n        return itemLen;\n    }\n\n    // @return number of bytes until the data\n    function _payloadOffset(uint256 memPtr) private pure returns (uint256) {\n        uint256 byte0;\n        assembly {\n            byte0 := byte(0, mload(memPtr))\n        }\n\n        if (byte0 < STRING_SHORT_START) {\n            return 0;\n        } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) {\n            return 1;\n        } else if (byte0 < LIST_SHORT_START) {\n            // being explicit\n            return byte0 - (STRING_LONG_START - 1) + 1;\n        } else {\n            return byte0 - (LIST_LONG_START - 1) + 1;\n        }\n    }\n\n    /*\n     * @param src Pointer to source\n     * @param dest Pointer to destination\n     * @param len Amount of memory to copy from the source\n     */\n    function copy(uint256 src, uint256 dest, uint256 len) private pure {\n        if (len == 0) return;\n\n        // copy as many word sizes as possible\n        for (; len >= WORD_SIZE; len -= WORD_SIZE) {\n            assembly {\n                mstore(dest, mload(src))\n            }\n\n            src += WORD_SIZE;\n            dest += WORD_SIZE;\n        }\n\n        if (len > 0) {\n            // left over bytes. Mask is used to remove unwanted bytes from the word\n            uint256 mask = 256**(WORD_SIZE - len) - 1;\n            assembly {\n                let srcpart := and(mload(src), not(mask)) // zero out src\n                let destpart := and(mload(dest), mask) // retrieve the bytes\n                mstore(dest, or(destpart, srcpart))\n            }\n        }\n    }\n}\n"
      }
    }
  }}