From 07f2ead05bdfc4383c9a687f07718f60aaf6a6a8 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Fri, 13 Sep 2024 18:46:19 +0530 Subject: [PATCH 1/7] perf(arbToGno): used concurently in deploy scripts --- contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts b/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts index 55a44bfe..4ee27ef3 100644 --- a/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts +++ b/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts @@ -22,7 +22,7 @@ const paramsByChainId = { }; const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { ethers, deployments, getNamedAccounts, getChainId, config } = hre; + const { ethers, deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; // fallback to hardhat node signers on local network From 73fa3fffd49dd0eea128f867471b79fe811627f8 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Mon, 16 Sep 2024 16:41:14 +0530 Subject: [PATCH 2/7] feat(arbtoGno): deployments for testnet --- .../01-outbox/01-arb-to-gnosis-outbox.ts | 2 +- .../deploy/02-inbox/02-arb-to-gnosis-inbox.ts | 25 +- .../VeaInboxArbToGnosisTestnet.json | 449 +++++++++++++++++ .../chiado/VeaInboxGnosisToArbTestnet.json | 450 ------------------ .../chiado/VeaOutboxArbToGnosisTestnet.json | 52 +- .../sepolia/RouterArbToGnosisTestnet.json | 395 +++++++++++++++ 6 files changed, 893 insertions(+), 480 deletions(-) create mode 100644 contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json delete mode 100644 contracts/deployments/chiado/VeaInboxGnosisToArbTestnet.json create mode 100644 contracts/deployments/sepolia/RouterArbToGnosisTestnet.json diff --git a/contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts b/contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts index 5d756481..e45181ca 100644 --- a/contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts +++ b/contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts @@ -26,7 +26,7 @@ const paramsByChainId = { GNOSIS_CHIADO: { deposit: parseEther("0.2"), // ~20 WETH budget to start, enough for 8 days of challenges // bridging speed is 29 - 31 hours. - epochPeriod: 7200, // 2 hours + epochPeriod: 3600, // 1 hours minChallengePeriod: 10800, // 3 hours numEpochTimeout: 1000000, // never maxMissingBlocks: 1000000, // any diff --git a/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts b/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts index 4ee27ef3..53216051 100644 --- a/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts +++ b/contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts @@ -2,6 +2,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; import getContractAddress from "../../deploy-helpers/getContractAddress"; import { ethers } from "hardhat"; +import { providers } from "ethers"; enum SenderChains { ARBITRUM = 42161, @@ -22,7 +23,7 @@ const paramsByChainId = { }; const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { ethers, deployments, getNamedAccounts, getChainId } = hre; + const { ethers, deployments, getNamedAccounts, getChainId, config } = hre; const { deploy } = deployments; // fallback to hardhat node signers on local network @@ -39,6 +40,12 @@ const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { epochPeriod } = paramsByChainId[SenderChains[chainId]]; + const routerNetworks = { + ARBITRUM: config.networks.mainnet, + ARBITRUM_SEPOLIA: config.networks.sepolia, + HARDHAT: config.networks.localhost, + }; + // Hack to predict the deployment address on the sender chain. // TODO: use deterministic deployments @@ -76,7 +83,20 @@ const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { }; // ---------------------------------------------------------------------------------------------- - const liveDeployer = async () => {}; + const liveDeployer = async () => { + const routerChainProvider = new providers.JsonRpcProvider(routerNetworks[SenderChains[chainId]].url); + let nonceRouter = await routerChainProvider.getTransactionCount(deployer); + + const routerAddress = getContractAddress(deployer, nonceRouter); + console.log("calculated future router for nonce %d: %s", nonceRouter, routerAddress); + + await deploy("VeaInboxArbToGnosis" + (chainId === 42161 ? "" : "Testnet"), { + contract: "VeaInboxArbToGnosis", + from: deployer, + args: [epochPeriod, routerAddress], + log: true, + }); + }; // ---------------------------------------------------------------------------------------------- if (chainId === 31337) { @@ -93,5 +113,4 @@ deployInbox.skip = async ({ getChainId }) => { return !SenderChains[chainId]; }; deployInbox.runAtTheEnd = true; - export default deployInbox; diff --git a/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json b/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json new file mode 100644 index 00000000..3e914f1f --- /dev/null +++ b/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json @@ -0,0 +1,449 @@ +{ + "address": "0x72c7d51647cBeaca636d0E20A66ca2F682da3539", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochPeriod", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_routerArbToGnosis", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "_nodeData", + "type": "bytes" + } + ], + "name": "MessageSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "_snapshot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "_count", + "type": "uint64" + } + ], + "name": "SnapshotSaved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_epochSent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "_ticketId", + "type": "bytes32" + } + ], + "name": "SnapshotSent", + "type": "event" + }, + { + "inputs": [], + "name": "count", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + } + ], + "name": "epochAt", + "outputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochFinalized", + "outputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochNow", + "outputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "routerArbToGnosis", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "saveSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "_fnSelector", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "sendMessage", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "claimer", + "type": "address" + }, + { + "internalType": "uint32", + "name": "timestampClaimed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "timestampVerification", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blocknumberVerification", + "type": "uint32" + }, + { + "internalType": "enum Party", + "name": "honest", + "type": "uint8" + }, + { + "internalType": "address", + "name": "challenger", + "type": "address" + } + ], + "internalType": "struct Claim", + "name": "_claim", + "type": "tuple" + } + ], + "name": "sendSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "snapshots", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x3a9cfc748a95d422aca01d7392632aa24ba577e13408d65e14489b7fff6c4e1e", + "receipt": { + "to": null, + "from": "0xcAf9AdE1fDDf1b31d490A4629ADA638d104e9543", + "contractAddress": "0x72c7d51647cBeaca636d0E20A66ca2F682da3539", + "transactionIndex": 1, + "gasUsed": "674637", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1fa0630de812732ef9a234872182a2798844fcdd41acaff9a28e9874899c452e", + "transactionHash": "0x3a9cfc748a95d422aca01d7392632aa24ba577e13408d65e14489b7fff6c4e1e", + "logs": [], + "blockNumber": 80843239, + "cumulativeGasUsed": "674637", + "status": 1, + "byzantium": true + }, + "args": [ + 3600, + "0x22d70804d4Ef5BB206C6B39e3267DFe8a0f97d27" + ], + "numDeployments": 2, + "solcInputHash": "0d66bd5cfdf493ed8e081e9f7e1bf4fa", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epochPeriod\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_routerArbToGnosis\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_nodeData\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_snapshot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"_count\",\"type\":\"uint64\"}],\"name\":\"SnapshotSaved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epochSent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_ticketId\",\"type\":\"bytes32\"}],\"name\":\"SnapshotSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"epochAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochFinalized\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochNow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerArbToGnosis\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"saveSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"_fnSelector\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"sendSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"name\":\"snapshots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Vea Inbox From Arbitrum to Gnosis. Note: This contract is deployed on the Arbitrum.\",\"events\":{\"MessageSent(bytes)\":{\"details\":\"Relayers watch for these events to construct merkle proofs to execute transactions on Gnosis.\",\"params\":{\"_nodeData\":\"The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message).\"}},\"SnapshotSaved(bytes32,uint256,uint64)\":{\"params\":{\"_count\":\"The count of messages in the merkle tree.\",\"_epoch\":\"The epoch of the snapshot.\",\"_snapshot\":\"The snapshot of the merkle tree state root.\"}},\"SnapshotSent(uint256,bytes32)\":{\"details\":\"The event is emitted when a snapshot is sent through the canonical arbitrum bridge.\",\"params\":{\"_epochSent\":\"The epoch of the snapshot.\",\"_ticketId\":\"The ticketId of the L2->L1 message.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor. Note: epochPeriod must match the VeaOutboxArbToGnosis contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value\",\"params\":{\"_epochPeriod\":\"The duration in seconds between epochs.\",\"_routerArbToGnosis\":\"The router on Ethereum that routes from Arbitrum to Gnosis.\"}},\"epochAt(uint256)\":{\"details\":\"Get the epoch from the inbox's point of view using timestamp.\",\"params\":{\"_timestamp\":\"The timestamp to calculate the epoch from.\"},\"returns\":{\"epoch\":\"The calculated epoch.\"}},\"epochFinalized()\":{\"details\":\"Get the most recent epoch for which snapshots are finalized.\",\"returns\":{\"epoch\":\"The epoch associated with the current inbox block.timestamp\"}},\"epochNow()\":{\"details\":\"Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.\",\"returns\":{\"epoch\":\"The epoch associated with the current inbox block.timestamp\"}},\"saveSnapshot()\":{\"details\":\"Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch. `O(log(count))` where count number of messages in the inbox. Note: See merkle tree docs for details how inbox manages state.\"},\"sendMessage(address,bytes4,bytes)\":{\"details\":\"Sends an arbitrary message to Gnosis. `O(log(count))` where count is the number of messages already sent. Amortized cost is constant. Note: See docs for details how inbox manages merkle tree state.\",\"params\":{\"_data\":\"The message calldata, abi.encode(param1, param2, ...)\",\"_fnSelector\":\"The function selector of the receiving contract.\",\"_to\":\"The address of the contract on the receiving chain which receives the calldata.\"},\"returns\":{\"_0\":\"msgId The zero based index of the message in the inbox.\"}},\"sendSnapshot(uint256,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Sends the state root snapshot using Arbitrum's canonical bridge.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the snapshot requested to send.\",\"_gasLimit\":\"The gas limit for the AMB transaction on Gnosis.\"}}},\"version\":1},\"userdoc\":{\"events\":{\"SnapshotSaved(bytes32,uint256,uint64)\":{\"notice\":\"The bridgers can watch this event to claim the stateRoot on the veaOutbox.\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitrumToGnosis/VeaInboxArbToGnosis.sol\":\"VeaInboxArbToGnosis\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/arbitrumToGnosis/VeaInboxArbToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../canonical/arbitrum/IArbSys.sol\\\";\\nimport \\\"../interfaces/inboxes/IVeaInbox.sol\\\";\\nimport \\\"../interfaces/routers/IRouterToGnosis.sol\\\";\\n\\n/// @dev Vea Inbox From Arbitrum to Gnosis.\\n/// Note: This contract is deployed on the Arbitrum.\\ncontract VeaInboxArbToGnosis is IVeaInbox {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n // Arbitrum precompile ArbSys for L2->L1 messaging: https://developer.arbitrum.io/arbos/precompiles#arbsys\\n IArbSys internal constant ARB_SYS = IArbSys(address(100));\\n\\n uint256 public immutable epochPeriod; // Epochs mark the period between potential snapshots.\\n address public immutable routerArbToGnosis; // The router on ethereum.\\n\\n mapping(uint256 epoch => bytes32) public snapshots; // epoch => state root snapshot\\n\\n // Inbox represents minimum data availability to maintain incremental merkle tree.\\n // Supports a max of 2^64 - 1 messages. See merkle tree docs for details how inbox manages state.\\n\\n bytes32[64] internal inbox; // stores minimal set of complete subtree roots of the merkle tree to increment.\\n uint64 public count; // count of messages in the merkle tree\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Relayers watch for these events to construct merkle proofs to execute transactions on Gnosis.\\n /// @param _nodeData The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message).\\n event MessageSent(bytes _nodeData);\\n\\n /// The bridgers can watch this event to claim the stateRoot on the veaOutbox.\\n /// @param _snapshot The snapshot of the merkle tree state root.\\n /// @param _epoch The epoch of the snapshot.\\n /// @param _count The count of messages in the merkle tree.\\n event SnapshotSaved(bytes32 _snapshot, uint256 _epoch, uint64 _count);\\n\\n /// @dev The event is emitted when a snapshot is sent through the canonical arbitrum bridge.\\n /// @param _epochSent The epoch of the snapshot.\\n /// @param _ticketId The ticketId of the L2->L1 message.\\n event SnapshotSent(uint256 indexed _epochSent, bytes32 _ticketId);\\n\\n /// @dev Constructor.\\n /// Note: epochPeriod must match the VeaOutboxArbToGnosis contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value\\n /// @param _epochPeriod The duration in seconds between epochs.\\n /// @param _routerArbToGnosis The router on Ethereum that routes from Arbitrum to Gnosis.\\n constructor(uint256 _epochPeriod, address _routerArbToGnosis) {\\n epochPeriod = _epochPeriod;\\n routerArbToGnosis = _routerArbToGnosis;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Sends an arbitrary message to Gnosis.\\n /// `O(log(count))` where count is the number of messages already sent.\\n /// Amortized cost is constant.\\n /// Note: See docs for details how inbox manages merkle tree state.\\n /// @param _to The address of the contract on the receiving chain which receives the calldata.\\n /// @param _fnSelector The function selector of the receiving contract.\\n /// @param _data The message calldata, abi.encode(param1, param2, ...)\\n /// @return msgId The zero based index of the message in the inbox.\\n function sendMessage(address _to, bytes4 _fnSelector, bytes memory _data) external override returns (uint64) {\\n uint64 oldCount = count;\\n\\n // Given arbitrum's speed limit of 7 million gas / second, it would take atleast 8 million years of full blocks to overflow.\\n // It *should* be impossible to overflow, but we check to be safe when appending to the tree.\\n require(oldCount < type(uint64).max, \\\"Inbox is full.\\\");\\n\\n bytes memory nodeData = abi.encodePacked(\\n oldCount,\\n _to,\\n // _data is abi.encode(param1, param2, ...), we need to encode it again to get the correct leaf data\\n abi.encodePacked( // equivalent to abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\\n _fnSelector,\\n bytes32(uint256(uint160(msg.sender))), // big endian padded encoding of msg.sender, simulating abi.encodeWithSelector\\n _data\\n )\\n );\\n\\n // single hashed leaf\\n bytes32 newInboxNode = keccak256(nodeData);\\n\\n // double hashed leaf\\n // avoids second order preimage attacks\\n // https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/\\n assembly {\\n // efficient hash using EVM scratch space\\n mstore(0x00, newInboxNode)\\n newInboxNode := keccak256(0x00, 0x20)\\n }\\n\\n // increment merkle tree calculating minimal number of hashes\\n unchecked {\\n uint256 height;\\n\\n // x = oldCount + 1; acts as a bit mask to determine if a hash is needed\\n // note: x is always non-zero, and x is bit shifted to the right each loop\\n // hence this loop will always terminate in a maximum of log_2(oldCount + 1) iterations\\n for (uint64 x = oldCount + 1; x & 1 == 0; x = x >> 1) {\\n // sort sibling hashes as a convention for efficient proof validation\\n newInboxNode = sortConcatAndHash(inbox[height], newInboxNode);\\n height++;\\n }\\n\\n inbox[height] = newInboxNode;\\n\\n // finally increment count\\n count = oldCount + 1;\\n }\\n\\n emit MessageSent(nodeData);\\n\\n // old count is the zero indexed leaf position in the tree, acts as a msgId\\n // gateways should index these msgIds to later relay proofs\\n return oldCount;\\n }\\n\\n /// @dev Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch.\\n /// `O(log(count))` where count number of messages in the inbox.\\n /// Note: See merkle tree docs for details how inbox manages state.\\n function saveSnapshot() external {\\n uint256 epoch;\\n bytes32 stateRoot;\\n\\n unchecked {\\n epoch = block.timestamp / epochPeriod;\\n\\n // calculate the current root of the incremental merkle tree encoded in the inbox\\n\\n uint256 height;\\n\\n // x acts as a bit mask to determine if the hash stored in the inbox contributes to the root\\n uint256 x;\\n\\n // x is bit shifted to the right each loop, hence this loop will always terminate in a maximum of log_2(count) iterations\\n for (x = uint256(count); x > 0; x = x >> 1) {\\n if ((x & 1) == 1) {\\n // first hash is special case\\n // inbox stores the root of complete subtrees\\n // eg if count = 4 = 0b100, then the first complete subtree is inbox[2]\\n // inbox = [H(3), H(1,2), H(1,4)], we read inbox[2] directly\\n\\n stateRoot = inbox[height];\\n break;\\n }\\n height++;\\n }\\n\\n // after the first hash, we can calculate the root incrementally\\n for (x = x >> 1; x > 0; x = x >> 1) {\\n height++;\\n if ((x & 1) == 1) {\\n // sort sibling hashes as a convention for efficient proof validation\\n stateRoot = sortConcatAndHash(inbox[height], stateRoot);\\n }\\n }\\n }\\n\\n snapshots[epoch] = stateRoot;\\n\\n emit SnapshotSaved(stateRoot, epoch, count);\\n }\\n\\n /// @dev Helper function to calculate merkle tree interior nodes by sorting and concatenating and hashing a pair of children nodes, left and right.\\n /// Note: EVM scratch space is used to efficiently calculate hashes.\\n /// @param _left The left hash.\\n /// @param _right The right hash.\\n /// @return parent The parent hash.\\n function sortConcatAndHash(bytes32 _left, bytes32 _right) internal pure returns (bytes32 parent) {\\n // sort sibling hashes as a convention for efficient proof validation\\n if (_left < _right) {\\n // efficient hash using EVM scratch space\\n assembly {\\n mstore(0x00, _left)\\n mstore(0x20, _right)\\n parent := keccak256(0x00, 0x40)\\n }\\n } else {\\n assembly {\\n mstore(0x00, _right)\\n mstore(0x20, _left)\\n parent := keccak256(0x00, 0x40)\\n }\\n }\\n }\\n\\n /// @dev Sends the state root snapshot using Arbitrum's canonical bridge.\\n /// @param _epoch The epoch of the snapshot requested to send.\\n /// @param _gasLimit The gas limit for the AMB transaction on Gnosis.\\n /// @param _claim The claim associated with the epoch.\\n function sendSnapshot(uint256 _epoch, uint256 _gasLimit, Claim memory _claim) external virtual {\\n unchecked {\\n require(_epoch < block.timestamp / epochPeriod, \\\"Can only send past epoch snapshot.\\\");\\n }\\n\\n bytes memory data = abi.encodeCall(IRouterToGnosis.route, (_epoch, snapshots[_epoch], _gasLimit, _claim));\\n\\n // Arbitrum -> Ethereum message with native bridge\\n // docs: https://developer.arbitrum.io/for-devs/cross-chain-messsaging#arbitrum-to-ethereum-messaging\\n // example: https://github.com/OffchainLabs/arbitrum-tutorials/blob/2c1b7d2db8f36efa496e35b561864c0f94123a5f/packages/greeter/contracts/arbitrum/GreeterL2.sol#L25\\n bytes32 ticketID = bytes32(ARB_SYS.sendTxToL1(routerArbToGnosis, data));\\n\\n emit SnapshotSent(_epoch, ticketID);\\n }\\n\\n // ************************************* //\\n // * Pure / Views * //\\n // ************************************* //\\n\\n /// @dev Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.\\n /// @return epoch The epoch associated with the current inbox block.timestamp\\n function epochNow() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the most recent epoch for which snapshots are finalized.\\n /// @return epoch The epoch associated with the current inbox block.timestamp\\n function epochFinalized() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod - 1;\\n }\\n\\n /// @dev Get the epoch from the inbox's point of view using timestamp.\\n /// @param _timestamp The timestamp to calculate the epoch from.\\n /// @return epoch The calculated epoch.\\n function epochAt(uint256 _timestamp) external view returns (uint256 epoch) {\\n epoch = _timestamp / epochPeriod;\\n }\\n}\\n\",\"keccak256\":\"0xf5706fefe86eb3bf49a130df2b54030f325327729e9ade1a94be9132eb77e333\",\"license\":\"MIT\"},\"src/canonical/arbitrum/IArbSys.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n// https://developer.arbitrum.io/arbos/precompiles#arbsys\\n// https://github.com/OffchainLabs/nitro-contracts/blob/39ea5a163afc637e2706d9be29cf7a289c300d00/src/precompiles/ArbSys.sol\\n// https://arbiscan.io/address/0x0000000000000000000000000000000000000064#code\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\n///@title System level functionality\\n///@notice For use by contracts to interact with core L2-specific functionality.\\n///Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064.\\ninterface IArbSys {\\n /// @notice Send a transaction to L1\\n /// @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data\\n /// to a contract address without any code (as enforced by the Bridge contract).\\n /// @param destination recipient address on L1\\n /// @param data (optional) calldata for L1 contract call\\n /// @return a unique identifier for this L2-to-L1 transaction.\\n function sendTxToL1(address destination, bytes calldata data) external payable returns (uint256);\\n}\\n\",\"keccak256\":\"0x5ae1fd0267552160821402b9bc50b2551b086904436e5abe838599179b279420\",\"license\":\"BUSL-1.1\"},\"src/interfaces/inboxes/IVeaInbox.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\ninterface IVeaInbox {\\n /// @dev Sends an arbitrary message to receiving chain.\\n /// Note: Calls authenticated by receiving gateway checking the sender argument.\\n /// @param _to The cross-domain contract address which receives the calldata.\\n /// @param _fnSelection The function selector of the receiving contract.\\n /// @param _data The message calldata, abi.encode(...)\\n /// @return msgId The index of the message in the inbox, as a message Id, needed to relay the message.\\n function sendMessage(address _to, bytes4 _fnSelection, bytes memory _data) external returns (uint64 msgId);\\n\\n /// @dev Snapshots can be saved a maximum of once per epoch.\\n /// Saves snapshot of state root.\\n /// `O(log(count))` where count number of messages in the inbox.\\n function saveSnapshot() external;\\n}\\n\",\"keccak256\":\"0xa8e2f65b7596235422f39933af80f02473493d2b15b398d7e34b81c82bd24a29\",\"license\":\"MIT\"},\"src/interfaces/routers/IRouterToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../types/VeaClaim.sol\\\";\\n\\n/// @dev Interface of the Vea Router which routes messages to Gnosis through the AMB.\\n/// @dev eg. L2 on Ethereum -> Ethereum (L1) -> Gnosis (L1), the IRouterToL1 will be deployed on Ethereum (L1) routing messages to Gnosis (L1).\\ninterface IRouterToGnosis {\\n /// @dev Routes state root snapshots through intermediary chains to the final destination L1 chain.\\n /// Note: Access restricted to canonical sending-chain bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _gasLimit The gas limit for the AMB message.\\n /// @param _claim The claim associated with the epoch.\\n function route(uint256 _epoch, bytes32 _stateRoot, uint256 _gasLimit, Claim memory _claim) external;\\n}\\n\",\"keccak256\":\"0x9d78c7872bd2bc3b206fc6d6dfa8f8b2dab4122b10bfe0d0ab1f76bec92613b6\",\"license\":\"MIT\"},\"src/interfaces/types/VeaClaim.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nenum Party {\\n None,\\n Claimer,\\n Challenger\\n}\\n\\nstruct Claim {\\n bytes32 stateRoot;\\n address claimer;\\n uint32 timestampClaimed;\\n uint32 timestampVerification;\\n uint32 blocknumberVerification;\\n Party honest;\\n address challenger;\\n}\\n\",\"keccak256\":\"0xfef781e359c97aebbe8dbfcb75edb7cb962139fd9ea538b8b89a3f2e13a05bfe\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561000f575f80fd5b50604051610c01380380610c0183398101604081905261002e91610045565b6080919091526001600160a01b031660a05261007f565b5f8060408385031215610056575f80fd5b825160208401519092506001600160a01b0381168114610074575f80fd5b809150509250929050565b60805160a051610b376100ca5f395f818161014b01526105d201525f8181610124015281816101bd015281816101ef015281816102240152818161025301526104df0152610b375ff3fe608060405234801561000f575f80fd5b506004361061009b575f3560e01c80635f85896c116100635780635f85896c1461010c578063b5b7a1841461011f578063d5e6a9df14610146578063d6565a2d14610185578063dc881a72146101a4575f80fd5b806306661abd1461009f578063222ae786146100d15780633ac3b6b6146100e75780634a439cfe146100ef5780635192053514610102575b5f80fd5b6041546100b39067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6100d96101b7565b6040519081526020016100c8565b6100d96101e7565b6100d96100fd3660046106a8565b61021e565b61010a61024f565b005b6100b361011a366004610748565b610370565b6100d97f000000000000000000000000000000000000000000000000000000000000000081565b61016d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100c8565b6100d96101933660046106a8565b5f6020819052908152604090205481565b61010a6101b2366004610818565b6104dd565b5f6101e27f0000000000000000000000000000000000000000000000000000000000000000426108e3565b905090565b5f60016102147f0000000000000000000000000000000000000000000000000000000000000000426108e3565b6101e29190610902565b5f6102497f0000000000000000000000000000000000000000000000000000000000000000836108e3565b92915050565b5f807f00000000000000000000000000000000000000000000000000000000000000004281610280576102806108cf565b60415491900492505f9067ffffffffffffffff165b80156102ce57806001166001036102c257600182604081106102b9576102b9610921565b015492506102ce565b6001918201911c610295565b60011c5b801561031057600191820191818116900361030857610305600183604081106102fd576102fd610921565b01548461067b565b92505b60011c6102d2565b50505f8281526020818152604091829020839055604154825184815291820185905267ffffffffffffffff168183015290517f592424eb1d6135501bd20833f15fd127c29d08eed4f03872f6f75182126b1e489181900360600190a15050565b6041545f9067ffffffffffffffff9081169081106103c65760405162461bcd60e51b815260206004820152600e60248201526d24b73137bc1034b990333ab6361760911b60448201526064015b60405180910390fd5b6040515f90829087906103e190889033908990602001610957565b60408051601f198184030181529082905261040093929160200161098c565b60408051601f1981840301815291905280516020808301919091205f908152908120919250600184015b600181165f036104625761044a600183604081106102fd576102fd610921565b92506001918201911c677fffffffffffffff1661042a565b50816001826040811061047757610477610921565b0155506041805467ffffffffffffffff19166001850167ffffffffffffffff161790556040517f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036906104ca908490610a05565b60405180910390a1509095945050505050565b7f0000000000000000000000000000000000000000000000000000000000000000428161050c5761050c6108cf565b0483106105665760405162461bcd60e51b815260206004820152602260248201527f43616e206f6e6c792073656e6420706173742065706f636820736e617073686f6044820152613a1760f11b60648201526084016103bd565b5f8381526020819052604080822054905161058991869186908690602401610a1e565b60408051601f198184030181529181526020820180516001600160e01b031663b1126dad60e01b179052516349460b4d60e11b81529091505f9060649063928c169a906105fc907f0000000000000000000000000000000000000000000000000000000000000000908690600401610abf565b6020604051808303815f875af1158015610618573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063c9190610aea565b60405181815290915085907f6fdd49f435101fc7b6ebdec7c8972932a926d18f6cb78a8891dfe950743b6b829060200160405180910390a25050505050565b5f8183101561069657825f528160205260405f209050610249565b505f9081526020919091526040902090565b5f602082840312156106b8575f80fd5b5035919050565b80356001600160a01b03811681146106d5575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b60405160e0810167ffffffffffffffff81118282101715610711576107116106da565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610740576107406106da565b604052919050565b5f805f6060848603121561075a575f80fd5b610763846106bf565b92506020848101356001600160e01b031981168114610780575f80fd5b9250604085013567ffffffffffffffff8082111561079c575f80fd5b818701915087601f8301126107af575f80fd5b8135818111156107c1576107c16106da565b6107d3601f8201601f19168501610717565b915080825288848285010111156107e8575f80fd5b80848401858401375f848284010152508093505050509250925092565b803563ffffffff811681146106d5575f80fd5b5f805f83850361012081121561082c575f80fd5b843593506020850135925060e0603f1982011215610848575f80fd5b506108516106ee565b60408501358152610864606086016106bf565b602082015261087560808601610805565b604082015261088660a08601610805565b606082015261089760c08601610805565b608082015260e0850135600381106108ad575f80fd5b60a08201526108bf61010086016106bf565b60c0820152809150509250925092565b634e487b7160e01b5f52601260045260245ffd5b5f826108fd57634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561024957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5b8381101561094f578181015183820152602001610937565b50505f910152565b63ffffffff60e01b841681528260048201525f825161097d816024850160208701610935565b91909101602401949350505050565b67ffffffffffffffff60c01b8460c01b1681526bffffffffffffffffffffffff198360601b1660088201525f82516109cb81601c850160208701610935565b91909101601c01949350505050565b5f81518084526109f1816020860160208601610935565b601f01601f19169290920160200192915050565b602081525f610a1760208301846109da565b9392505050565b5f610140820190508582528460208301528360408301528251606083015260018060a01b036020840151166080830152604083015163ffffffff80821660a08501528060608601511660c08501528060808601511660e0850152505060a083015160038110610a9b57634e487b7160e01b5f52602160045260245ffd5b61010083015260c092909201516001600160a01b0316610120909101529392505050565b6001600160a01b03831681526040602082018190525f90610ae2908301846109da565b949350505050565b5f60208284031215610afa575f80fd5b505191905056fea26469706673582212202d649cbd9f2d8c6de23d68dcef4120219fd7f19544dca063a8d508394cfcb79764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061009b575f3560e01c80635f85896c116100635780635f85896c1461010c578063b5b7a1841461011f578063d5e6a9df14610146578063d6565a2d14610185578063dc881a72146101a4575f80fd5b806306661abd1461009f578063222ae786146100d15780633ac3b6b6146100e75780634a439cfe146100ef5780635192053514610102575b5f80fd5b6041546100b39067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6100d96101b7565b6040519081526020016100c8565b6100d96101e7565b6100d96100fd3660046106a8565b61021e565b61010a61024f565b005b6100b361011a366004610748565b610370565b6100d97f000000000000000000000000000000000000000000000000000000000000000081565b61016d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100c8565b6100d96101933660046106a8565b5f6020819052908152604090205481565b61010a6101b2366004610818565b6104dd565b5f6101e27f0000000000000000000000000000000000000000000000000000000000000000426108e3565b905090565b5f60016102147f0000000000000000000000000000000000000000000000000000000000000000426108e3565b6101e29190610902565b5f6102497f0000000000000000000000000000000000000000000000000000000000000000836108e3565b92915050565b5f807f00000000000000000000000000000000000000000000000000000000000000004281610280576102806108cf565b60415491900492505f9067ffffffffffffffff165b80156102ce57806001166001036102c257600182604081106102b9576102b9610921565b015492506102ce565b6001918201911c610295565b60011c5b801561031057600191820191818116900361030857610305600183604081106102fd576102fd610921565b01548461067b565b92505b60011c6102d2565b50505f8281526020818152604091829020839055604154825184815291820185905267ffffffffffffffff168183015290517f592424eb1d6135501bd20833f15fd127c29d08eed4f03872f6f75182126b1e489181900360600190a15050565b6041545f9067ffffffffffffffff9081169081106103c65760405162461bcd60e51b815260206004820152600e60248201526d24b73137bc1034b990333ab6361760911b60448201526064015b60405180910390fd5b6040515f90829087906103e190889033908990602001610957565b60408051601f198184030181529082905261040093929160200161098c565b60408051601f1981840301815291905280516020808301919091205f908152908120919250600184015b600181165f036104625761044a600183604081106102fd576102fd610921565b92506001918201911c677fffffffffffffff1661042a565b50816001826040811061047757610477610921565b0155506041805467ffffffffffffffff19166001850167ffffffffffffffff161790556040517f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036906104ca908490610a05565b60405180910390a1509095945050505050565b7f0000000000000000000000000000000000000000000000000000000000000000428161050c5761050c6108cf565b0483106105665760405162461bcd60e51b815260206004820152602260248201527f43616e206f6e6c792073656e6420706173742065706f636820736e617073686f6044820152613a1760f11b60648201526084016103bd565b5f8381526020819052604080822054905161058991869186908690602401610a1e565b60408051601f198184030181529181526020820180516001600160e01b031663b1126dad60e01b179052516349460b4d60e11b81529091505f9060649063928c169a906105fc907f0000000000000000000000000000000000000000000000000000000000000000908690600401610abf565b6020604051808303815f875af1158015610618573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063c9190610aea565b60405181815290915085907f6fdd49f435101fc7b6ebdec7c8972932a926d18f6cb78a8891dfe950743b6b829060200160405180910390a25050505050565b5f8183101561069657825f528160205260405f209050610249565b505f9081526020919091526040902090565b5f602082840312156106b8575f80fd5b5035919050565b80356001600160a01b03811681146106d5575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b60405160e0810167ffffffffffffffff81118282101715610711576107116106da565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610740576107406106da565b604052919050565b5f805f6060848603121561075a575f80fd5b610763846106bf565b92506020848101356001600160e01b031981168114610780575f80fd5b9250604085013567ffffffffffffffff8082111561079c575f80fd5b818701915087601f8301126107af575f80fd5b8135818111156107c1576107c16106da565b6107d3601f8201601f19168501610717565b915080825288848285010111156107e8575f80fd5b80848401858401375f848284010152508093505050509250925092565b803563ffffffff811681146106d5575f80fd5b5f805f83850361012081121561082c575f80fd5b843593506020850135925060e0603f1982011215610848575f80fd5b506108516106ee565b60408501358152610864606086016106bf565b602082015261087560808601610805565b604082015261088660a08601610805565b606082015261089760c08601610805565b608082015260e0850135600381106108ad575f80fd5b60a08201526108bf61010086016106bf565b60c0820152809150509250925092565b634e487b7160e01b5f52601260045260245ffd5b5f826108fd57634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561024957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5b8381101561094f578181015183820152602001610937565b50505f910152565b63ffffffff60e01b841681528260048201525f825161097d816024850160208701610935565b91909101602401949350505050565b67ffffffffffffffff60c01b8460c01b1681526bffffffffffffffffffffffff198360601b1660088201525f82516109cb81601c850160208701610935565b91909101601c01949350505050565b5f81518084526109f1816020860160208601610935565b601f01601f19169290920160200192915050565b602081525f610a1760208301846109da565b9392505050565b5f610140820190508582528460208301528360408301528251606083015260018060a01b036020840151166080830152604083015163ffffffff80821660a08501528060608601511660c08501528060808601511660e0850152505060a083015160038110610a9b57634e487b7160e01b5f52602160045260245ffd5b61010083015260c092909201516001600160a01b0316610120909101529392505050565b6001600160a01b03831681526040602082018190525f90610ae2908301846109da565b949350505050565b5f60208284031215610afa575f80fd5b505191905056fea26469706673582212202d649cbd9f2d8c6de23d68dcef4120219fd7f19544dca063a8d508394cfcb79764736f6c63430008180033", + "devdoc": { + "details": "Vea Inbox From Arbitrum to Gnosis. Note: This contract is deployed on the Arbitrum.", + "events": { + "MessageSent(bytes)": { + "details": "Relayers watch for these events to construct merkle proofs to execute transactions on Gnosis.", + "params": { + "_nodeData": "The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message)." + } + }, + "SnapshotSaved(bytes32,uint256,uint64)": { + "params": { + "_count": "The count of messages in the merkle tree.", + "_epoch": "The epoch of the snapshot.", + "_snapshot": "The snapshot of the merkle tree state root." + } + }, + "SnapshotSent(uint256,bytes32)": { + "details": "The event is emitted when a snapshot is sent through the canonical arbitrum bridge.", + "params": { + "_epochSent": "The epoch of the snapshot.", + "_ticketId": "The ticketId of the L2->L1 message." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "details": "Constructor. Note: epochPeriod must match the VeaOutboxArbToGnosis contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value", + "params": { + "_epochPeriod": "The duration in seconds between epochs.", + "_routerArbToGnosis": "The router on Ethereum that routes from Arbitrum to Gnosis." + } + }, + "epochAt(uint256)": { + "details": "Get the epoch from the inbox's point of view using timestamp.", + "params": { + "_timestamp": "The timestamp to calculate the epoch from." + }, + "returns": { + "epoch": "The calculated epoch." + } + }, + "epochFinalized()": { + "details": "Get the most recent epoch for which snapshots are finalized.", + "returns": { + "epoch": "The epoch associated with the current inbox block.timestamp" + } + }, + "epochNow()": { + "details": "Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.", + "returns": { + "epoch": "The epoch associated with the current inbox block.timestamp" + } + }, + "saveSnapshot()": { + "details": "Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch. `O(log(count))` where count number of messages in the inbox. Note: See merkle tree docs for details how inbox manages state." + }, + "sendMessage(address,bytes4,bytes)": { + "details": "Sends an arbitrary message to Gnosis. `O(log(count))` where count is the number of messages already sent. Amortized cost is constant. Note: See docs for details how inbox manages merkle tree state.", + "params": { + "_data": "The message calldata, abi.encode(param1, param2, ...)", + "_fnSelector": "The function selector of the receiving contract.", + "_to": "The address of the contract on the receiving chain which receives the calldata." + }, + "returns": { + "_0": "msgId The zero based index of the message in the inbox." + } + }, + "sendSnapshot(uint256,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))": { + "details": "Sends the state root snapshot using Arbitrum's canonical bridge.", + "params": { + "_claim": "The claim associated with the epoch.", + "_epoch": "The epoch of the snapshot requested to send.", + "_gasLimit": "The gas limit for the AMB transaction on Gnosis." + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "SnapshotSaved(bytes32,uint256,uint64)": { + "notice": "The bridgers can watch this event to claim the stateRoot on the veaOutbox." + } + }, + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2245, + "contract": "src/arbitrumToGnosis/VeaInboxArbToGnosis.sol:VeaInboxArbToGnosis", + "label": "snapshots", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_bytes32)" + }, + { + "astId": 2249, + "contract": "src/arbitrumToGnosis/VeaInboxArbToGnosis.sol:VeaInboxArbToGnosis", + "label": "inbox", + "offset": 0, + "slot": "1", + "type": "t_array(t_bytes32)64_storage" + }, + { + "astId": 2251, + "contract": "src/arbitrumToGnosis/VeaInboxArbToGnosis.sol:VeaInboxArbToGnosis", + "label": "count", + "offset": 0, + "slot": "65", + "type": "t_uint64" + } + ], + "types": { + "t_array(t_bytes32)64_storage": { + "base": "t_bytes32", + "encoding": "inplace", + "label": "bytes32[64]", + "numberOfBytes": "2048" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bytes32)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} diff --git a/contracts/deployments/chiado/VeaInboxGnosisToArbTestnet.json b/contracts/deployments/chiado/VeaInboxGnosisToArbTestnet.json deleted file mode 100644 index 8fb15964..00000000 --- a/contracts/deployments/chiado/VeaInboxGnosisToArbTestnet.json +++ /dev/null @@ -1,450 +0,0 @@ -{ - "address": "0xC21c20a719fAc23c54c336FA0E16a0CFdC4baA00", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epochPeriod", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_routerGnosisToArb", - "type": "address" - }, - { - "internalType": "contract IAMB", - "name": "_amb", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "_nodeData", - "type": "bytes" - } - ], - "name": "MessageSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "_snapshot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "_count", - "type": "uint64" - } - ], - "name": "SnapshotSaved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_epochSent", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "_ticketId", - "type": "bytes32" - } - ], - "name": "SnapshotSent", - "type": "event" - }, - { - "inputs": [], - "name": "amb", - "outputs": [ - { - "internalType": "contract IAMB", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "count", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - } - ], - "name": "epochAt", - "outputs": [ - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochFinalized", - "outputs": [ - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochNow", - "outputs": [ - { - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochPeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "routerGnosisToArb", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "saveSnapshot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "_fnSelector", - "type": "bytes4" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "sendMessage", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_inboxIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_excessFeeRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxFeePerGas", - "type": "uint256" - } - ], - "name": "sendSnapshot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "snapshots", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x1a55a618bf45d5bc51bf4cb28f10b3f2245e4693d62baf563fa01a31578b2de3", - "receipt": { - "to": null, - "from": "0x407DDEC61d69b212498B140a26da70AE1C879f5a", - "contractAddress": "0xC21c20a719fAc23c54c336FA0E16a0CFdC4baA00", - "transactionIndex": 0, - "gasUsed": "665312", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xdd9c7358639288db01ef3c3212f0adbeb1c77d99dfadb23e93c82eea126d9cb8", - "transactionHash": "0x1a55a618bf45d5bc51bf4cb28f10b3f2245e4693d62baf563fa01a31578b2de3", - "logs": [], - "blockNumber": 4814060, - "cumulativeGasUsed": "665312", - "status": 1, - "byzantium": true - }, - "args": [ - 7200, - "0x18AB70ea8dBc7072D1C1C90bA0bC1547d92198CF", - "0x99Ca51a3534785ED619f46A79C7Ad65Fa8d85e7a" - ], - "numDeployments": 8, - "solcInputHash": "76a6a9e6371fade9c8f1066bebbf4e7c", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epochPeriod\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_routerGnosisToArb\",\"type\":\"address\"},{\"internalType\":\"contract IAMB\",\"name\":\"_amb\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_nodeData\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_snapshot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"_count\",\"type\":\"uint64\"}],\"name\":\"SnapshotSaved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epochSent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_ticketId\",\"type\":\"bytes32\"}],\"name\":\"SnapshotSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"epochAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochFinalized\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochNow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerGnosisToArb\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"saveSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"_fnSelector\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_inboxIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxSubmissionCost\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_excessFeeRefundAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxFeePerGas\",\"type\":\"uint256\"}],\"name\":\"sendSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"snapshots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Vea Inbox From Gnosis to Arbitrum. Note: This contract is deployed on the Gnosis.\",\"events\":{\"MessageSent(bytes)\":{\"details\":\"Relayers watch for these events to construct merkle proofs to execute transactions on Ethereum.\",\"params\":{\"_nodeData\":\"The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message).\"}},\"SnapshotSaved(bytes32,uint256,uint64)\":{\"params\":{\"_count\":\"The count of messages in the merkle tree.\",\"_epoch\":\"The epoch of the snapshot.\",\"_snapshot\":\"The snapshot of the merkle tree state root.\"}},\"SnapshotSent(uint256,bytes32)\":{\"details\":\"The event is emitted when a snapshot is sent through the canonical arbitrum bridge.\",\"params\":{\"_epochSent\":\"The epoch of the snapshot.\",\"_ticketId\":\"The ticketId of the L2->L1 message.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor. Note: epochPeriod must match the VeaOutboxGnosisToArb contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value\",\"params\":{\"_amb\":\"The address of the AMB contract on Gnosis.\",\"_epochPeriod\":\"The duration in seconds between epochs.\",\"_routerGnosisToArb\":\"The router on Ethereum that routes from Gnosis to Arbitrum.\"}},\"epochAt(uint256)\":{\"details\":\"Get the epoch from the inbox's point of view using timestamp.\",\"params\":{\"_timestamp\":\"The timestamp to calculate the epoch from.\"},\"returns\":{\"epoch\":\"The calculated epoch.\"}},\"epochFinalized()\":{\"details\":\"Get the most recent epoch for which snapshots are finalized.\",\"returns\":{\"epoch\":\"The epoch associated with the current inbox block.timestamp\"}},\"epochNow()\":{\"details\":\"Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.\",\"returns\":{\"epoch\":\"The epoch associated with the current inbox block.timestamp\"}},\"saveSnapshot()\":{\"details\":\"Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch. `O(log(count))` where count number of messages in the inbox. Note: See merkle tree docs for details how inbox manages state.\"},\"sendMessage(address,bytes4,bytes)\":{\"details\":\"Sends an arbitrary message to Gnosis. `O(log(count))` where count is the number of messages already sent. Amortized cost is constant. Note: See docs for details how inbox manages merkle tree state.\",\"params\":{\"_data\":\"The message calldata, abi.encode(param1, param2, ...)\",\"_fnSelector\":\"The function selector of the receiving contract.\",\"_to\":\"The address of the contract on the receiving chain which receives the calldata.\"},\"returns\":{\"_0\":\"msgId The zero based index of the message in the inbox.\"}},\"sendSnapshot(uint256,uint256,uint256,address,uint256,uint256)\":{\"details\":\"Sends the state root snapshot using Arbitrum's canonical bridge.\",\"params\":{\"_epoch\":\"The epoch of the snapshot requested to send.\",\"_excessFeeRefundAddress\":\"Address to refund any excess fee to\",\"_gasLimit\":\"Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\",\"_inboxIndex\":\"The index of the inbox in the Arbitrum bridge contract.\",\"_maxFeePerGas\":\"price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\",\"_maxSubmissionCost\":\"Max gas deducted from user's L2 balance to cover base submission fee\"}}},\"version\":1},\"userdoc\":{\"events\":{\"SnapshotSaved(bytes32,uint256,uint64)\":{\"notice\":\"The bridgers can watch this event to claim the stateRoot on the veaOutbox.\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/gnosisToArbitrum/VeaInboxGnosisToArb.sol\":\"VeaInboxGnosisToArb\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/canonical/gnosis-chain/IAMB.sol\":{\"content\":\"// https://docs.gnosischain.com/bridges/tokenbridge/amb-bridge#gnosis\\n// https://github.com/omni/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/interfaces/IAMB.sol\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.18;\\n\\ninterface IAMB {\\n function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);\\n\\n function maxGasPerTx() external view returns (uint256);\\n\\n function messageSender() external view returns (address);\\n\\n function messageSourceChainId() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x529d45e46ca0c046c32b296b35ae8073c4a999ef37510545ec44d26e78deca0d\"},\"src/gnosisToArbitrum/VeaInboxGnosisToArb.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"../canonical/gnosis-chain/IAMB.sol\\\";\\nimport \\\"../interfaces/inboxes/IVeaInbox.sol\\\";\\nimport \\\"../interfaces/routers/IRouterToArb.sol\\\";\\n\\n/// @dev Vea Inbox From Gnosis to Arbitrum.\\n/// Note: This contract is deployed on the Gnosis.\\ncontract VeaInboxGnosisToArb is IVeaInbox {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n IAMB public immutable amb; // The address of the AMB contract on Gnosis.\\n\\n uint256 public immutable epochPeriod; // Epochs mark the period between potential snapshots.\\n address public immutable routerGnosisToArb; // The router on Ethereum.\\n\\n mapping(uint256 => bytes32) public snapshots; // epoch => state root snapshot\\n\\n // Inbox represents minimum data availability to maintain incremental merkle tree.\\n // Supports a max of 2^64 - 1 messages. See merkle tree docs for details how inbox manages state.\\n\\n bytes32[64] internal inbox; // stores minimal set of complete subtree roots of the merkle tree to increment.\\n uint64 public count; // count of messages in the merkle tree\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Relayers watch for these events to construct merkle proofs to execute transactions on Ethereum.\\n /// @param _nodeData The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message).\\n event MessageSent(bytes _nodeData);\\n\\n /// The bridgers can watch this event to claim the stateRoot on the veaOutbox.\\n /// @param _snapshot The snapshot of the merkle tree state root.\\n /// @param _epoch The epoch of the snapshot.\\n /// @param _count The count of messages in the merkle tree.\\n event SnapshotSaved(bytes32 _snapshot, uint256 _epoch, uint64 _count);\\n\\n /// @dev The event is emitted when a snapshot is sent through the canonical arbitrum bridge.\\n /// @param _epochSent The epoch of the snapshot.\\n /// @param _ticketId The ticketId of the L2->L1 message.\\n event SnapshotSent(uint256 indexed _epochSent, bytes32 _ticketId);\\n\\n /// @dev Constructor.\\n /// Note: epochPeriod must match the VeaOutboxGnosisToArb contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value\\n /// @param _epochPeriod The duration in seconds between epochs.\\n /// @param _routerGnosisToArb The router on Ethereum that routes from Gnosis to Arbitrum.\\n /// @param _amb The address of the AMB contract on Gnosis.\\n constructor(uint256 _epochPeriod, address _routerGnosisToArb, IAMB _amb) {\\n epochPeriod = _epochPeriod;\\n routerGnosisToArb = _routerGnosisToArb;\\n amb = _amb;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Sends an arbitrary message to Gnosis.\\n /// `O(log(count))` where count is the number of messages already sent.\\n /// Amortized cost is constant.\\n /// Note: See docs for details how inbox manages merkle tree state.\\n /// @param _to The address of the contract on the receiving chain which receives the calldata.\\n /// @param _fnSelector The function selector of the receiving contract.\\n /// @param _data The message calldata, abi.encode(param1, param2, ...)\\n /// @return msgId The zero based index of the message in the inbox.\\n function sendMessage(address _to, bytes4 _fnSelector, bytes memory _data) external override returns (uint64) {\\n uint64 oldCount = count;\\n\\n // Given arbitrum's speed limit of 7 million gas / second, it would take atleast 8 million years of full blocks to overflow.\\n // It *should* be impossible to overflow, but we check to be safe when appending to the tree.\\n require(oldCount < type(uint64).max, \\\"Inbox is full.\\\");\\n\\n bytes memory nodeData = abi.encodePacked(\\n oldCount,\\n _to,\\n // _data is abi.encode(param1, param2, ...), we need to encode it again to get the correct leaf data\\n abi.encodePacked( // equivalent to abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\\n _fnSelector,\\n bytes32(uint256(uint160(msg.sender))), // big endian padded encoding of msg.sender, simulating abi.encodeWithSelector\\n _data\\n )\\n );\\n\\n // single hashed leaf\\n bytes32 newInboxNode = keccak256(nodeData);\\n\\n // double hashed leaf\\n // avoids second order preimage attacks\\n // https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/\\n assembly {\\n // efficient hash using EVM scratch space\\n mstore(0x00, newInboxNode)\\n newInboxNode := keccak256(0x00, 0x20)\\n }\\n\\n // increment merkle tree calculating minimal number of hashes\\n unchecked {\\n uint256 height;\\n\\n // x = oldCount + 1; acts as a bit mask to determine if a hash is needed\\n // note: x is always non-zero, and x is bit shifted to the right each loop\\n // hence this loop will always terminate in a maximum of log_2(oldCount + 1) iterations\\n for (uint64 x = oldCount + 1; x & 1 == 0; x = x >> 1) {\\n // sort sibling hashes as a convention for efficient proof validation\\n newInboxNode = sortConcatAndHash(inbox[height], newInboxNode);\\n height++;\\n }\\n\\n inbox[height] = newInboxNode;\\n\\n // finally increment count\\n count = oldCount + 1;\\n }\\n\\n emit MessageSent(nodeData);\\n\\n // old count is the zero indexed leaf position in the tree, acts as a msgId\\n // gateways should index these msgIds to later relay proofs\\n return oldCount;\\n }\\n\\n /// @dev Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch.\\n /// `O(log(count))` where count number of messages in the inbox.\\n /// Note: See merkle tree docs for details how inbox manages state.\\n function saveSnapshot() external {\\n uint256 epoch;\\n bytes32 stateRoot;\\n\\n unchecked {\\n epoch = block.timestamp / epochPeriod;\\n\\n // calculate the current root of the incremental merkle tree encoded in the inbox\\n\\n uint256 height;\\n\\n // x acts as a bit mask to determine if the hash stored in the inbox contributes to the root\\n uint256 x;\\n\\n // x is bit shifted to the right each loop, hence this loop will always terminate in a maximum of log_2(count) iterations\\n for (x = uint256(count); x > 0; x = x >> 1) {\\n if ((x & 1) == 1) {\\n // first hash is special case\\n // inbox stores the root of complete subtrees\\n // eg if count = 4 = 0b100, then the first complete subtree is inbox[2]\\n // inbox = [H(3), H(1,2), H(1,4)], we read inbox[2] directly\\n\\n stateRoot = inbox[height];\\n break;\\n }\\n height++;\\n }\\n\\n // after the first hash, we can calculate the root incrementally\\n for (x = x >> 1; x > 0; x = x >> 1) {\\n height++;\\n if ((x & 1) == 1) {\\n // sort sibling hashes as a convention for efficient proof validation\\n stateRoot = sortConcatAndHash(inbox[height], stateRoot);\\n }\\n }\\n }\\n\\n snapshots[epoch] = stateRoot;\\n\\n emit SnapshotSaved(stateRoot, epoch, count);\\n }\\n\\n /// @dev Helper function to calculate merkle tree interior nodes by sorting and concatenating and hashing a pair of children nodes, left and right.\\n /// Note: EVM scratch space is used to efficiently calculate hashes.\\n /// @param _left The left hash.\\n /// @param _right The right hash.\\n /// @return parent The parent hash.\\n function sortConcatAndHash(bytes32 _left, bytes32 _right) internal pure returns (bytes32 parent) {\\n // sort sibling hashes as a convention for efficient proof validation\\n if (_left < _right) {\\n // efficient hash using EVM scratch space\\n assembly {\\n mstore(0x00, _left)\\n mstore(0x20, _right)\\n parent := keccak256(0x00, 0x40)\\n }\\n } else {\\n assembly {\\n mstore(0x00, _right)\\n mstore(0x20, _left)\\n parent := keccak256(0x00, 0x40)\\n }\\n }\\n }\\n\\n /// @dev Sends the state root snapshot using Arbitrum's canonical bridge.\\n /// @param _epoch The epoch of the snapshot requested to send.\\n /// @param _inboxIndex The index of the inbox in the Arbitrum bridge contract.\\n /// @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\\n /// @param _excessFeeRefundAddress Address to refund any excess fee to\\n /// @param _gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\\n /// @param _maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\\n function sendSnapshot(\\n uint256 _epoch,\\n uint256 _inboxIndex,\\n uint256 _maxSubmissionCost,\\n address _excessFeeRefundAddress,\\n uint256 _gasLimit,\\n uint256 _maxFeePerGas\\n ) external virtual {\\n unchecked {\\n require(_epoch < block.timestamp / epochPeriod, \\\"Can only send past epoch snapshot.\\\");\\n }\\n\\n bytes memory data = abi.encodeCall(\\n IRouterToArb.route,\\n (\\n _epoch,\\n snapshots[_epoch],\\n _inboxIndex,\\n _maxSubmissionCost,\\n _excessFeeRefundAddress,\\n _gasLimit,\\n _maxFeePerGas\\n )\\n );\\n // Note: using maxGasPerTx here means the relaying txn on Gnosis will need to pass that (large) amount of gas, though almost all will be unused and refunded. This is preferred over hardcoding a gas limit.\\n bytes32 ticketID = amb.requireToPassMessage(routerGnosisToArb, data, amb.maxGasPerTx());\\n\\n emit SnapshotSent(_epoch, ticketID);\\n }\\n\\n // ************************************* //\\n // * Pure / Views * //\\n // ************************************* //\\n\\n /// @dev Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.\\n /// @return epoch The epoch associated with the current inbox block.timestamp\\n function epochNow() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the most recent epoch for which snapshots are finalized.\\n /// @return epoch The epoch associated with the current inbox block.timestamp\\n function epochFinalized() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod - 1;\\n }\\n\\n /// @dev Get the epoch from the inbox's point of view using timestamp.\\n /// @param _timestamp The timestamp to calculate the epoch from.\\n /// @return epoch The calculated epoch.\\n function epochAt(uint256 _timestamp) external view returns (uint256 epoch) {\\n epoch = _timestamp / epochPeriod;\\n }\\n}\\n\",\"keccak256\":\"0x0f6903fbd2d4f68f94851fa1325a6889fedb386ae9c270fefba850fbd9ce4da0\",\"license\":\"MIT\"},\"src/interfaces/inboxes/IVeaInbox.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\ninterface IVeaInbox {\\n /// @dev Sends an arbitrary message to receiving chain.\\n /// Note: Calls authenticated by receiving gateway checking the sender argument.\\n /// @param _to The cross-domain contract address which receives the calldata.\\n /// @param _fnSelection The function selector of the receiving contract.\\n /// @param _data The message calldata, abi.encode(...)\\n /// @return msgId The index of the message in the inbox, as a message Id, needed to relay the message.\\n function sendMessage(address _to, bytes4 _fnSelection, bytes memory _data) external returns (uint64 msgId);\\n\\n /// @dev Snapshots can be saved a maximum of once per epoch.\\n /// Saves snapshot of state root.\\n /// `O(log(count))` where count number of messages in the inbox.\\n function saveSnapshot() external;\\n}\\n\",\"keccak256\":\"0x053799bf55019a7f1db4cd889ce83cbe7319e832eec0234b1d4020a2aa0026f9\",\"license\":\"MIT\"},\"src/interfaces/routers/IRouterToArb.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\n/// @dev Interface of the Vea Router intended to be deployed on an intermediary chain which routes messages to Arbitrum where calldata is the primary cost.\\n/// eg. Gnosis (L1) -> Ethereum (L1) -> Arbitrum (L2), the IRouterToL2 will be deployed on Ethereum (L1) routing messages to Arbitrum (L2).\\ninterface IRouterToArb {\\n /// @dev Resolves any challenge of the optimistic claim for 'epoch' using the canonical bridge.\\n /// Note: Access restricted to canonical sending-chain bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateroot The true state root for the epoch.\\n /// @param _inboxIndex The index of the inbox in the Arbitrum bridge contract.\\n /// @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\\n /// @param _excessFeeRefundAddress Address to refund any excess fee to\\n /// @param _gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\\n /// @param _maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\\n function route(\\n uint256 _epoch,\\n bytes32 _stateroot,\\n uint256 _inboxIndex,\\n uint256 _maxSubmissionCost,\\n address _excessFeeRefundAddress,\\n uint256 _gasLimit,\\n uint256 _maxFeePerGas\\n ) external;\\n}\\n\",\"keccak256\":\"0xc265211871b748c9191df4fd6419d57abf030314ee5ef7aa89f14a863521f174\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051610c12380380610c1283398101604081905261002f91610064565b60a0929092526001600160a01b0390811660c052166080526100a7565b6001600160a01b038116811461006157600080fd5b50565b60008060006060848603121561007957600080fd5b83519250602084015161008b8161004c565b604085015190925061009c8161004c565b809150509250925092565b60805160a05160c051610b0c610106600039600081816101cc015261036f015260008181610185015281816101f5015281816102210152818161048c015281816104c201526104f201526000818160e501526103460152610b0c6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80634a439cfe116100715780634a439cfe1461015257806351920535146101655780635f85896c1461016d578063b5b7a18414610180578063d6565a2d146101a7578063eb8dedfa146101c757600080fd5b806306661abd146100ae5780631062b39a146100e0578063222ae7861461011f5780632bbb4704146101355780633ac3b6b61461014a575b600080fd5b6041546100c29067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6101077f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100d7565b6101276101ee565b6040519081526020016100d7565b6101486101433660046107ca565b61021f565b005b610127610483565b61012761016036600461081b565b6104bb565b6101486104ed565b6100c261017b36600461084a565b610611565b6101277f000000000000000000000000000000000000000000000000000000000000000081565b6101276101b536600461081b565b60006020819052908152604090205481565b6101077f000000000000000000000000000000000000000000000000000000000000000081565b600061021a7f000000000000000000000000000000000000000000000000000000000000000042610941565b905090565b7f0000000000000000000000000000000000000000000000000000000000000000428161024e5761024e61092b565b0486106102ad5760405162461bcd60e51b815260206004820152602260248201527f43616e206f6e6c792073656e6420706173742065706f636820736e617073686f6044820152613a1760f11b60648201526084015b60405180910390fd5b60008681526020819052604080822054905160248101899052604481019190915260648101879052608481018690526001600160a01b03851660a482015260c4810184905260e481018390526101040160408051601f19818403018152918152602080830180516001600160e01b031663507b5ad360e01b179052815163e5789d0360e01b815291519293506000926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263dc8601b3927f0000000000000000000000000000000000000000000000000000000000000000928792869263e5789d03926004808401938290030181865afa1580156103b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103dc9190610963565b6040518463ffffffff1660e01b81526004016103fa939291906109cc565b6020604051808303816000875af1158015610419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043d9190610963565b9050877f6fdd49f435101fc7b6ebdec7c8972932a926d18f6cb78a8891dfe950743b6b828260405161047191815260200190565b60405180910390a25050505050505050565b600060016104b17f000000000000000000000000000000000000000000000000000000000000000042610941565b61021a9190610a00565b60006104e77f000000000000000000000000000000000000000000000000000000000000000083610941565b92915050565b6000807f0000000000000000000000000000000000000000000000000000000000000000428161051f5761051f61092b565b604154919004925060009067ffffffffffffffff165b801561056e5780600116600103610562576001826040811061055957610559610a21565b0154925061056e565b6001918201911c610535565b60011c5b80156105b05760019182019181811690036105a8576105a56001836040811061059d5761059d610a21565b01548461077d565b92505b60011c610572565b505060008281526020818152604091829020839055604154825184815291820185905267ffffffffffffffff168183015290517f592424eb1d6135501bd20833f15fd127c29d08eed4f03872f6f75182126b1e489181900360600190a15050565b60415460009067ffffffffffffffff9081169081106106635760405162461bcd60e51b815260206004820152600e60248201526d24b73137bc1034b990333ab6361760911b60448201526064016102a4565b6040516000908290879061067f90889033908990602001610a37565b60408051601f198184030181529082905261069e939291602001610a6d565b60408051601f1981840301815291905280516020808301919091206000908152908120919250600184015b60018116600003610702576106ea6001836040811061059d5761059d610a21565b92506001918201911c677fffffffffffffff166106c9565b50816001826040811061071757610717610a21565b0155506041805467ffffffffffffffff19166001850167ffffffffffffffff161790556040517f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369061076a908490610abc565b60405180910390a1509095945050505050565b60008183101561079b578260005281602052604060002090506104e7565b5060009081526020919091526040902090565b80356001600160a01b03811681146107c557600080fd5b919050565b60008060008060008060c087890312156107e357600080fd5b863595506020870135945060408701359350610801606088016107ae565b92506080870135915060a087013590509295509295509295565b60006020828403121561082d57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561085f57600080fd5b610868846107ae565b925060208401356001600160e01b03198116811461088557600080fd5b9150604084013567ffffffffffffffff808211156108a257600080fd5b818601915086601f8301126108b657600080fd5b8135818111156108c8576108c8610834565b604051601f8201601f19908116603f011681019083821181831017156108f0576108f0610834565b8160405282815289602084870101111561090957600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b634e487b7160e01b600052601260045260246000fd5b60008261095e57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561097557600080fd5b5051919050565b60005b8381101561099757818101518382015260200161097f565b50506000910152565b600081518084526109b881602086016020860161097c565b601f01601f19169290920160200192915050565b6001600160a01b03841681526060602082018190526000906109f0908301856109a0565b9050826040830152949350505050565b818103818111156104e757634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b63ffffffff60e01b8416815282600482015260008251610a5e81602485016020870161097c565b91909101602401949350505050565b67ffffffffffffffff60c01b8460c01b1681526bffffffffffffffffffffffff198360601b16600882015260008251610aad81601c85016020870161097c565b91909101601c01949350505050565b602081526000610acf60208301846109a0565b939250505056fea26469706673582212208f85936a0d5ffa471af8a38c879ca78b06fcc0561f714b8395bb25bd09df413f64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80634a439cfe116100715780634a439cfe1461015257806351920535146101655780635f85896c1461016d578063b5b7a18414610180578063d6565a2d146101a7578063eb8dedfa146101c757600080fd5b806306661abd146100ae5780631062b39a146100e0578063222ae7861461011f5780632bbb4704146101355780633ac3b6b61461014a575b600080fd5b6041546100c29067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6101077f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100d7565b6101276101ee565b6040519081526020016100d7565b6101486101433660046107ca565b61021f565b005b610127610483565b61012761016036600461081b565b6104bb565b6101486104ed565b6100c261017b36600461084a565b610611565b6101277f000000000000000000000000000000000000000000000000000000000000000081565b6101276101b536600461081b565b60006020819052908152604090205481565b6101077f000000000000000000000000000000000000000000000000000000000000000081565b600061021a7f000000000000000000000000000000000000000000000000000000000000000042610941565b905090565b7f0000000000000000000000000000000000000000000000000000000000000000428161024e5761024e61092b565b0486106102ad5760405162461bcd60e51b815260206004820152602260248201527f43616e206f6e6c792073656e6420706173742065706f636820736e617073686f6044820152613a1760f11b60648201526084015b60405180910390fd5b60008681526020819052604080822054905160248101899052604481019190915260648101879052608481018690526001600160a01b03851660a482015260c4810184905260e481018390526101040160408051601f19818403018152918152602080830180516001600160e01b031663507b5ad360e01b179052815163e5789d0360e01b815291519293506000926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263dc8601b3927f0000000000000000000000000000000000000000000000000000000000000000928792869263e5789d03926004808401938290030181865afa1580156103b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103dc9190610963565b6040518463ffffffff1660e01b81526004016103fa939291906109cc565b6020604051808303816000875af1158015610419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043d9190610963565b9050877f6fdd49f435101fc7b6ebdec7c8972932a926d18f6cb78a8891dfe950743b6b828260405161047191815260200190565b60405180910390a25050505050505050565b600060016104b17f000000000000000000000000000000000000000000000000000000000000000042610941565b61021a9190610a00565b60006104e77f000000000000000000000000000000000000000000000000000000000000000083610941565b92915050565b6000807f0000000000000000000000000000000000000000000000000000000000000000428161051f5761051f61092b565b604154919004925060009067ffffffffffffffff165b801561056e5780600116600103610562576001826040811061055957610559610a21565b0154925061056e565b6001918201911c610535565b60011c5b80156105b05760019182019181811690036105a8576105a56001836040811061059d5761059d610a21565b01548461077d565b92505b60011c610572565b505060008281526020818152604091829020839055604154825184815291820185905267ffffffffffffffff168183015290517f592424eb1d6135501bd20833f15fd127c29d08eed4f03872f6f75182126b1e489181900360600190a15050565b60415460009067ffffffffffffffff9081169081106106635760405162461bcd60e51b815260206004820152600e60248201526d24b73137bc1034b990333ab6361760911b60448201526064016102a4565b6040516000908290879061067f90889033908990602001610a37565b60408051601f198184030181529082905261069e939291602001610a6d565b60408051601f1981840301815291905280516020808301919091206000908152908120919250600184015b60018116600003610702576106ea6001836040811061059d5761059d610a21565b92506001918201911c677fffffffffffffff166106c9565b50816001826040811061071757610717610a21565b0155506041805467ffffffffffffffff19166001850167ffffffffffffffff161790556040517f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369061076a908490610abc565b60405180910390a1509095945050505050565b60008183101561079b578260005281602052604060002090506104e7565b5060009081526020919091526040902090565b80356001600160a01b03811681146107c557600080fd5b919050565b60008060008060008060c087890312156107e357600080fd5b863595506020870135945060408701359350610801606088016107ae565b92506080870135915060a087013590509295509295509295565b60006020828403121561082d57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561085f57600080fd5b610868846107ae565b925060208401356001600160e01b03198116811461088557600080fd5b9150604084013567ffffffffffffffff808211156108a257600080fd5b818601915086601f8301126108b657600080fd5b8135818111156108c8576108c8610834565b604051601f8201601f19908116603f011681019083821181831017156108f0576108f0610834565b8160405282815289602084870101111561090957600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b634e487b7160e01b600052601260045260246000fd5b60008261095e57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561097557600080fd5b5051919050565b60005b8381101561099757818101518382015260200161097f565b50506000910152565b600081518084526109b881602086016020860161097c565b601f01601f19169290920160200192915050565b6001600160a01b03841681526060602082018190526000906109f0908301856109a0565b9050826040830152949350505050565b818103818111156104e757634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b63ffffffff60e01b8416815282600482015260008251610a5e81602485016020870161097c565b91909101602401949350505050565b67ffffffffffffffff60c01b8460c01b1681526bffffffffffffffffffffffff198360601b16600882015260008251610aad81601c85016020870161097c565b91909101601c01949350505050565b602081526000610acf60208301846109a0565b939250505056fea26469706673582212208f85936a0d5ffa471af8a38c879ca78b06fcc0561f714b8395bb25bd09df413f64736f6c63430008120033", - "devdoc": { - "details": "Vea Inbox From Gnosis to Arbitrum. Note: This contract is deployed on the Gnosis.", - "events": { - "MessageSent(bytes)": { - "details": "Relayers watch for these events to construct merkle proofs to execute transactions on Ethereum.", - "params": { - "_nodeData": "The data to create leaves in the merkle tree. abi.encodePacked(msgId, to, message), outbox relays to.call(message)." - } - }, - "SnapshotSaved(bytes32,uint256,uint64)": { - "params": { - "_count": "The count of messages in the merkle tree.", - "_epoch": "The epoch of the snapshot.", - "_snapshot": "The snapshot of the merkle tree state root." - } - }, - "SnapshotSent(uint256,bytes32)": { - "details": "The event is emitted when a snapshot is sent through the canonical arbitrum bridge.", - "params": { - "_epochSent": "The epoch of the snapshot.", - "_ticketId": "The ticketId of the L2->L1 message." - } - } - }, - "kind": "dev", - "methods": { - "constructor": { - "details": "Constructor. Note: epochPeriod must match the VeaOutboxGnosisToArb contract deployment on Gnosis, since it's on a different chain, we can't read it and trust the deployer to set a correct value", - "params": { - "_amb": "The address of the AMB contract on Gnosis.", - "_epochPeriod": "The duration in seconds between epochs.", - "_routerGnosisToArb": "The router on Ethereum that routes from Gnosis to Arbitrum." - } - }, - "epochAt(uint256)": { - "details": "Get the epoch from the inbox's point of view using timestamp.", - "params": { - "_timestamp": "The timestamp to calculate the epoch from." - }, - "returns": { - "epoch": "The calculated epoch." - } - }, - "epochFinalized()": { - "details": "Get the most recent epoch for which snapshots are finalized.", - "returns": { - "epoch": "The epoch associated with the current inbox block.timestamp" - } - }, - "epochNow()": { - "details": "Get the current epoch from the inbox's point of view using the Arbitrum L2 clock.", - "returns": { - "epoch": "The epoch associated with the current inbox block.timestamp" - } - }, - "saveSnapshot()": { - "details": "Saves snapshot of state root. Snapshots can be saved a maximum of once per epoch. `O(log(count))` where count number of messages in the inbox. Note: See merkle tree docs for details how inbox manages state." - }, - "sendMessage(address,bytes4,bytes)": { - "details": "Sends an arbitrary message to Gnosis. `O(log(count))` where count is the number of messages already sent. Amortized cost is constant. Note: See docs for details how inbox manages merkle tree state.", - "params": { - "_data": "The message calldata, abi.encode(param1, param2, ...)", - "_fnSelector": "The function selector of the receiving contract.", - "_to": "The address of the contract on the receiving chain which receives the calldata." - }, - "returns": { - "_0": "msgId The zero based index of the message in the inbox." - } - }, - "sendSnapshot(uint256,uint256,uint256,address,uint256,uint256)": { - "details": "Sends the state root snapshot using Arbitrum's canonical bridge.", - "params": { - "_epoch": "The epoch of the snapshot requested to send.", - "_excessFeeRefundAddress": "Address to refund any excess fee to", - "_gasLimit": "Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)", - "_inboxIndex": "The index of the inbox in the Arbitrum bridge contract.", - "_maxFeePerGas": "price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)", - "_maxSubmissionCost": "Max gas deducted from user's L2 balance to cover base submission fee" - } - } - }, - "version": 1 - }, - "userdoc": { - "events": { - "SnapshotSaved(bytes32,uint256,uint64)": { - "notice": "The bridgers can watch this event to claim the stateRoot on the veaOutbox." - } - }, - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 880, - "contract": "src/gnosisToArbitrum/VeaInboxGnosisToArb.sol:VeaInboxGnosisToArb", - "label": "snapshots", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_uint256,t_bytes32)" - }, - { - "astId": 884, - "contract": "src/gnosisToArbitrum/VeaInboxGnosisToArb.sol:VeaInboxGnosisToArb", - "label": "inbox", - "offset": 0, - "slot": "1", - "type": "t_array(t_bytes32)64_storage" - }, - { - "astId": 886, - "contract": "src/gnosisToArbitrum/VeaInboxGnosisToArb.sol:VeaInboxGnosisToArb", - "label": "count", - "offset": 0, - "slot": "65", - "type": "t_uint64" - } - ], - "types": { - "t_array(t_bytes32)64_storage": { - "base": "t_bytes32", - "encoding": "inplace", - "label": "bytes32[64]", - "numberOfBytes": "2048" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bytes32)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bytes32)", - "numberOfBytes": "32", - "value": "t_bytes32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - } - } - } -} diff --git a/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json b/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json index 60325c17..194539ba 100644 --- a/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json +++ b/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json @@ -1,5 +1,5 @@ { - "address": "0xB28943800115d0D3F938434F623715E5fE0433F2", + "address": "0xa3C6608539693C13434e4E29c9aB53Dd029178BE", "abi": [ { "inputs": [ @@ -287,7 +287,7 @@ ], "name": "challenge", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -312,7 +312,7 @@ "inputs": [ { "internalType": "uint256", - "name": "", + "name": "epoch", "type": "uint256" } ], @@ -1040,39 +1040,39 @@ "type": "function" } ], - "transactionHash": "0x1086071ffe2130f3ff71279f27ab74e7b97bfdee2abe5201ee0051233e89ceef", + "transactionHash": "0xf81ccb617c06afcdf64f3d4f2f398561a9202330e2e788c0028edd340fca4131", "receipt": { "to": null, - "from": "0x407DDEC61d69b212498B140a26da70AE1C879f5a", - "contractAddress": "0xB28943800115d0D3F938434F623715E5fE0433F2", - "transactionIndex": 1, - "gasUsed": "2348042", + "from": "0xcAf9AdE1fDDf1b31d490A4629ADA638d104e9543", + "contractAddress": "0xa3C6608539693C13434e4E29c9aB53Dd029178BE", + "transactionIndex": 0, + "gasUsed": "2260759", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x53a48f358e8f6d77b4b5a196bd742f336c338f712c27c17041e8006028514ad8", - "transactionHash": "0x1086071ffe2130f3ff71279f27ab74e7b97bfdee2abe5201ee0051233e89ceef", + "blockHash": "0xf4ab39aa5e534dd1927362cb076ff5d115494c4ff8f1d78152e045d591fb89ad", + "transactionHash": "0xf81ccb617c06afcdf64f3d4f2f398561a9202330e2e788c0028edd340fca4131", "logs": [], - "blockNumber": 5310979, - "cumulativeGasUsed": "2384074", + "blockNumber": 11809729, + "cumulativeGasUsed": "2260759", "status": 1, "byzantium": true }, "args": [ "200000000000000000", - 7200, + 3600, 10800, 1000000, "0x99Ca51a3534785ED619f46A79C7Ad65Fa8d85e7a", - "0xD75dB719B04842174cDB7b1d8C6f60957ab6A25E", + "0x22d70804d4Ef5BB206C6B39e3267DFe8a0f97d27", 86400, 1000000, - 5, + 11155111, "0x8d74e5e4DA11629537C4575cB0f33b4F0Dfa42EB" ], - "numDeployments": 11, - "solcInputHash": "18d8b299616ba6ea1bb506a660a35de5", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_deposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_epochPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minChallengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timeoutEpochs\",\"type\":\"uint256\"},{\"internalType\":\"contract IAMB\",\"name\":\"_amb\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_routerArbToGnosis\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_sequencerDelayLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxMissingBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_routerChainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IWETH\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"}],\"name\":\"Challenged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"_msgId\",\"type\":\"uint64\"}],\"name\":\"MessageRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"VerificationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Verified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newSequencerDelayLimit\",\"type\":\"uint256\"}],\"name\":\"sequencerDelayLimitUpdateReceived\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"censorshipTestStatus\",\"outputs\":[{\"internalType\":\"enum VeaOutboxArbToGnosis.CensorshipTestStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"challenge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositPlusReward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"epochAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochNow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"hashClaim\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedClaim\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_msgId\",\"type\":\"uint256\"}],\"name\":\"isMsgRelayed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isRelayed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestVerifiedEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxMissingBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minChallengePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"resolveDisputedClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerArbToGnosis\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint64\",\"name\":\"_msgId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequencerDelayLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"startVerification\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeoutEpochs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestampDelayUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newSequencerDelayLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"updateSequencerDelayLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"verifySnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawChallengeDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawChallengerEscapeHatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawClaimDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawClaimerEscapeHatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Vea Outbox From Arbitrum to Gnosis. Note: This contract is deployed on Gnosis.\",\"events\":{\"Challenged(uint256,address)\":{\"details\":\"This event indicates that `sendSnapshot(epoch)` should be called in the inbox.\",\"params\":{\"_challenger\":\"The address of the challenger.\",\"_epoch\":\"The epoch associated with the challenged claim.\"}},\"Claimed(address,uint256,bytes32)\":{\"details\":\"Watchers check this event to challenge fraud.\",\"params\":{\"_claimer\":\"The address of the claimer.\",\"_epoch\":\"The epoch associated with the claim.\",\"_stateRoot\":\"The state root of the claim.\"}},\"MessageRelayed(uint64)\":{\"details\":\"This event indicates that a message has been relayed.\",\"params\":{\"_msgId\":\"The msgId of the message that was relayed.\"}},\"VerificationStarted(uint256)\":{\"details\":\"This event indicates that the censorship test started and all challengers are ready even in the worst case scenario of a malicious sequencer.\",\"params\":{\"_epoch\":\"The epoch that started verification.\"}},\"Verified(uint256)\":{\"details\":\"This events indicates that verification has succeeded. The messages are ready to be relayed.\",\"params\":{\"_epoch\":\"The epoch that was verified.\"}},\"sequencerDelayLimitUpdateReceived(uint256)\":{\"details\":\"This event indicates the sequencer limit updated.\",\"params\":{\"_newSequencerDelayLimit\":\"The new sequencer delay limit.\"}}},\"kind\":\"dev\",\"methods\":{\"censorshipTestStatus((bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Gets the status of the censorship test for claim.\",\"params\":{\"_claim\":\"The claim to test.\"},\"returns\":{\"status\":\"True if the claim passed the censorship test.\"}},\"challenge(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Submit a challenge for the claim of the inbox state root snapshot taken at 'epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the claim to challenge.\"}},\"claim(uint256,bytes32)\":{\"details\":\"Submit a claim about the _stateRoot at _epoch and submit a deposit.\",\"params\":{\"_epoch\":\"The epoch for which the claim is made.\",\"_stateRoot\":\"The state root to claim.\"}},\"constructor\":{\"details\":\"Constructor. Note: epochPeriod must match the VeaInboxArbToGnosis contract deployment on Arbitrum, since it's on a different chain, we can't read it and trust the deployer to set a correct value\",\"params\":{\"_amb\":\"The address of the AMB contract on Gnosis.\",\"_deposit\":\"The deposit amount to submit a claim in wei.\",\"_epochPeriod\":\"The duration of each epoch.\",\"_maxMissingBlocks\":\"The maximum number of blocks that can be missing in a challenge period.\",\"_minChallengePeriod\":\"The minimum time window to challenge a claim.\",\"_routerArbToGnosis\":\"The address of the router on Ethereum that routes from Arbitrum to Gnosis.\",\"_routerChainId\":\"The chain id of the routerArbToGnosis.\",\"_sequencerDelayLimit\":\"The maximum delay in seconds that the Arbitrum sequencer can backdate transactions.\",\"_timeoutEpochs\":\"The epochs before the bridge is considered shutdown.\",\"_weth\":\"The address of the WETH contract on Gnosis.\"}},\"epochAt(uint256)\":{\"details\":\"Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\",\"returns\":{\"epoch\":\"The hash of the claim.\"}},\"epochNow()\":{\"details\":\"Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\",\"returns\":{\"epoch\":\"The hash of the claim.\"}},\"hashClaim((bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Hashes the claim.\",\"params\":{\"_claim\":\"The claim to hash.\"},\"returns\":{\"hashedClaim\":\"The hash of the claim.\"}},\"isMsgRelayed(uint256)\":{\"details\":\"Get the msg relayed status.\",\"params\":{\"_msgId\":\"The msgId to check.\"},\"returns\":{\"isRelayed\":\"True if the msg was relayed.\"}},\"resolveDisputedClaim(uint256,bytes32,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Resolves any challenge of the optimistic claim for '_epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch to verify.\",\"_stateRoot\":\"The true state root for the epoch.\"}},\"sendMessage(bytes32[],uint64,address,bytes)\":{\"details\":\"Verifies and relays the message. UNTRUSTED.\",\"params\":{\"_message\":\"The message encoded in the vea inbox as abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\",\"_msgId\":\"The zero based index of the message in the inbox.\",\"_proof\":\"The merkle proof to prove the message inclusion in the inbox state root.\",\"_to\":\"The address of the contract on Gnosis to call.\"}},\"startVerification(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Start verification for claim for 'epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the claim to challenge.\"}},\"updateSequencerDelayLimit(uint256,uint256)\":{\"details\":\"Set the sequencerDelayLimit by receiving a message from the AMB.\",\"params\":{\"_newSequencerDelayLimit\":\"The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\",\"_timestamp\":\"The timestamp of the message.\"}},\"verifySnapshot(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Resolves the optimistic claim for '_epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the optimistic claim.\"}},\"withdrawChallengeDeposit(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Sends the deposit back to the Challenger if successful. Includes a portion of the Bridger's deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the challenge deposit to withraw.\"}},\"withdrawChallengerEscapeHatch(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"When bridge is shutdown, no claim disputes can be resolved. This allows the challenger to withdraw their deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}},\"withdrawClaimDeposit(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Sends the deposit back to the Claimer if successful. Includes a portion of the Challenger's deposit if unsuccessfully challenged.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}},\"withdrawClaimerEscapeHatch(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"When bridge is shutdown, no claim disputes can be resolved. This allows the claimer to withdraw their deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"resolveDisputedClaim(uint256,bytes32,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"notice\":\"Note: Access restricted to AMB.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol\":\"VeaOutboxArbToGnosis\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"../canonical/gnosis-chain/IAMB.sol\\\";\\nimport \\\"../interfaces/outboxes/IVeaOutboxOnL1.sol\\\";\\nimport \\\"../interfaces/updaters/ISequencerDelayUpdatable.sol\\\";\\nimport \\\"../interfaces/tokens/gnosis/IWETH.sol\\\";\\n\\n/// @dev Vea Outbox From Arbitrum to Gnosis.\\n/// Note: This contract is deployed on Gnosis.\\ncontract VeaOutboxArbToGnosis is IVeaOutboxOnL1, ISequencerDelayUpdatable {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n IAMB public immutable amb; // The address of the AMB contract on Gnosis.\\n address public immutable routerArbToGnosis; // The address of the router from Arbitrum to Gnosis on ethereum.\\n\\n IWETH public immutable weth; // The address of the WETH contract on Gnosis.\\n uint256 public immutable deposit; // The deposit in wei required to submit a claim or challenge\\n uint256 public immutable burn; // The amount of wei to burn. deposit / 2\\n uint256 public immutable depositPlusReward; // 2 * deposit - burn\\n\\n uint256 internal constant SLOT_TIME = 5; // Gnosis 5 second slot time\\n\\n uint256 public immutable routerChainId; // Router chain id for authentication of messages from the AMB.\\n uint256 public immutable epochPeriod; // Epochs mark the period between potential snapshots.\\n uint256 public immutable minChallengePeriod; // Minimum time window to challenge a claim, even with a malicious sequencer.\\n\\n uint256 public immutable timeoutEpochs; // The number of epochs without forward progress before the bridge is considered shutdown.\\n uint256 public immutable maxMissingBlocks; // The maximum number of blocks that can be missing in a challenge period.\\n\\n bytes32 public stateRoot; // merkle root of the outbox state\\n uint256 public latestVerifiedEpoch; // The latest epoch that has been verified.\\n\\n mapping(uint256 => bytes32) public claimHashes; // epoch => claim\\n mapping(uint256 => bytes32) internal relayed; // msgId/256 => packed replay bitmap, preferred over a simple boolean mapping to save 15k gas per message\\n\\n uint256 public sequencerDelayLimit; // This is MaxTimeVariation.delaySeconds from the arbitrum sequencer inbox, it is the maximum seconds the sequencer can backdate L2 txns relative to the L1 clock.\\n uint256 public timestampDelayUpdated; // The timestamp of the last sequencer delay update.\\n\\n enum CensorshipTestStatus {\\n Failed,\\n Passed,\\n NotStarted,\\n InProgress\\n }\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Watchers check this event to challenge fraud.\\n /// @param _claimer The address of the claimer.\\n /// @param _epoch The epoch associated with the claim.\\n /// @param _stateRoot The state root of the claim.\\n event Claimed(address indexed _claimer, uint256 indexed _epoch, bytes32 _stateRoot);\\n\\n /// @dev This event indicates that `sendSnapshot(epoch)` should be called in the inbox.\\n /// @param _epoch The epoch associated with the challenged claim.\\n /// @param _challenger The address of the challenger.\\n event Challenged(uint256 indexed _epoch, address indexed _challenger);\\n\\n /// @dev This event indicates that a message has been relayed.\\n /// @param _msgId The msgId of the message that was relayed.\\n event MessageRelayed(uint64 _msgId);\\n\\n /// @dev This event indicates that the censorship test started and all challengers are ready even in the worst case scenario of a malicious sequencer.\\n /// @param _epoch The epoch that started verification.\\n event VerificationStarted(uint256 indexed _epoch);\\n\\n /// @dev This events indicates that verification has succeeded. The messages are ready to be relayed.\\n /// @param _epoch The epoch that was verified.\\n event Verified(uint256 _epoch);\\n\\n /// @dev This event indicates the sequencer limit updated.\\n /// @param _newSequencerDelayLimit The new sequencer delay limit.\\n event sequencerDelayLimitUpdateReceived(uint256 _newSequencerDelayLimit);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier OnlyBridgeRunning() {\\n unchecked {\\n require(block.timestamp / epochPeriod - latestVerifiedEpoch <= timeoutEpochs, \\\"Bridge Shutdown.\\\");\\n }\\n _;\\n }\\n\\n modifier OnlyBridgeShutdown() {\\n unchecked {\\n require(block.timestamp / epochPeriod - latestVerifiedEpoch > timeoutEpochs, \\\"Bridge Running.\\\");\\n }\\n _;\\n }\\n\\n /// @dev Constructor.\\n /// Note: epochPeriod must match the VeaInboxArbToGnosis contract deployment on Arbitrum, since it's on a different chain, we can't read it and trust the deployer to set a correct value\\n /// @param _deposit The deposit amount to submit a claim in wei.\\n /// @param _epochPeriod The duration of each epoch.\\n /// @param _minChallengePeriod The minimum time window to challenge a claim.\\n /// @param _timeoutEpochs The epochs before the bridge is considered shutdown.\\n /// @param _amb The address of the AMB contract on Gnosis.\\n /// @param _routerArbToGnosis The address of the router on Ethereum that routes from Arbitrum to Gnosis.\\n /// @param _sequencerDelayLimit The maximum delay in seconds that the Arbitrum sequencer can backdate transactions.\\n /// @param _maxMissingBlocks The maximum number of blocks that can be missing in a challenge period.\\n /// @param _routerChainId The chain id of the routerArbToGnosis.\\n /// @param _weth The address of the WETH contract on Gnosis.\\n constructor(\\n uint256 _deposit,\\n uint256 _epochPeriod,\\n uint256 _minChallengePeriod,\\n uint256 _timeoutEpochs,\\n IAMB _amb,\\n address _routerArbToGnosis,\\n uint256 _sequencerDelayLimit,\\n uint256 _maxMissingBlocks,\\n uint256 _routerChainId,\\n IWETH _weth\\n ) {\\n deposit = _deposit;\\n // epochPeriod must match the VeaInboxArbToGnosis contract deployment epochPeriod value.\\n epochPeriod = _epochPeriod;\\n timeoutEpochs = _timeoutEpochs;\\n minChallengePeriod = _minChallengePeriod;\\n amb = _amb;\\n routerArbToGnosis = _routerArbToGnosis;\\n // This value is on another chain, so we can't read it, we trust the deployer to set a correct value.\\n sequencerDelayLimit = _sequencerDelayLimit; // MaxTimeVariation.delaySeconds from the arbitrum sequencer inbox\\n maxMissingBlocks = _maxMissingBlocks;\\n routerChainId = _routerChainId;\\n weth = _weth;\\n\\n // claimant and challenger are not sybil resistant\\n // must burn half deposit to prevent zero cost griefing\\n burn = _deposit / 2;\\n depositPlusReward = 2 * _deposit - burn;\\n\\n latestVerifiedEpoch = block.timestamp / epochPeriod - 1;\\n }\\n\\n // ************************************* //\\n // * Parameter Updates * //\\n // ************************************* //\\n\\n /// @dev Set the sequencerDelayLimit by receiving a message from the AMB.\\n /// @param _newSequencerDelayLimit The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\\n /// @param _timestamp The timestamp of the message.\\n function updateSequencerDelayLimit(uint256 _newSequencerDelayLimit, uint256 _timestamp) external {\\n require(msg.sender == address(amb), \\\"Not from bridge.\\\");\\n require(bytes32(routerChainId) == amb.messageSourceChainId(), \\\"Invalid chain id.\\\");\\n require(routerArbToGnosis == amb.messageSender(), \\\"Not from router.\\\");\\n require(timestampDelayUpdated < _timestamp, \\\"Message is outdated.\\\");\\n\\n if (sequencerDelayLimit != _newSequencerDelayLimit) {\\n // If _newSequencerDelayLimit > timeout * epochPeriod, then the bridge will shutdown.\\n sequencerDelayLimit = _newSequencerDelayLimit;\\n timestampDelayUpdated = _timestamp;\\n emit sequencerDelayLimitUpdateReceived(_newSequencerDelayLimit);\\n }\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Submit a claim about the _stateRoot at _epoch and submit a deposit.\\n /// @param _epoch The epoch for which the claim is made.\\n /// @param _stateRoot The state root to claim.\\n function claim(uint256 _epoch, bytes32 _stateRoot) external virtual {\\n require(weth.transferFrom(msg.sender, address(this), deposit), \\\"Failed WETH transfer.\\\");\\n unchecked {\\n require(_epoch == block.timestamp / epochPeriod - 1, \\\"Epoch has not yet passed.\\\");\\n }\\n\\n require(_stateRoot != bytes32(0), \\\"Invalid claim.\\\");\\n require(claimHashes[_epoch] == bytes32(0), \\\"Claim already made.\\\");\\n\\n claimHashes[_epoch] = hashClaim(\\n Claim({\\n stateRoot: _stateRoot,\\n claimer: msg.sender,\\n timestampClaimed: uint32(block.timestamp),\\n timestampVerification: uint32(0),\\n blocknumberVerification: uint32(0),\\n honest: Party.None,\\n challenger: address(0)\\n })\\n );\\n\\n emit Claimed(msg.sender, _epoch, _stateRoot);\\n }\\n\\n /// @dev Submit a challenge for the claim of the inbox state root snapshot taken at 'epoch'.\\n /// @param _epoch The epoch of the claim to challenge.\\n /// @param _claim The claim associated with the epoch.\\n function challenge(uint256 _epoch, Claim memory _claim) external payable {\\n require(weth.transferFrom(msg.sender, address(this), deposit), \\\"Failed WETH transfer.\\\");\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.challenger == address(0), \\\"Claim already challenged.\\\");\\n require(_claim.honest == Party.None, \\\"Claim already verified.\\\");\\n\\n _claim.challenger = msg.sender;\\n claimHashes[_epoch] = hashClaim(_claim);\\n\\n emit Challenged(_epoch, msg.sender);\\n }\\n\\n /// @dev Start verification for claim for 'epoch'.\\n /// @param _epoch The epoch of the claim to challenge.\\n /// @param _claim The claim associated with the epoch.\\n function startVerification(uint256 _epoch, Claim memory _claim) external virtual {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n\\n // sequencerDelayLimit + epochPeriod is the worst case time to sync the L2 state compared to L1 clock.\\n // using checked arithmetic incase arbitrum governance sets sequencerDelayLimit to a large value\\n require(\\n block.timestamp - uint256(_claim.timestampClaimed) >= sequencerDelayLimit + epochPeriod,\\n \\\"Claim must wait atleast maxL2StateSyncDelay.\\\"\\n );\\n\\n CensorshipTestStatus _censorshipTestStatus = censorshipTestStatus(_claim);\\n require(\\n _censorshipTestStatus == CensorshipTestStatus.NotStarted ||\\n _censorshipTestStatus == CensorshipTestStatus.Failed,\\n \\\"Claim verification in progress or already completed.\\\"\\n );\\n\\n _claim.timestampVerification = uint32(block.timestamp);\\n _claim.blocknumberVerification = uint32(block.number);\\n\\n claimHashes[_epoch] = hashClaim(_claim);\\n\\n emit VerificationStarted(_epoch);\\n }\\n\\n /// @dev Resolves the optimistic claim for '_epoch'.\\n /// @param _epoch The epoch of the optimistic claim.\\n /// @param _claim The claim associated with the epoch.\\n function verifySnapshot(uint256 _epoch, Claim memory _claim) external virtual OnlyBridgeRunning {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.challenger == address(0), \\\"Claim is challenged.\\\");\\n require(censorshipTestStatus(_claim) == CensorshipTestStatus.Passed, \\\"Censorship test not passed.\\\");\\n\\n if (_epoch > latestVerifiedEpoch) {\\n latestVerifiedEpoch = _epoch;\\n stateRoot = _claim.stateRoot;\\n emit Verified(_epoch);\\n }\\n\\n _claim.honest = Party.Claimer;\\n claimHashes[_epoch] = hashClaim(_claim);\\n }\\n\\n /// Note: Access restricted to AMB.\\n /// @dev Resolves any challenge of the optimistic claim for '_epoch'.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function resolveDisputedClaim(\\n uint256 _epoch,\\n bytes32 _stateRoot,\\n Claim memory _claim\\n ) external virtual OnlyBridgeRunning {\\n // Ethereum -> Gnosis message authentication with the AMB, the canonical Ethereum <-> Gnosis bridge.\\n // https://docs.tokenbridge.net/amb-bridge/development-of-a-cross-chain-application/how-to-develop-xchain-apps-by-amb#receive-a-method-call-from-the-amb-bridge\\n\\n require(msg.sender == address(amb), \\\"Not from native Gnosis AMB bridge.\\\");\\n require(bytes32(routerChainId) == amb.messageSourceChainId(), \\\"Invalid chain id.\\\");\\n require(routerArbToGnosis == amb.messageSender(), \\\"Not from router.\\\");\\n\\n if (_epoch > latestVerifiedEpoch && _stateRoot != bytes32(0)) {\\n latestVerifiedEpoch = _epoch;\\n stateRoot = _stateRoot;\\n emit Verified(_epoch);\\n }\\n\\n if (claimHashes[_epoch] == hashClaim(_claim)) {\\n if (_claim.stateRoot == _stateRoot) {\\n _claim.honest = Party.Claimer;\\n } else if (_claim.challenger != address(0)) {\\n _claim.honest = Party.Challenger;\\n }\\n claimHashes[_epoch] = hashClaim(_claim);\\n }\\n }\\n\\n /// @dev Verifies and relays the message. UNTRUSTED.\\n /// @param _proof The merkle proof to prove the message inclusion in the inbox state root.\\n /// @param _msgId The zero based index of the message in the inbox.\\n /// @param _to The address of the contract on Gnosis to call.\\n /// @param _message The message encoded in the vea inbox as abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\\n function sendMessage(bytes32[] calldata _proof, uint64 _msgId, address _to, bytes calldata _message) external {\\n require(_proof.length < 64, \\\"Proof too long.\\\");\\n\\n bytes32 nodeHash = keccak256(abi.encodePacked(_msgId, _to, _message));\\n\\n // double hashed leaf\\n // avoids second order preimage attacks\\n // https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/\\n assembly {\\n mstore(0x00, nodeHash)\\n nodeHash := keccak256(0x00, 0x20)\\n }\\n\\n unchecked {\\n for (uint256 i = 0; i < _proof.length; i++) {\\n bytes32 proofElement = _proof[i];\\n // sort sibling hashes as a convention for efficient proof validation\\n if (proofElement > nodeHash)\\n assembly {\\n mstore(0x00, nodeHash)\\n mstore(0x20, proofElement)\\n nodeHash := keccak256(0x00, 0x40)\\n }\\n else\\n assembly {\\n mstore(0x00, proofElement)\\n mstore(0x20, nodeHash)\\n nodeHash := keccak256(0x00, 0x40)\\n }\\n }\\n }\\n\\n require(stateRoot == nodeHash, \\\"Invalid proof.\\\");\\n\\n // msgId is the zero-based index of the message in the inbox.\\n // msgId is also used as an index in the relayed bitmap to prevent replay.\\n // Note: a bitmap is used instead of a simple boolean mapping to save 15k gas per message.\\n\\n uint256 relayIndex = _msgId >> 8;\\n uint256 offset;\\n\\n unchecked {\\n offset = _msgId % 256;\\n }\\n\\n bytes32 replay = relayed[relayIndex];\\n\\n require(((replay >> offset) & bytes32(uint256(1))) == bytes32(0), \\\"Message already relayed\\\");\\n relayed[relayIndex] = replay | bytes32(1 << offset);\\n\\n // UNTRUSTED.\\n (bool success, ) = _to.call(_message);\\n require(success, \\\"Failed to call contract\\\");\\n\\n emit MessageRelayed(_msgId);\\n }\\n\\n /// @dev Sends the deposit back to the Claimer if successful. Includes a portion of the Challenger's deposit if unsuccessfully challenged.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawClaimDeposit(uint256 _epoch, Claim calldata _claim) external virtual {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.Claimer, \\\"Claim failed.\\\");\\n\\n delete claimHashes[_epoch];\\n\\n if (_claim.challenger != address(0)) {\\n weth.burn(burn); // no return value to check\\n require(weth.transfer(_claim.claimer, depositPlusReward), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n require(weth.transfer(_claim.claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n\\n /// @dev Sends the deposit back to the Challenger if successful. Includes a portion of the Bridger's deposit.\\n /// @param _epoch The epoch associated with the challenge deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawChallengeDeposit(uint256 _epoch, Claim calldata _claim) external {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.Challenger, \\\"Challenge failed.\\\");\\n\\n delete claimHashes[_epoch];\\n\\n weth.burn(burn); // no return value to check\\n require(weth.transfer(_claim.challenger, depositPlusReward), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n\\n /// @dev When bridge is shutdown, no claim disputes can be resolved. This allows the claimer to withdraw their deposit.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawClaimerEscapeHatch(uint256 _epoch, Claim memory _claim) external OnlyBridgeShutdown {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.None, \\\"Claim resolved.\\\");\\n\\n if (_claim.claimer != address(0)) {\\n if (_claim.challenger == address(0)) {\\n delete claimHashes[_epoch];\\n require(weth.transfer(_claim.claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n address claimer = _claim.claimer;\\n _claim.claimer = address(0);\\n claimHashes[_epoch] == hashClaim(_claim);\\n require(weth.transfer(claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n }\\n\\n /// @dev When bridge is shutdown, no claim disputes can be resolved. This allows the challenger to withdraw their deposit.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawChallengerEscapeHatch(uint256 _epoch, Claim memory _claim) external OnlyBridgeShutdown {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.None, \\\"Claim resolved.\\\");\\n\\n if (_claim.challenger != address(0)) {\\n if (_claim.claimer == address(0)) {\\n delete claimHashes[_epoch];\\n require(weth.transfer(_claim.challenger, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n address challenger = _claim.challenger;\\n _claim.challenger = address(0);\\n claimHashes[_epoch] == hashClaim(_claim);\\n require(weth.transfer(challenger, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n }\\n\\n // ************************************* //\\n // * Pure / Views * //\\n // ************************************* //\\n\\n /// @dev Hashes the claim.\\n /// @param _claim The claim to hash.\\n /// @return hashedClaim The hash of the claim.\\n function hashClaim(Claim memory _claim) public pure returns (bytes32 hashedClaim) {\\n return\\n hashedClaim = keccak256(\\n abi.encodePacked(\\n _claim.stateRoot,\\n _claim.claimer,\\n _claim.timestampClaimed,\\n _claim.timestampVerification,\\n _claim.blocknumberVerification,\\n _claim.honest,\\n _claim.challenger\\n )\\n );\\n }\\n\\n /// @dev Gets the status of the censorship test for claim.\\n /// @param _claim The claim to test.\\n /// @return status True if the claim passed the censorship test.\\n function censorshipTestStatus(Claim memory _claim) public view returns (CensorshipTestStatus status) {\\n unchecked {\\n if (uint256(_claim.timestampVerification) == 0) {\\n status = CensorshipTestStatus.NotStarted;\\n } else if (block.timestamp - uint256(_claim.timestampVerification) < minChallengePeriod) {\\n status = CensorshipTestStatus.InProgress;\\n } else {\\n uint256 expectedBlocks = uint256(_claim.blocknumberVerification) +\\n (block.timestamp - uint256(_claim.timestampVerification)) /\\n SLOT_TIME;\\n uint256 actualBlocks = block.number;\\n if (expectedBlocks - actualBlocks <= maxMissingBlocks) {\\n status = CensorshipTestStatus.Passed;\\n } else {\\n status = CensorshipTestStatus.Failed;\\n }\\n }\\n }\\n }\\n\\n /// @dev Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\\n /// @return epoch The hash of the claim.\\n function epochNow() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\\n /// @return epoch The hash of the claim.\\n function epochAt(uint256 timestamp) external view returns (uint256 epoch) {\\n epoch = timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the msg relayed status.\\n /// @param _msgId The msgId to check.\\n /// @return isRelayed True if the msg was relayed.\\n function isMsgRelayed(uint256 _msgId) external view returns (bool isRelayed) {\\n uint256 relayIndex = _msgId >> 8;\\n uint256 offset;\\n\\n unchecked {\\n offset = _msgId % 256;\\n }\\n\\n bytes32 replay = relayed[relayIndex];\\n\\n isRelayed = (replay >> offset) & bytes32(uint256(1)) == bytes32(uint256(1));\\n }\\n}\\n\",\"keccak256\":\"0x8a5031b4acc020c109c8bca88e621aa8b7a480c8c1d6b00f28fd9574ce42be9e\",\"license\":\"MIT\"},\"src/canonical/gnosis-chain/IAMB.sol\":{\"content\":\"// https://docs.gnosischain.com/bridges/tokenbridge/amb-bridge#gnosis\\n// https://github.com/omni/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/interfaces/IAMB.sol\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.18;\\n\\ninterface IAMB {\\n function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);\\n\\n function maxGasPerTx() external view returns (uint256);\\n\\n function messageSender() external view returns (address);\\n\\n function messageSourceChainId() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x529d45e46ca0c046c32b296b35ae8073c4a999ef37510545ec44d26e78deca0d\"},\"src/interfaces/outboxes/IVeaOutboxOnL1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"../types/VeaClaim.sol\\\";\\n\\n/// @dev Interface of the Vea Outbox on L1 chains like Ethereum, Gnosis, Polygon POS where storage is expensive.\\ninterface IVeaOutboxOnL1 {\\n /// @dev Verifies and relays the message.\\n /// Note: Gateways expect first argument of message call to be the arbitrum message sender, used for authentication.\\n /// @param _proof The merkle proof to prove the message.\\n /// @param _msgId The zero based index of the message in the inbox.\\n /// @param _to The address to send the message to.\\n /// @param _message The message to relay.\\n function sendMessage(bytes32[] calldata _proof, uint64 _msgId, address _to, bytes calldata _message) external;\\n\\n /// @dev Resolves any challenge of the optimistic claim for 'epoch' using the canonical bridge.\\n /// Note: Access restricted to canonical bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function resolveDisputedClaim(uint256 _epoch, bytes32 _stateRoot, Claim memory _claim) external;\\n}\\n\",\"keccak256\":\"0x52f714405dbb6f5953f7e59bf7139742837c2f055fc090971421d931a5289b51\",\"license\":\"MIT\"},\"src/interfaces/tokens/gnosis/IWETH.sol\":{\"content\":\"// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/5daaf60d11ee2075260d0f3adfb22b1c536db983/contracts/token/ERC20/BurnableToken.sol\\n// implementation: https://gnosisscan.io/address/0xf8d1677c8a0c961938bf2f9adc3f3cfda759a9d9#code\\n// proxy: https://gnosisscan.io/token/0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1#readProxyContract\\n\\n/**\\n * @title Burnable Token\\n * @dev Token that can be irreversibly burned (destroyed).\\n */\\ninterface IWETH {\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n event Burn(address indexed burner, uint256 value);\\n\\n /**\\n * @dev Burns a specific amount of tokens.\\n * @param _value The amount of token to be burned.\\n */\\n function burn(uint256 _value) external;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Transfer tokens from one address to another\\n * @param _from address The address which you want to send tokens from\\n * @param _to address The address which you want to transfer to\\n * @param _value uint256 the amount of tokens to be transferred\\n */\\n function transferFrom(address _from, address _to, uint256 _value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xd7cb8c8585a387464c451c2ff81ad3f9f02e291fe0dad802ff84646ff18d1eb2\"},\"src/interfaces/types/VeaClaim.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\nenum Party {\\n None,\\n Claimer,\\n Challenger\\n}\\n\\nstruct Claim {\\n bytes32 stateRoot;\\n address claimer;\\n uint32 timestampClaimed;\\n uint32 timestampVerification;\\n uint32 blocknumberVerification;\\n Party honest;\\n address challenger;\\n}\\n\",\"keccak256\":\"0x1b25222d0ebdb4beed6cd844ea1f262c89e4c002e7520972e6b79083eeed6418\",\"license\":\"MIT\"},\"src/interfaces/updaters/ISequencerDelayUpdatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.18;\\n\\n/// @dev Interface of a contract which is updatable, receiving parameter updates from an L1 contract through a cross-chain call.\\n/// @dev eg. Arbitrum (L2) -> Ethereum (L1) -> Gnosis (L1), the veaOutbox on Gnosis will be an ISequencerDelayUpdatable contract which receives updates from the router on Ethereum.\\ninterface ISequencerDelayUpdatable {\\n /// @dev Updates the sequencer limit.\\n /// Note: Access restricted to ensure the argument is passed from the Sequencer contract.\\n /// @param _newSequencerDelayLimit The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\\n /// @param _timestamp The timestamp of the message.\\n function updateSequencerDelayLimit(uint256 _newSequencerDelayLimit, uint256 _timestamp) external;\\n}\\n\",\"keccak256\":\"0xa99728056c1360f321ddac49c565ed0d4f2094569aaca3a2523df9f833e83925\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6101e06040523480156200001257600080fd5b5060405162002c6f38038062002c6f8339810160408190526200003591620000f2565b60e08a90526101608990526101a08790526101808890526001600160a01b0380871660805285811660a05260048590556101c0849052610140839052811660c0526200008360028b620001a3565b610100819052620000968b6002620001c6565b620000a29190620001e6565b6101205261016051600190620000b99042620001a3565b620000c59190620001e6565b60015550620001fc98505050505050505050565b6001600160a01b0381168114620000ef57600080fd5b50565b6000806000806000806000806000806101408b8d0312156200011357600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b01516200013c81620000d9565b60a08c01519096506200014f81620000d9565b8095505060c08b0151935060e08b015192506101008b015191506101208b01516200017a81620000d9565b809150509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b600082620001c157634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417620001e057620001e06200018d565b92915050565b81810381811115620001e057620001e06200018d565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516128bf620003b06000396000818161054f01526122bc0152600081816105830152818161091a01528181611b9b01528181611d8f015261204e01526000818161060b01526122500152600081816105b70152818161093e01528181610ccf015281816110a60152818161196e01528181611b1c01528181611bbf01528181611db301526120720152600081816104e501528181610ab50152610de80152600081816104b101526116780152600081816103e70152818161158701526117db01526000818161063f0152818161071301528181610feb0152818161190b01528181611f0801528181611f9d01526121c70152600081816103660152818161073901528181611011015281816115ad01528181611619015281816118010152818161186d015281816118b001528181611f2e01528181611fc301526121ed01526000818161067301528181610ba20152610ed501526000818161022f015281816109b901528181610a3301528181610b1701528181610d0401528181610d660152610e4a01526128bf6000f3fe6080604052600436106101e35760003560e01c8063541adcca11610102578063b5b7a18411610095578063d5e6a9df11610064578063d5e6a9df14610661578063da2b7bc414610695578063df19e6ff146106b5578063e813a755146106e257600080fd5b8063b5b7a184146105a5578063b633b944146105d9578063c2114a16146105f9578063d0e30db01461062d57600080fd5b8063930f28af116100d1578063930f28af146105075780639588eca214610527578063aa22a1c61461053d578063b044397e1461057157600080fd5b8063541adcca146104695780637ffc2a6e14610489578063836e344b1461049f5780638d96fdea146104d357600080fd5b806331ddf7431161017a57806344df8e701161014957806344df8e70146103d55780634788cb381461040957806349b4299e146104295780634a439cfe1461044957600080fd5b806331ddf743146103145780633ce43cfd146103345780633fc8cef31461035457806343b066d51461038857600080fd5b80632639c060116101b65780632639c0601461029157806327ee6bdd146102be5780632c192519146102d457806331d14457146102f457600080fd5b806301139b68146101e85780630f0adca5146101fd5780631062b39a1461021d578063222ae7861461026e575b600080fd5b6101fb6101f63660046123f9565b6106f8565b005b34801561020957600080fd5b506101fb610218366004612427565b610918565b34801561022957600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561027a57600080fd5b50610283610cc8565b604051908152602001610265565b34801561029d57600080fd5b506102836102ac36600461245e565b60026020526000908152604090205481565b3480156102ca57600080fd5b5061028360015481565b3480156102e057600080fd5b506101fb6102ef366004612477565b610cf9565b34801561030057600080fd5b506101fb61030f366004612477565b610fd0565b34801561032057600080fd5b506101fb61032f3660046124fa565b611225565b34801561034057600080fd5b506101fb61034f3660046125bc565b6114c5565b34801561036057600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b34801561039457600080fd5b506103c56103a336600461245e565b600881901c600090815260036020526040902054600160ff9092161c81161490565b6040519015158152602001610265565b3480156103e157600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b506101fb6104243660046125bc565b6116ff565b34801561043557600080fd5b506101fb6104443660046123f9565b611937565b34801561045557600080fd5b5061028361046436600461245e565b611b15565b34801561047557600080fd5b506102836104843660046125f5565b611b47565b34801561049557600080fd5b5061028360055481565b3480156104ab57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156104df57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561051357600080fd5b506101fb6105223660046123f9565b611b99565b34801561053357600080fd5b5061028360005481565b34801561054957600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561057d57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b157600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156105e557600080fd5b506101fb6105f43660046123f9565b611d8d565b34801561060557600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561063957600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561066d57600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b3480156106a157600080fd5b506101fb6106b03660046123f9565b61204c565b3480156106c157600080fd5b506106d56106d03660046125f5565b612232565b604051610265919061262e565b3480156106ee57600080fd5b5061028360045481565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af115801561078a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ae9190612648565b6107d35760405162461bcd60e51b81526004016107ca9061266a565b60405180910390fd5b6107dc81611b47565b600083815260026020526040902054146108085760405162461bcd60e51b81526004016107ca90612699565b60c08101516001600160a01b0316156108635760405162461bcd60e51b815260206004820152601960248201527f436c61696d20616c7265616479206368616c6c656e6765642e0000000000000060448201526064016107ca565b60008160a00151600281111561087b5761087b612618565b146108c85760405162461bcd60e51b815260206004820152601760248201527f436c61696d20616c72656164792076657269666965642e00000000000000000060448201526064016107ca565b3360c08201526108d781611b47565b600083815260026020526040808220929092559051339184917fcfe09ca25f55d949baba5e280f5750c9ba4b9048fca5532f916067d433afe4d79190a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f0000000000000000000000000000000000000000000000000000000000000000428161096b5761096b6126c1565b040311156109ae5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b60448201526064016107ca565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a315760405162461bcd60e51b815260206004820152602260248201527f4e6f742066726f6d206e617469766520476e6f73697320414d42206272696467604482015261329760f11b60648201526084016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab391906126d7565b7f000000000000000000000000000000000000000000000000000000000000000014610b155760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9791906126f0565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610c0a5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b60448201526064016107ca565b60015483118015610c1a57508115155b15610c5d57600183905560008290556040518381527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b610c6681611b47565b60008481526002602052604090205403610cc3578051829003610c8f57600160a0820152610caa565b60c08101516001600160a01b031615610caa57600260a08201525b610cb381611b47565b6000848152600260205260409020555b505050565b6000610cf47f000000000000000000000000000000000000000000000000000000000000000042612723565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d645760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906126d7565b7f000000000000000000000000000000000000000000000000000000000000000014610e485760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eca91906126f0565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610f3d5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b60448201526064016107ca565b8060055410610f855760405162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29034b99037baba3230ba32b21760611b60448201526064016107ca565b8160045414610fcc57600482905560058190556040518281527f684f6fb71cbcb798156dcca2a95dbd142fa1f8957637833b1897ab89e05aa7079060200160405180910390a15b5050565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015611062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110869190612648565b6110a25760405162461bcd60e51b81526004016107ca9061266a565b60017f000000000000000000000000000000000000000000000000000000000000000042816110d3576110d36126c1565b040382146111235760405162461bcd60e51b815260206004820152601960248201527f45706f636820686173206e6f7420796574207061737365642e0000000000000060448201526064016107ca565b806111405760405162461bcd60e51b81526004016107ca90612699565b600082815260026020526040902054156111925760405162461bcd60e51b815260206004820152601360248201527221b630b4b69030b63932b0b23c9036b0b2329760691b60448201526064016107ca565b6040805160e0810182528281523360208201524263ffffffff16918101919091526000606082018190526080820181905260a0820181905260c08201526111d890611b47565b6000838152600260209081526040918290209290925551828152839133917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a35050565b604085106112675760405162461bcd60e51b815260206004820152600f60248201526e283937b7b3103a37b7903637b7339760891b60448201526064016107ca565b6000848484846040516020016112809493929190612745565b604051602081830303815290604052805190602001209050806000526020600020905060005b868110156113005760008888838181106112c2576112c2612787565b905060200201359050828111156112e7578260005280602052604060002092506112f7565b8060005282602052604060002092505b506001016112a6565b5080600054146113435760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b210383937b7b31760911b60448201526064016107ca565b600885901c66ffffffffffffff1660008181526003602052604090205460ff87169080821c600116156113b85760405162461bcd60e51b815260206004820152601760248201527f4d65737361676520616c72656164792072656c6179656400000000000000000060448201526064016107ca565b6000838152600360205260408082206001851b84179055516001600160a01b038916906113e8908990899061279d565b6000604051808303816000865af19150503d8060008114611425576040519150601f19603f3d011682016040523d82523d6000602084013e61142a565b606091505b505090508061147b5760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f2063616c6c20636f6e747261637400000000000000000060448201526064016107ca565b60405167ffffffffffffffff8a1681527f54303fab361bc52c2f1f56ace7351189582264f74ce47a6e7c3f478d64c429439060200160405180910390a15050505050505050505050565b6114d7610484368390038301836125f5565b600083815260026020526040902054146115035760405162461bcd60e51b81526004016107ca90612699565b600261151560c0830160a084016127ad565b600281111561152657611526612618565b146115675760405162461bcd60e51b815260206004820152601160248201527021b430b63632b733b2903330b4b632b21760791b60448201526064016107ca565b6000828152600260205260408082209190915551630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b1580156115f957600080fd5b505af115801561160d573d6000803e3d6000fd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061165260e0840160c085016127c8565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044015b6020604051808303816000875af11580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190612648565b610fcc5760405162461bcd60e51b81526004016107ca9061266a565b611711610484368390038301836125f5565b6000838152600260205260409020541461173d5760405162461bcd60e51b81526004016107ca90612699565b600161174f60c0830160a084016127ad565b600281111561176057611760612618565b1461179d5760405162461bcd60e51b815260206004820152600d60248201526c21b630b4b6903330b4b632b21760991b60448201526064016107ca565b60008281526002602052604081208190556117be60e0830160c084016127c8565b6001600160a01b0316146118a657604051630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b15801561184d57600080fd5b505af1158015611861573d6000803e3d6000fd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061165260408401602085016127c8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb6118e560408401602085016127c8565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044016116a0565b61194081611b47565b6000838152600260205260409020541461196c5760405162461bcd60e51b81526004016107ca90612699565b7f000000000000000000000000000000000000000000000000000000000000000060045461199a91906127e5565b60408201516119af9063ffffffff16426127f8565b1015611a125760405162461bcd60e51b815260206004820152602c60248201527f436c61696d206d75737420776169742061746c65617374206d61784c3253746160448201526b3a32a9bcb731a232b630bc9760a11b60648201526084016107ca565b6000611a1d82612232565b90506002816003811115611a3357611a33612618565b1480611a5057506000816003811115611a4e57611a4e612618565b145b611ab95760405162461bcd60e51b815260206004820152603460248201527f436c61696d20766572696669636174696f6e20696e2070726f6772657373206f604482015273391030b63932b0b23c9031b7b6b83632ba32b21760611b60648201526084016107ca565b63ffffffff428116606084015243166080830152611ad682611b47565b60008481526002602052604080822092909255905184917f37b700b61b9b4710dddb0c3316b2be7ef6088ed4b1d7bfe0fb98be8f9a163e1691a2505050565b6000611b417f000000000000000000000000000000000000000000000000000000000000000083612723565b92915050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098611b7c98909796910161280b565b604051602081830303815290604052805190602001209050919050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611bec57611bec6126c1565b04031115611c2f5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b60448201526064016107ca565b611c3881611b47565b60008381526002602052604090205414611c645760405162461bcd60e51b81526004016107ca90612699565b60c08101516001600160a01b031615611cb65760405162461bcd60e51b815260206004820152601460248201527321b630b4b69034b99031b430b63632b733b2b21760611b60448201526064016107ca565b6001611cc182612232565b6003811115611cd257611cd2612618565b14611d1f5760405162461bcd60e51b815260206004820152601b60248201527f43656e736f72736869702074657374206e6f74207061737365642e000000000060448201526064016107ca565b600154821115611d6757600182905580516000556040518281527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b600160a0820152611d7781611b47565b6000928352600260205260409092209190915550565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611de057611de06126c1565b040311611e215760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b60448201526064016107ca565b611e2a81611b47565b60008381526002602052604090205414611e565760405162461bcd60e51b81526004016107ca90612699565b60008160a001516002811115611e6e57611e6e612618565b14611ead5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b60448201526064016107ca565b60c08101516001600160a01b031615610fcc5760208101516001600160a01b0316611f5f576000828152600260205260408082209190915560c0820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016116a0565b60c0810180516000909152611f7382611b47565b506000839052600260205260405163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af115801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190612648565b610cc35760405162461bcd60e51b81526004016107ca9061266a565b7f00000000000000000000000000000000000000000000000000000000000000006001547f0000000000000000000000000000000000000000000000000000000000000000428161209f5761209f6126c1565b0403116120e05760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b60448201526064016107ca565b6120e981611b47565b600083815260026020526040902054146121155760405162461bcd60e51b81526004016107ca90612699565b60008160a00151600281111561212d5761212d612618565b1461216c5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b60448201526064016107ca565b60208101516001600160a01b031615610fcc5760c08101516001600160a01b031661221e57600082815260026020908152604080832092909255820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016116a0565b6020810180516000909152611f7382611b47565b6000816060015163ffffffff1660000361224e57506002919050565b7f0000000000000000000000000000000000000000000000000000000000000000826060015163ffffffff164203101561228a57506003919050565b60006005836060015163ffffffff164203816122a8576122a86126c1565b608085015163ffffffff16919004019050437f0000000000000000000000000000000000000000000000000000000000000000818303116122ec57600192506122f1565b600092505b50505b919050565b6001600160a01b038116811461230e57600080fd5b50565b80356122f4816122f9565b803563ffffffff811681146122f457600080fd5b8035600381106122f457600080fd5b600060e0828403121561235157600080fd5b60405160e0810181811067ffffffffffffffff8211171561238257634e487b7160e01b600052604160045260246000fd5b6040528235815290508061239860208401612311565b60208201526123a96040840161231c565b60408201526123ba6060840161231c565b60608201526123cb6080840161231c565b60808201526123dc60a08401612330565b60a08201526123ed60c08401612311565b60c08201525092915050565b600080610100838503121561240d57600080fd5b8235915061241e846020850161233f565b90509250929050565b6000806000610120848603121561243d57600080fd5b8335925060208401359150612455856040860161233f565b90509250925092565b60006020828403121561247057600080fd5b5035919050565b6000806040838503121561248a57600080fd5b50508035926020909101359150565b803567ffffffffffffffff811681146122f457600080fd5b60008083601f8401126124c357600080fd5b50813567ffffffffffffffff8111156124db57600080fd5b6020830191508360208285010111156124f357600080fd5b9250929050565b6000806000806000806080878903121561251357600080fd5b863567ffffffffffffffff8082111561252b57600080fd5b818901915089601f83011261253f57600080fd5b81358181111561254e57600080fd5b8a60208260051b850101111561256357600080fd5b6020830198508097505061257960208a01612499565b955061258760408a01612311565b9450606089013591508082111561259d57600080fd5b506125aa89828a016124b1565b979a9699509497509295939492505050565b6000808284036101008112156125d157600080fd5b8335925060e0601f19820112156125e757600080fd5b506020830190509250929050565b600060e0828403121561260757600080fd5b612611838361233f565b9392505050565b634e487b7160e01b600052602160045260246000fd5b602081016004831061264257612642612618565b91905290565b60006020828403121561265a57600080fd5b8151801515811461261157600080fd5b6020808252601590820152742330b4b632b2102ba2aa24103a3930b739b332b91760591b604082015260600190565b6020808252600e908201526d24b73b30b634b21031b630b4b69760911b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000602082840312156126e957600080fd5b5051919050565b60006020828403121561270257600080fd5b8151612611816122f9565b634e487b7160e01b600052601160045260246000fd5b60008261274057634e487b7160e01b600052601260045260246000fd5b500490565b60c085901b6001600160c01b0319168152606084901b6bffffffffffffffffffffffff191660088201528183601c83013760009101601c019081529392505050565b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b6000602082840312156127bf57600080fd5b61261182612330565b6000602082840312156127da57600080fd5b8135612611816122f9565b80820180821115611b4157611b4161270d565b81810381811115611b4157611b4161270d565b87815260006bffffffffffffffffffffffff19808960601b16602084015263ffffffff60e01b808960e01b166034850152808860e01b166038850152808760e01b16603c850152506003851061286357612863612618565b60f89490941b60408301525060609190911b90911660418201526055019594505050505056fea264697066735822122022ba0f495a78693991ca05bc8ebc668367b0e3eb446f48492e25094b4b4fa39d64736f6c63430008120033", - "deployedBytecode": "0x6080604052600436106101e35760003560e01c8063541adcca11610102578063b5b7a18411610095578063d5e6a9df11610064578063d5e6a9df14610661578063da2b7bc414610695578063df19e6ff146106b5578063e813a755146106e257600080fd5b8063b5b7a184146105a5578063b633b944146105d9578063c2114a16146105f9578063d0e30db01461062d57600080fd5b8063930f28af116100d1578063930f28af146105075780639588eca214610527578063aa22a1c61461053d578063b044397e1461057157600080fd5b8063541adcca146104695780637ffc2a6e14610489578063836e344b1461049f5780638d96fdea146104d357600080fd5b806331ddf7431161017a57806344df8e701161014957806344df8e70146103d55780634788cb381461040957806349b4299e146104295780634a439cfe1461044957600080fd5b806331ddf743146103145780633ce43cfd146103345780633fc8cef31461035457806343b066d51461038857600080fd5b80632639c060116101b65780632639c0601461029157806327ee6bdd146102be5780632c192519146102d457806331d14457146102f457600080fd5b806301139b68146101e85780630f0adca5146101fd5780631062b39a1461021d578063222ae7861461026e575b600080fd5b6101fb6101f63660046123f9565b6106f8565b005b34801561020957600080fd5b506101fb610218366004612427565b610918565b34801561022957600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561027a57600080fd5b50610283610cc8565b604051908152602001610265565b34801561029d57600080fd5b506102836102ac36600461245e565b60026020526000908152604090205481565b3480156102ca57600080fd5b5061028360015481565b3480156102e057600080fd5b506101fb6102ef366004612477565b610cf9565b34801561030057600080fd5b506101fb61030f366004612477565b610fd0565b34801561032057600080fd5b506101fb61032f3660046124fa565b611225565b34801561034057600080fd5b506101fb61034f3660046125bc565b6114c5565b34801561036057600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b34801561039457600080fd5b506103c56103a336600461245e565b600881901c600090815260036020526040902054600160ff9092161c81161490565b6040519015158152602001610265565b3480156103e157600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b506101fb6104243660046125bc565b6116ff565b34801561043557600080fd5b506101fb6104443660046123f9565b611937565b34801561045557600080fd5b5061028361046436600461245e565b611b15565b34801561047557600080fd5b506102836104843660046125f5565b611b47565b34801561049557600080fd5b5061028360055481565b3480156104ab57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156104df57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561051357600080fd5b506101fb6105223660046123f9565b611b99565b34801561053357600080fd5b5061028360005481565b34801561054957600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561057d57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b157600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156105e557600080fd5b506101fb6105f43660046123f9565b611d8d565b34801561060557600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561063957600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561066d57600080fd5b506102517f000000000000000000000000000000000000000000000000000000000000000081565b3480156106a157600080fd5b506101fb6106b03660046123f9565b61204c565b3480156106c157600080fd5b506106d56106d03660046125f5565b612232565b604051610265919061262e565b3480156106ee57600080fd5b5061028360045481565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af115801561078a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ae9190612648565b6107d35760405162461bcd60e51b81526004016107ca9061266a565b60405180910390fd5b6107dc81611b47565b600083815260026020526040902054146108085760405162461bcd60e51b81526004016107ca90612699565b60c08101516001600160a01b0316156108635760405162461bcd60e51b815260206004820152601960248201527f436c61696d20616c7265616479206368616c6c656e6765642e0000000000000060448201526064016107ca565b60008160a00151600281111561087b5761087b612618565b146108c85760405162461bcd60e51b815260206004820152601760248201527f436c61696d20616c72656164792076657269666965642e00000000000000000060448201526064016107ca565b3360c08201526108d781611b47565b600083815260026020526040808220929092559051339184917fcfe09ca25f55d949baba5e280f5750c9ba4b9048fca5532f916067d433afe4d79190a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f0000000000000000000000000000000000000000000000000000000000000000428161096b5761096b6126c1565b040311156109ae5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b60448201526064016107ca565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a315760405162461bcd60e51b815260206004820152602260248201527f4e6f742066726f6d206e617469766520476e6f73697320414d42206272696467604482015261329760f11b60648201526084016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab391906126d7565b7f000000000000000000000000000000000000000000000000000000000000000014610b155760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9791906126f0565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610c0a5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b60448201526064016107ca565b60015483118015610c1a57508115155b15610c5d57600183905560008290556040518381527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b610c6681611b47565b60008481526002602052604090205403610cc3578051829003610c8f57600160a0820152610caa565b60c08101516001600160a01b031615610caa57600260a08201525b610cb381611b47565b6000848152600260205260409020555b505050565b6000610cf47f000000000000000000000000000000000000000000000000000000000000000042612723565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d645760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de691906126d7565b7f000000000000000000000000000000000000000000000000000000000000000014610e485760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b60448201526064016107ca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eca91906126f0565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610f3d5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b60448201526064016107ca565b8060055410610f855760405162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29034b99037baba3230ba32b21760611b60448201526064016107ca565b8160045414610fcc57600482905560058190556040518281527f684f6fb71cbcb798156dcca2a95dbd142fa1f8957637833b1897ab89e05aa7079060200160405180910390a15b5050565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015611062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110869190612648565b6110a25760405162461bcd60e51b81526004016107ca9061266a565b60017f000000000000000000000000000000000000000000000000000000000000000042816110d3576110d36126c1565b040382146111235760405162461bcd60e51b815260206004820152601960248201527f45706f636820686173206e6f7420796574207061737365642e0000000000000060448201526064016107ca565b806111405760405162461bcd60e51b81526004016107ca90612699565b600082815260026020526040902054156111925760405162461bcd60e51b815260206004820152601360248201527221b630b4b69030b63932b0b23c9036b0b2329760691b60448201526064016107ca565b6040805160e0810182528281523360208201524263ffffffff16918101919091526000606082018190526080820181905260a0820181905260c08201526111d890611b47565b6000838152600260209081526040918290209290925551828152839133917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a35050565b604085106112675760405162461bcd60e51b815260206004820152600f60248201526e283937b7b3103a37b7903637b7339760891b60448201526064016107ca565b6000848484846040516020016112809493929190612745565b604051602081830303815290604052805190602001209050806000526020600020905060005b868110156113005760008888838181106112c2576112c2612787565b905060200201359050828111156112e7578260005280602052604060002092506112f7565b8060005282602052604060002092505b506001016112a6565b5080600054146113435760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b210383937b7b31760911b60448201526064016107ca565b600885901c66ffffffffffffff1660008181526003602052604090205460ff87169080821c600116156113b85760405162461bcd60e51b815260206004820152601760248201527f4d65737361676520616c72656164792072656c6179656400000000000000000060448201526064016107ca565b6000838152600360205260408082206001851b84179055516001600160a01b038916906113e8908990899061279d565b6000604051808303816000865af19150503d8060008114611425576040519150601f19603f3d011682016040523d82523d6000602084013e61142a565b606091505b505090508061147b5760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f2063616c6c20636f6e747261637400000000000000000060448201526064016107ca565b60405167ffffffffffffffff8a1681527f54303fab361bc52c2f1f56ace7351189582264f74ce47a6e7c3f478d64c429439060200160405180910390a15050505050505050505050565b6114d7610484368390038301836125f5565b600083815260026020526040902054146115035760405162461bcd60e51b81526004016107ca90612699565b600261151560c0830160a084016127ad565b600281111561152657611526612618565b146115675760405162461bcd60e51b815260206004820152601160248201527021b430b63632b733b2903330b4b632b21760791b60448201526064016107ca565b6000828152600260205260408082209190915551630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b1580156115f957600080fd5b505af115801561160d573d6000803e3d6000fd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061165260e0840160c085016127c8565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044015b6020604051808303816000875af11580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e39190612648565b610fcc5760405162461bcd60e51b81526004016107ca9061266a565b611711610484368390038301836125f5565b6000838152600260205260409020541461173d5760405162461bcd60e51b81526004016107ca90612699565b600161174f60c0830160a084016127ad565b600281111561176057611760612618565b1461179d5760405162461bcd60e51b815260206004820152600d60248201526c21b630b4b6903330b4b632b21760991b60448201526064016107ca565b60008281526002602052604081208190556117be60e0830160c084016127c8565b6001600160a01b0316146118a657604051630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b15801561184d57600080fd5b505af1158015611861573d6000803e3d6000fd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061165260408401602085016127c8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb6118e560408401602085016127c8565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044016116a0565b61194081611b47565b6000838152600260205260409020541461196c5760405162461bcd60e51b81526004016107ca90612699565b7f000000000000000000000000000000000000000000000000000000000000000060045461199a91906127e5565b60408201516119af9063ffffffff16426127f8565b1015611a125760405162461bcd60e51b815260206004820152602c60248201527f436c61696d206d75737420776169742061746c65617374206d61784c3253746160448201526b3a32a9bcb731a232b630bc9760a11b60648201526084016107ca565b6000611a1d82612232565b90506002816003811115611a3357611a33612618565b1480611a5057506000816003811115611a4e57611a4e612618565b145b611ab95760405162461bcd60e51b815260206004820152603460248201527f436c61696d20766572696669636174696f6e20696e2070726f6772657373206f604482015273391030b63932b0b23c9031b7b6b83632ba32b21760611b60648201526084016107ca565b63ffffffff428116606084015243166080830152611ad682611b47565b60008481526002602052604080822092909255905184917f37b700b61b9b4710dddb0c3316b2be7ef6088ed4b1d7bfe0fb98be8f9a163e1691a2505050565b6000611b417f000000000000000000000000000000000000000000000000000000000000000083612723565b92915050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098611b7c98909796910161280b565b604051602081830303815290604052805190602001209050919050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611bec57611bec6126c1565b04031115611c2f5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b60448201526064016107ca565b611c3881611b47565b60008381526002602052604090205414611c645760405162461bcd60e51b81526004016107ca90612699565b60c08101516001600160a01b031615611cb65760405162461bcd60e51b815260206004820152601460248201527321b630b4b69034b99031b430b63632b733b2b21760611b60448201526064016107ca565b6001611cc182612232565b6003811115611cd257611cd2612618565b14611d1f5760405162461bcd60e51b815260206004820152601b60248201527f43656e736f72736869702074657374206e6f74207061737365642e000000000060448201526064016107ca565b600154821115611d6757600182905580516000556040518281527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b600160a0820152611d7781611b47565b6000928352600260205260409092209190915550565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611de057611de06126c1565b040311611e215760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b60448201526064016107ca565b611e2a81611b47565b60008381526002602052604090205414611e565760405162461bcd60e51b81526004016107ca90612699565b60008160a001516002811115611e6e57611e6e612618565b14611ead5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b60448201526064016107ca565b60c08101516001600160a01b031615610fcc5760208101516001600160a01b0316611f5f576000828152600260205260408082209190915560c0820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016116a0565b60c0810180516000909152611f7382611b47565b506000839052600260205260405163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af115801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190612648565b610cc35760405162461bcd60e51b81526004016107ca9061266a565b7f00000000000000000000000000000000000000000000000000000000000000006001547f0000000000000000000000000000000000000000000000000000000000000000428161209f5761209f6126c1565b0403116120e05760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b60448201526064016107ca565b6120e981611b47565b600083815260026020526040902054146121155760405162461bcd60e51b81526004016107ca90612699565b60008160a00151600281111561212d5761212d612618565b1461216c5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b60448201526064016107ca565b60208101516001600160a01b031615610fcc5760c08101516001600160a01b031661221e57600082815260026020908152604080832092909255820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016116a0565b6020810180516000909152611f7382611b47565b6000816060015163ffffffff1660000361224e57506002919050565b7f0000000000000000000000000000000000000000000000000000000000000000826060015163ffffffff164203101561228a57506003919050565b60006005836060015163ffffffff164203816122a8576122a86126c1565b608085015163ffffffff16919004019050437f0000000000000000000000000000000000000000000000000000000000000000818303116122ec57600192506122f1565b600092505b50505b919050565b6001600160a01b038116811461230e57600080fd5b50565b80356122f4816122f9565b803563ffffffff811681146122f457600080fd5b8035600381106122f457600080fd5b600060e0828403121561235157600080fd5b60405160e0810181811067ffffffffffffffff8211171561238257634e487b7160e01b600052604160045260246000fd5b6040528235815290508061239860208401612311565b60208201526123a96040840161231c565b60408201526123ba6060840161231c565b60608201526123cb6080840161231c565b60808201526123dc60a08401612330565b60a08201526123ed60c08401612311565b60c08201525092915050565b600080610100838503121561240d57600080fd5b8235915061241e846020850161233f565b90509250929050565b6000806000610120848603121561243d57600080fd5b8335925060208401359150612455856040860161233f565b90509250925092565b60006020828403121561247057600080fd5b5035919050565b6000806040838503121561248a57600080fd5b50508035926020909101359150565b803567ffffffffffffffff811681146122f457600080fd5b60008083601f8401126124c357600080fd5b50813567ffffffffffffffff8111156124db57600080fd5b6020830191508360208285010111156124f357600080fd5b9250929050565b6000806000806000806080878903121561251357600080fd5b863567ffffffffffffffff8082111561252b57600080fd5b818901915089601f83011261253f57600080fd5b81358181111561254e57600080fd5b8a60208260051b850101111561256357600080fd5b6020830198508097505061257960208a01612499565b955061258760408a01612311565b9450606089013591508082111561259d57600080fd5b506125aa89828a016124b1565b979a9699509497509295939492505050565b6000808284036101008112156125d157600080fd5b8335925060e0601f19820112156125e757600080fd5b506020830190509250929050565b600060e0828403121561260757600080fd5b612611838361233f565b9392505050565b634e487b7160e01b600052602160045260246000fd5b602081016004831061264257612642612618565b91905290565b60006020828403121561265a57600080fd5b8151801515811461261157600080fd5b6020808252601590820152742330b4b632b2102ba2aa24103a3930b739b332b91760591b604082015260600190565b6020808252600e908201526d24b73b30b634b21031b630b4b69760911b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000602082840312156126e957600080fd5b5051919050565b60006020828403121561270257600080fd5b8151612611816122f9565b634e487b7160e01b600052601160045260246000fd5b60008261274057634e487b7160e01b600052601260045260246000fd5b500490565b60c085901b6001600160c01b0319168152606084901b6bffffffffffffffffffffffff191660088201528183601c83013760009101601c019081529392505050565b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b6000602082840312156127bf57600080fd5b61261182612330565b6000602082840312156127da57600080fd5b8135612611816122f9565b80820180821115611b4157611b4161270d565b81810381811115611b4157611b4161270d565b87815260006bffffffffffffffffffffffff19808960601b16602084015263ffffffff60e01b808960e01b166034850152808860e01b166038850152808760e01b16603c850152506003851061286357612863612618565b60f89490941b60408301525060609190911b90911660418201526055019594505050505056fea264697066735822122022ba0f495a78693991ca05bc8ebc668367b0e3eb446f48492e25094b4b4fa39d64736f6c63430008120033", + "numDeployments": 1, + "solcInputHash": "1149cad1075bcb2114060ce12accca6a", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_deposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_epochPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minChallengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timeoutEpochs\",\"type\":\"uint256\"},{\"internalType\":\"contract IAMB\",\"name\":\"_amb\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_routerArbToGnosis\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_sequencerDelayLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxMissingBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_routerChainId\",\"type\":\"uint256\"},{\"internalType\":\"contract IWETH\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"}],\"name\":\"Challenged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"}],\"name\":\"Claimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"_msgId\",\"type\":\"uint64\"}],\"name\":\"MessageRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"VerificationStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Verified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newSequencerDelayLimit\",\"type\":\"uint256\"}],\"name\":\"sequencerDelayLimitUpdateReceived\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"censorshipTestStatus\",\"outputs\":[{\"internalType\":\"enum VeaOutboxArbToGnosis.CensorshipTestStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"challenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"name\":\"claimHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositPlusReward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"epochAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochNow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"epoch\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"epochPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"hashClaim\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedClaim\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_msgId\",\"type\":\"uint256\"}],\"name\":\"isMsgRelayed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isRelayed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestVerifiedEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxMissingBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minChallengePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_stateRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"resolveDisputedClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerArbToGnosis\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"routerChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"_proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint64\",\"name\":\"_msgId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequencerDelayLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"startVerification\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stateRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeoutEpochs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestampDelayUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newSequencerDelayLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"}],\"name\":\"updateSequencerDelayLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"verifySnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract IWETH\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawChallengeDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawChallengerEscapeHatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawClaimDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"withdrawClaimerEscapeHatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Vea Outbox From Arbitrum to Gnosis. Note: This contract is deployed on Gnosis.\",\"events\":{\"Challenged(uint256,address)\":{\"details\":\"This event indicates that `sendSnapshot(epoch)` should be called in the inbox.\",\"params\":{\"_challenger\":\"The address of the challenger.\",\"_epoch\":\"The epoch associated with the challenged claim.\"}},\"Claimed(address,uint256,bytes32)\":{\"details\":\"Watchers check this event to challenge fraud.\",\"params\":{\"_claimer\":\"The address of the claimer.\",\"_epoch\":\"The epoch associated with the claim.\",\"_stateRoot\":\"The state root of the claim.\"}},\"MessageRelayed(uint64)\":{\"details\":\"This event indicates that a message has been relayed.\",\"params\":{\"_msgId\":\"The msgId of the message that was relayed.\"}},\"VerificationStarted(uint256)\":{\"details\":\"This event indicates that the censorship test started and all challengers are ready even in the worst case scenario of a malicious sequencer.\",\"params\":{\"_epoch\":\"The epoch that started verification.\"}},\"Verified(uint256)\":{\"details\":\"This events indicates that verification has succeeded. The messages are ready to be relayed.\",\"params\":{\"_epoch\":\"The epoch that was verified.\"}},\"sequencerDelayLimitUpdateReceived(uint256)\":{\"details\":\"This event indicates the sequencer limit updated.\",\"params\":{\"_newSequencerDelayLimit\":\"The new sequencer delay limit.\"}}},\"kind\":\"dev\",\"methods\":{\"censorshipTestStatus((bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Gets the status of the censorship test for claim.\",\"params\":{\"_claim\":\"The claim to test.\"},\"returns\":{\"status\":\"True if the claim passed the censorship test.\"}},\"challenge(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Submit a challenge for the claim of the inbox state root snapshot taken at 'epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the claim to challenge.\"}},\"claim(uint256,bytes32)\":{\"details\":\"Submit a claim about the _stateRoot at _epoch and submit a deposit.\",\"params\":{\"_epoch\":\"The epoch for which the claim is made.\",\"_stateRoot\":\"The state root to claim.\"}},\"constructor\":{\"details\":\"Constructor. Note: epochPeriod must match the VeaInboxArbToGnosis contract deployment on Arbitrum, since it's on a different chain, we can't read it and trust the deployer to set a correct value\",\"params\":{\"_amb\":\"The address of the AMB contract on Gnosis.\",\"_deposit\":\"The deposit amount to submit a claim in wei.\",\"_epochPeriod\":\"The duration of each epoch.\",\"_maxMissingBlocks\":\"The maximum number of blocks that can be missing in a challenge period.\",\"_minChallengePeriod\":\"The minimum time window to challenge a claim.\",\"_routerArbToGnosis\":\"The address of the router on Ethereum that routes from Arbitrum to Gnosis.\",\"_routerChainId\":\"The chain id of the routerArbToGnosis.\",\"_sequencerDelayLimit\":\"The maximum delay in seconds that the Arbitrum sequencer can backdate transactions.\",\"_timeoutEpochs\":\"The epochs before the bridge is considered shutdown.\",\"_weth\":\"The address of the WETH contract on Gnosis.\"}},\"epochAt(uint256)\":{\"details\":\"Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\",\"returns\":{\"epoch\":\"The hash of the claim.\"}},\"epochNow()\":{\"details\":\"Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\",\"returns\":{\"epoch\":\"The hash of the claim.\"}},\"hashClaim((bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Hashes the claim.\",\"params\":{\"_claim\":\"The claim to hash.\"},\"returns\":{\"hashedClaim\":\"The hash of the claim.\"}},\"isMsgRelayed(uint256)\":{\"details\":\"Get the msg relayed status.\",\"params\":{\"_msgId\":\"The msgId to check.\"},\"returns\":{\"isRelayed\":\"True if the msg was relayed.\"}},\"resolveDisputedClaim(uint256,bytes32,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Resolves any challenge of the optimistic claim for '_epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch to verify.\",\"_stateRoot\":\"The true state root for the epoch.\"}},\"sendMessage(bytes32[],uint64,address,bytes)\":{\"details\":\"Verifies and relays the message. UNTRUSTED.\",\"params\":{\"_message\":\"The message encoded in the vea inbox as abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\",\"_msgId\":\"The zero based index of the message in the inbox.\",\"_proof\":\"The merkle proof to prove the message inclusion in the inbox state root.\",\"_to\":\"The address of the contract on Gnosis to call.\"}},\"startVerification(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Start verification for claim for 'epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the claim to challenge.\"}},\"updateSequencerDelayLimit(uint256,uint256)\":{\"details\":\"Set the sequencerDelayLimit by receiving a message from the AMB.\",\"params\":{\"_newSequencerDelayLimit\":\"The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\",\"_timestamp\":\"The timestamp of the message.\"}},\"verifySnapshot(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Resolves the optimistic claim for '_epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch of the optimistic claim.\"}},\"withdrawChallengeDeposit(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Sends the deposit back to the Challenger if successful. Includes a portion of the Bridger's deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the challenge deposit to withraw.\"}},\"withdrawChallengerEscapeHatch(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"When bridge is shutdown, no claim disputes can be resolved. This allows the challenger to withdraw their deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}},\"withdrawClaimDeposit(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Sends the deposit back to the Claimer if successful. Includes a portion of the Challenger's deposit if unsuccessfully challenged.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}},\"withdrawClaimerEscapeHatch(uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"When bridge is shutdown, no claim disputes can be resolved. This allows the claimer to withdraw their deposit.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch associated with the claim deposit to withraw.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"resolveDisputedClaim(uint256,bytes32,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"notice\":\"Note: Access restricted to AMB.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol\":\"VeaOutboxArbToGnosis\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../canonical/gnosis-chain/IAMB.sol\\\";\\nimport \\\"../interfaces/outboxes/IVeaOutboxOnL1.sol\\\";\\nimport \\\"../interfaces/updaters/ISequencerDelayUpdatable.sol\\\";\\nimport \\\"../interfaces/tokens/gnosis/IWETH.sol\\\";\\n\\n/// @dev Vea Outbox From Arbitrum to Gnosis.\\n/// Note: This contract is deployed on Gnosis.\\ncontract VeaOutboxArbToGnosis is IVeaOutboxOnL1, ISequencerDelayUpdatable {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n IAMB public immutable amb; // The address of the AMB contract on Gnosis.\\n address public immutable routerArbToGnosis; // The address of the router from Arbitrum to Gnosis on ethereum.\\n\\n IWETH public immutable weth; // The address of the WETH contract on Gnosis.\\n uint256 public immutable deposit; // The deposit in wei required to submit a claim or challenge\\n uint256 public immutable burn; // The amount of wei to burn. deposit / 2\\n uint256 public immutable depositPlusReward; // 2 * deposit - burn\\n\\n uint256 internal constant SLOT_TIME = 5; // Gnosis 5 second slot time\\n\\n uint256 public immutable routerChainId; // Router chain id for authentication of messages from the AMB.\\n uint256 public immutable epochPeriod; // Epochs mark the period between potential snapshots.\\n uint256 public immutable minChallengePeriod; // Minimum time window to challenge a claim, even with a malicious sequencer.\\n\\n uint256 public immutable timeoutEpochs; // The number of epochs without forward progress before the bridge is considered shutdown.\\n uint256 public immutable maxMissingBlocks; // The maximum number of blocks that can be missing in a challenge period.\\n\\n bytes32 public stateRoot; // merkle root of the outbox state\\n uint256 public latestVerifiedEpoch; // The latest epoch that has been verified.\\n\\n mapping(uint256 epoch => bytes32) public claimHashes; // epoch => claim\\n mapping(uint256 messageId => bytes32) internal relayed; // msgId/256 => packed replay bitmap, preferred over a simple boolean mapping to save 15k gas per message\\n\\n uint256 public sequencerDelayLimit; // This is MaxTimeVariation.delaySeconds from the arbitrum sequencer inbox, it is the maximum seconds the sequencer can backdate L2 txns relative to the L1 clock.\\n uint256 public timestampDelayUpdated; // The timestamp of the last sequencer delay update.\\n\\n enum CensorshipTestStatus {\\n Failed,\\n Passed,\\n NotStarted,\\n InProgress\\n }\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Watchers check this event to challenge fraud.\\n /// @param _claimer The address of the claimer.\\n /// @param _epoch The epoch associated with the claim.\\n /// @param _stateRoot The state root of the claim.\\n event Claimed(address indexed _claimer, uint256 indexed _epoch, bytes32 _stateRoot);\\n\\n /// @dev This event indicates that `sendSnapshot(epoch)` should be called in the inbox.\\n /// @param _epoch The epoch associated with the challenged claim.\\n /// @param _challenger The address of the challenger.\\n event Challenged(uint256 indexed _epoch, address indexed _challenger);\\n\\n /// @dev This event indicates that a message has been relayed.\\n /// @param _msgId The msgId of the message that was relayed.\\n event MessageRelayed(uint64 _msgId);\\n\\n /// @dev This event indicates that the censorship test started and all challengers are ready even in the worst case scenario of a malicious sequencer.\\n /// @param _epoch The epoch that started verification.\\n event VerificationStarted(uint256 indexed _epoch);\\n\\n /// @dev This events indicates that verification has succeeded. The messages are ready to be relayed.\\n /// @param _epoch The epoch that was verified.\\n event Verified(uint256 _epoch);\\n\\n /// @dev This event indicates the sequencer limit updated.\\n /// @param _newSequencerDelayLimit The new sequencer delay limit.\\n event sequencerDelayLimitUpdateReceived(uint256 _newSequencerDelayLimit);\\n\\n // ************************************* //\\n // * Function Modifiers * //\\n // ************************************* //\\n\\n modifier OnlyBridgeRunning() {\\n unchecked {\\n require(block.timestamp / epochPeriod - latestVerifiedEpoch <= timeoutEpochs, \\\"Bridge Shutdown.\\\");\\n }\\n _;\\n }\\n\\n modifier OnlyBridgeShutdown() {\\n unchecked {\\n require(block.timestamp / epochPeriod - latestVerifiedEpoch > timeoutEpochs, \\\"Bridge Running.\\\");\\n }\\n _;\\n }\\n\\n /// @dev Constructor.\\n /// Note: epochPeriod must match the VeaInboxArbToGnosis contract deployment on Arbitrum, since it's on a different chain, we can't read it and trust the deployer to set a correct value\\n /// @param _deposit The deposit amount to submit a claim in wei.\\n /// @param _epochPeriod The duration of each epoch.\\n /// @param _minChallengePeriod The minimum time window to challenge a claim.\\n /// @param _timeoutEpochs The epochs before the bridge is considered shutdown.\\n /// @param _amb The address of the AMB contract on Gnosis.\\n /// @param _routerArbToGnosis The address of the router on Ethereum that routes from Arbitrum to Gnosis.\\n /// @param _sequencerDelayLimit The maximum delay in seconds that the Arbitrum sequencer can backdate transactions.\\n /// @param _maxMissingBlocks The maximum number of blocks that can be missing in a challenge period.\\n /// @param _routerChainId The chain id of the routerArbToGnosis.\\n /// @param _weth The address of the WETH contract on Gnosis.\\n constructor(\\n uint256 _deposit,\\n uint256 _epochPeriod,\\n uint256 _minChallengePeriod,\\n uint256 _timeoutEpochs,\\n IAMB _amb,\\n address _routerArbToGnosis,\\n uint256 _sequencerDelayLimit,\\n uint256 _maxMissingBlocks,\\n uint256 _routerChainId,\\n IWETH _weth\\n ) {\\n deposit = _deposit;\\n // epochPeriod must match the VeaInboxArbToGnosis contract deployment epochPeriod value.\\n epochPeriod = _epochPeriod;\\n timeoutEpochs = _timeoutEpochs;\\n minChallengePeriod = _minChallengePeriod;\\n amb = _amb;\\n routerArbToGnosis = _routerArbToGnosis;\\n // This value is on another chain, so we can't read it, we trust the deployer to set a correct value.\\n sequencerDelayLimit = _sequencerDelayLimit; // MaxTimeVariation.delaySeconds from the arbitrum sequencer inbox\\n maxMissingBlocks = _maxMissingBlocks;\\n routerChainId = _routerChainId;\\n weth = _weth;\\n\\n // claimant and challenger are not sybil resistant\\n // must burn half deposit to prevent zero cost griefing\\n burn = _deposit / 2;\\n depositPlusReward = 2 * _deposit - burn;\\n\\n latestVerifiedEpoch = block.timestamp / epochPeriod - 1;\\n }\\n\\n // ************************************* //\\n // * Parameter Updates * //\\n // ************************************* //\\n\\n /// @dev Set the sequencerDelayLimit by receiving a message from the AMB.\\n /// @param _newSequencerDelayLimit The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\\n /// @param _timestamp The timestamp of the message.\\n function updateSequencerDelayLimit(uint256 _newSequencerDelayLimit, uint256 _timestamp) external {\\n require(msg.sender == address(amb), \\\"Not from bridge.\\\");\\n require(bytes32(routerChainId) == amb.messageSourceChainId(), \\\"Invalid chain id.\\\");\\n require(routerArbToGnosis == amb.messageSender(), \\\"Not from router.\\\");\\n require(timestampDelayUpdated < _timestamp, \\\"Message is outdated.\\\");\\n\\n if (sequencerDelayLimit != _newSequencerDelayLimit) {\\n // If _newSequencerDelayLimit > timeout * epochPeriod, then the bridge will shutdown.\\n sequencerDelayLimit = _newSequencerDelayLimit;\\n timestampDelayUpdated = _timestamp;\\n emit sequencerDelayLimitUpdateReceived(_newSequencerDelayLimit);\\n }\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Submit a claim about the _stateRoot at _epoch and submit a deposit.\\n /// @param _epoch The epoch for which the claim is made.\\n /// @param _stateRoot The state root to claim.\\n function claim(uint256 _epoch, bytes32 _stateRoot) external virtual {\\n require(weth.transferFrom(msg.sender, address(this), deposit), \\\"Failed WETH transfer.\\\");\\n unchecked {\\n require(_epoch == block.timestamp / epochPeriod - 1, \\\"Epoch has not yet passed.\\\");\\n }\\n\\n require(_stateRoot != bytes32(0), \\\"Invalid claim.\\\");\\n require(claimHashes[_epoch] == bytes32(0), \\\"Claim already made.\\\");\\n\\n claimHashes[_epoch] = hashClaim(\\n Claim({\\n stateRoot: _stateRoot,\\n claimer: msg.sender,\\n timestampClaimed: uint32(block.timestamp),\\n timestampVerification: uint32(0),\\n blocknumberVerification: uint32(0),\\n honest: Party.None,\\n challenger: address(0)\\n })\\n );\\n\\n emit Claimed(msg.sender, _epoch, _stateRoot);\\n }\\n\\n /// @dev Submit a challenge for the claim of the inbox state root snapshot taken at 'epoch'.\\n /// @param _epoch The epoch of the claim to challenge.\\n /// @param _claim The claim associated with the epoch.\\n function challenge(uint256 _epoch, Claim memory _claim) external {\\n require(weth.transferFrom(msg.sender, address(this), deposit), \\\"Failed WETH transfer.\\\");\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.challenger == address(0), \\\"Claim already challenged.\\\");\\n require(_claim.honest == Party.None, \\\"Claim already verified.\\\");\\n\\n _claim.challenger = msg.sender;\\n claimHashes[_epoch] = hashClaim(_claim);\\n\\n emit Challenged(_epoch, msg.sender);\\n }\\n\\n /// @dev Start verification for claim for 'epoch'.\\n /// @param _epoch The epoch of the claim to challenge.\\n /// @param _claim The claim associated with the epoch.\\n function startVerification(uint256 _epoch, Claim memory _claim) external virtual {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n\\n // sequencerDelayLimit + epochPeriod is the worst case time to sync the L2 state compared to L1 clock.\\n // using checked arithmetic incase arbitrum governance sets sequencerDelayLimit to a large value\\n require(\\n block.timestamp - uint256(_claim.timestampClaimed) >= sequencerDelayLimit + epochPeriod,\\n \\\"Claim must wait atleast maxL2StateSyncDelay.\\\"\\n );\\n\\n CensorshipTestStatus _censorshipTestStatus = censorshipTestStatus(_claim);\\n require(\\n _censorshipTestStatus == CensorshipTestStatus.NotStarted ||\\n _censorshipTestStatus == CensorshipTestStatus.Failed,\\n \\\"Claim verification in progress or already completed.\\\"\\n );\\n\\n _claim.timestampVerification = uint32(block.timestamp);\\n _claim.blocknumberVerification = uint32(block.number);\\n\\n claimHashes[_epoch] = hashClaim(_claim);\\n\\n emit VerificationStarted(_epoch);\\n }\\n\\n /// @dev Resolves the optimistic claim for '_epoch'.\\n /// @param _epoch The epoch of the optimistic claim.\\n /// @param _claim The claim associated with the epoch.\\n function verifySnapshot(uint256 _epoch, Claim memory _claim) external virtual OnlyBridgeRunning {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.challenger == address(0), \\\"Claim is challenged.\\\");\\n require(censorshipTestStatus(_claim) == CensorshipTestStatus.Passed, \\\"Censorship test not passed.\\\");\\n\\n if (_epoch > latestVerifiedEpoch) {\\n latestVerifiedEpoch = _epoch;\\n stateRoot = _claim.stateRoot;\\n emit Verified(_epoch);\\n }\\n\\n _claim.honest = Party.Claimer;\\n claimHashes[_epoch] = hashClaim(_claim);\\n }\\n\\n /// Note: Access restricted to AMB.\\n /// @dev Resolves any challenge of the optimistic claim for '_epoch'.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function resolveDisputedClaim(\\n uint256 _epoch,\\n bytes32 _stateRoot,\\n Claim memory _claim\\n ) external virtual OnlyBridgeRunning {\\n // Ethereum -> Gnosis message authentication with the AMB, the canonical Ethereum <-> Gnosis bridge.\\n // https://docs.tokenbridge.net/amb-bridge/development-of-a-cross-chain-application/how-to-develop-xchain-apps-by-amb#receive-a-method-call-from-the-amb-bridge\\n\\n require(msg.sender == address(amb), \\\"Not from native Gnosis AMB bridge.\\\");\\n require(bytes32(routerChainId) == amb.messageSourceChainId(), \\\"Invalid chain id.\\\");\\n require(routerArbToGnosis == amb.messageSender(), \\\"Not from router.\\\");\\n\\n if (_epoch > latestVerifiedEpoch && _stateRoot != bytes32(0)) {\\n latestVerifiedEpoch = _epoch;\\n stateRoot = _stateRoot;\\n emit Verified(_epoch);\\n }\\n\\n if (claimHashes[_epoch] == hashClaim(_claim)) {\\n if (_claim.stateRoot == _stateRoot) {\\n _claim.honest = Party.Claimer;\\n } else if (_claim.challenger != address(0)) {\\n _claim.honest = Party.Challenger;\\n }\\n claimHashes[_epoch] = hashClaim(_claim);\\n }\\n }\\n\\n /// @dev Verifies and relays the message. UNTRUSTED.\\n /// @param _proof The merkle proof to prove the message inclusion in the inbox state root.\\n /// @param _msgId The zero based index of the message in the inbox.\\n /// @param _to The address of the contract on Gnosis to call.\\n /// @param _message The message encoded in the vea inbox as abi.encodeWithSelector(fnSelector, msg.sender, param1, param2, ...)\\n function sendMessage(bytes32[] calldata _proof, uint64 _msgId, address _to, bytes calldata _message) external {\\n require(_proof.length < 64, \\\"Proof too long.\\\");\\n\\n bytes32 nodeHash = keccak256(abi.encodePacked(_msgId, _to, _message));\\n\\n // double hashed leaf\\n // avoids second order preimage attacks\\n // https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/\\n assembly {\\n mstore(0x00, nodeHash)\\n nodeHash := keccak256(0x00, 0x20)\\n }\\n\\n unchecked {\\n for (uint256 i = 0; i < _proof.length; i++) {\\n bytes32 proofElement = _proof[i];\\n // sort sibling hashes as a convention for efficient proof validation\\n if (proofElement > nodeHash)\\n assembly {\\n mstore(0x00, nodeHash)\\n mstore(0x20, proofElement)\\n nodeHash := keccak256(0x00, 0x40)\\n }\\n else\\n assembly {\\n mstore(0x00, proofElement)\\n mstore(0x20, nodeHash)\\n nodeHash := keccak256(0x00, 0x40)\\n }\\n }\\n }\\n\\n require(stateRoot == nodeHash, \\\"Invalid proof.\\\");\\n\\n // msgId is the zero-based index of the message in the inbox.\\n // msgId is also used as an index in the relayed bitmap to prevent replay.\\n // Note: a bitmap is used instead of a simple boolean mapping to save 15k gas per message.\\n\\n uint256 relayIndex = _msgId >> 8;\\n uint256 offset;\\n\\n unchecked {\\n offset = _msgId % 256;\\n }\\n\\n bytes32 replay = relayed[relayIndex];\\n\\n require(((replay >> offset) & bytes32(uint256(1))) == bytes32(0), \\\"Message already relayed\\\");\\n relayed[relayIndex] = replay | bytes32(1 << offset);\\n\\n // UNTRUSTED.\\n (bool success, ) = _to.call(_message);\\n require(success, \\\"Failed to call contract\\\");\\n\\n emit MessageRelayed(_msgId);\\n }\\n\\n /// @dev Sends the deposit back to the Claimer if successful. Includes a portion of the Challenger's deposit if unsuccessfully challenged.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawClaimDeposit(uint256 _epoch, Claim calldata _claim) external virtual {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.Claimer, \\\"Claim failed.\\\");\\n\\n delete claimHashes[_epoch];\\n\\n if (_claim.challenger != address(0)) {\\n weth.burn(burn); // no return value to check\\n require(weth.transfer(_claim.claimer, depositPlusReward), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n require(weth.transfer(_claim.claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n\\n /// @dev Sends the deposit back to the Challenger if successful. Includes a portion of the Bridger's deposit.\\n /// @param _epoch The epoch associated with the challenge deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawChallengeDeposit(uint256 _epoch, Claim calldata _claim) external {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.Challenger, \\\"Challenge failed.\\\");\\n\\n delete claimHashes[_epoch];\\n\\n weth.burn(burn); // no return value to check\\n require(weth.transfer(_claim.challenger, depositPlusReward), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n\\n /// @dev When bridge is shutdown, no claim disputes can be resolved. This allows the claimer to withdraw their deposit.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawClaimerEscapeHatch(uint256 _epoch, Claim memory _claim) external OnlyBridgeShutdown {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.None, \\\"Claim resolved.\\\");\\n\\n if (_claim.claimer != address(0)) {\\n if (_claim.challenger == address(0)) {\\n delete claimHashes[_epoch];\\n require(weth.transfer(_claim.claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n address claimer = _claim.claimer;\\n _claim.claimer = address(0);\\n claimHashes[_epoch] = hashClaim(_claim);\\n require(weth.transfer(claimer, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n }\\n\\n /// @dev When bridge is shutdown, no claim disputes can be resolved. This allows the challenger to withdraw their deposit.\\n /// @param _epoch The epoch associated with the claim deposit to withraw.\\n /// @param _claim The claim associated with the epoch.\\n function withdrawChallengerEscapeHatch(uint256 _epoch, Claim memory _claim) external OnlyBridgeShutdown {\\n require(claimHashes[_epoch] == hashClaim(_claim), \\\"Invalid claim.\\\");\\n require(_claim.honest == Party.None, \\\"Claim resolved.\\\");\\n\\n if (_claim.challenger != address(0)) {\\n if (_claim.claimer == address(0)) {\\n delete claimHashes[_epoch];\\n require(weth.transfer(_claim.challenger, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n } else {\\n address challenger = _claim.challenger;\\n _claim.challenger = address(0);\\n claimHashes[_epoch] == hashClaim(_claim);\\n require(weth.transfer(challenger, deposit), \\\"Failed WETH transfer.\\\"); // should revert on errors, but we check return value anyways\\n }\\n }\\n }\\n\\n // ************************************* //\\n // * Pure / Views * //\\n // ************************************* //\\n\\n /// @dev Hashes the claim.\\n /// @param _claim The claim to hash.\\n /// @return hashedClaim The hash of the claim.\\n function hashClaim(Claim memory _claim) public pure returns (bytes32 hashedClaim) {\\n return\\n hashedClaim = keccak256(\\n abi.encodePacked(\\n _claim.stateRoot,\\n _claim.claimer,\\n _claim.timestampClaimed,\\n _claim.timestampVerification,\\n _claim.blocknumberVerification,\\n _claim.honest,\\n _claim.challenger\\n )\\n );\\n }\\n\\n /// @dev Gets the status of the censorship test for claim.\\n /// @param _claim The claim to test.\\n /// @return status True if the claim passed the censorship test.\\n function censorshipTestStatus(Claim memory _claim) public view returns (CensorshipTestStatus status) {\\n unchecked {\\n if (uint256(_claim.timestampVerification) == 0) {\\n status = CensorshipTestStatus.NotStarted;\\n } else if (block.timestamp - uint256(_claim.timestampVerification) < minChallengePeriod) {\\n status = CensorshipTestStatus.InProgress;\\n } else {\\n uint256 expectedBlocks = uint256(_claim.blocknumberVerification) +\\n (block.timestamp - uint256(_claim.timestampVerification)) /\\n SLOT_TIME;\\n uint256 actualBlocks = block.number;\\n if (expectedBlocks - actualBlocks <= maxMissingBlocks) {\\n status = CensorshipTestStatus.Passed;\\n } else {\\n status = CensorshipTestStatus.Failed;\\n }\\n }\\n }\\n }\\n\\n /// @dev Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\\n /// @return epoch The hash of the claim.\\n function epochNow() external view returns (uint256 epoch) {\\n epoch = block.timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the current epoch from the outbox's point of view using the Ethereum L1 clock.\\n /// @return epoch The hash of the claim.\\n function epochAt(uint256 timestamp) external view returns (uint256 epoch) {\\n epoch = timestamp / epochPeriod;\\n }\\n\\n /// @dev Get the msg relayed status.\\n /// @param _msgId The msgId to check.\\n /// @return isRelayed True if the msg was relayed.\\n function isMsgRelayed(uint256 _msgId) external view returns (bool isRelayed) {\\n uint256 relayIndex = _msgId >> 8;\\n uint256 offset;\\n\\n unchecked {\\n offset = _msgId % 256;\\n }\\n\\n bytes32 replay = relayed[relayIndex];\\n\\n isRelayed = (replay >> offset) & bytes32(uint256(1)) == bytes32(uint256(1));\\n }\\n}\\n\",\"keccak256\":\"0x9f76fb20913b1458f88779d1ec1045c703a03ef8e185294754b04ee104e0f2ae\",\"license\":\"MIT\"},\"src/canonical/gnosis-chain/IAMB.sol\":{\"content\":\"// https://docs.gnosischain.com/bridges/tokenbridge/amb-bridge#gnosis\\n// https://github.com/omni/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/interfaces/IAMB.sol\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\ninterface IAMB {\\n function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);\\n\\n function maxGasPerTx() external view returns (uint256);\\n\\n function messageSender() external view returns (address);\\n\\n function messageSourceChainId() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xc94fccde4d2c5ede32856f84b8fd4275c353fce8a3f449a1d2a7246eafb7bc53\"},\"src/interfaces/outboxes/IVeaOutboxOnL1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../types/VeaClaim.sol\\\";\\n\\n/// @dev Interface of the Vea Outbox on L1 chains like Ethereum, Gnosis, Polygon POS where storage is expensive.\\ninterface IVeaOutboxOnL1 {\\n /// @dev Verifies and relays the message.\\n /// Note: Gateways expect first argument of message call to be the arbitrum message sender, used for authentication.\\n /// @param _proof The merkle proof to prove the message.\\n /// @param _msgId The zero based index of the message in the inbox.\\n /// @param _to The address to send the message to.\\n /// @param _message The message to relay.\\n function sendMessage(bytes32[] calldata _proof, uint64 _msgId, address _to, bytes calldata _message) external;\\n\\n /// @dev Resolves any challenge of the optimistic claim for 'epoch' using the canonical bridge.\\n /// Note: Access restricted to canonical bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function resolveDisputedClaim(uint256 _epoch, bytes32 _stateRoot, Claim memory _claim) external;\\n}\\n\",\"keccak256\":\"0xf1d52e289e790088502b7909f11f47bc33ddd3fc545636b7fb29c01ed00d3ff3\",\"license\":\"MIT\"},\"src/interfaces/tokens/gnosis/IWETH.sol\":{\"content\":\"// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/5daaf60d11ee2075260d0f3adfb22b1c536db983/contracts/token/ERC20/StandardBurnableToken.sol\\n// implementation: https://gnosisscan.io/address/0xf8d1677c8a0c961938bf2f9adc3f3cfda759a9d9#code\\n// proxy: https://gnosisscan.io/token/0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1#readProxyContract\\n\\n/**\\n * @title Standard Burnable Token\\n * @dev Token that can be irreversibly burned (destroyed).\\n */\\ninterface IWETH {\\n /**\\n * @dev Burns a specific amount of tokens.\\n * @param _value The amount of token to be burned.\\n */\\n function burn(uint256 _value) external;\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _owner The address to query the the balance of.\\n * @return An uint256 representing the amount owned by the passed address.\\n */\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /**\\n * @dev Transfer tokens from one address to another\\n * @param _from address The address which you want to send tokens from\\n * @param _to address The address which you want to transfer to\\n * @param _value uint256 the amount of tokens to be transferred\\n */\\n function transferFrom(address _from, address _to, uint256 _value) external returns (bool);\\n\\n /**\\n * @dev Transfer token for a specified address\\n * @param _to The address to transfer to.\\n * @param _value The amount to be transferred.\\n */\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n /**\\n * @dev Function to check the amount of tokens that an owner allowed to a spender.\\n * @param _owner address The address which owns the funds.\\n * @param _spender address The address which will spend the funds.\\n * @return A uint256 specifying the amount of tokens still available for the spender.\\n */\\n function allowance(address _owner, address _spender) external view returns (uint256);\\n\\n /**\\n * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.\\n * Beware that changing an allowance with this method brings the risk that someone may use both the old\\n * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this\\n * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n * @param _spender The address which will spend the funds.\\n * @param _value The amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) external returns (bool);\\n}\\n\",\"keccak256\":\"0x3d388cba7d9e9c0f579876cd530737511d24f0eac7f31fd6e01802505f4e24e3\"},\"src/interfaces/types/VeaClaim.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nenum Party {\\n None,\\n Claimer,\\n Challenger\\n}\\n\\nstruct Claim {\\n bytes32 stateRoot;\\n address claimer;\\n uint32 timestampClaimed;\\n uint32 timestampVerification;\\n uint32 blocknumberVerification;\\n Party honest;\\n address challenger;\\n}\\n\",\"keccak256\":\"0xfef781e359c97aebbe8dbfcb75edb7cb962139fd9ea538b8b89a3f2e13a05bfe\",\"license\":\"MIT\"},\"src/interfaces/updaters/ISequencerDelayUpdatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\n/// @dev Interface of a contract which is updatable, receiving parameter updates from an L1 contract through a cross-chain call.\\n/// @dev eg. Arbitrum (L2) -> Ethereum (L1) -> Gnosis (L1), the veaOutbox on Gnosis will be an ISequencerDelayUpdatable contract which receives updates from the router on Ethereum.\\ninterface ISequencerDelayUpdatable {\\n /// @dev Updates the sequencer limit.\\n /// Note: Access restricted to ensure the argument is passed from the Sequencer contract.\\n /// @param _newSequencerDelayLimit The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\\n /// @param _timestamp The timestamp of the message.\\n function updateSequencerDelayLimit(uint256 _newSequencerDelayLimit, uint256 _timestamp) external;\\n}\\n\",\"keccak256\":\"0x95ca3cc0dfaddee5c94a7e6b68bb9a90ce6d1b9cdd3b59241f5b1b5831ed89ec\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6101e060405234801562000011575f80fd5b5060405162002ac838038062002ac88339810160408190526200003491620000f0565b60e08a90526101608990526101a08790526101808890526001600160a01b0380871660805285811660a05260048590556101c0849052610140839052811660c0526200008260028b62000199565b610100819052620000958b6002620001b9565b620000a19190620001d9565b6101205261016051600190620000b8904262000199565b620000c49190620001d9565b60015550620001ef98505050505050505050565b6001600160a01b0381168114620000ed575f80fd5b50565b5f805f805f805f805f806101408b8d0312156200010b575f80fd5b8a51995060208b0151985060408b0151975060608b0151965060808b01516200013481620000d8565b60a08c01519096506200014781620000d8565b8095505060c08b0151935060e08b015192506101008b015191506101208b01516200017281620000d8565b809150509295989b9194979a5092959850565b634e487b7160e01b5f52601160045260245ffd5b5f82620001b457634e487b7160e01b5f52601260045260245ffd5b500490565b8082028115828204841417620001d357620001d362000185565b92915050565b81810381811115620001d357620001d362000185565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051612724620003a45f395f8181610431015261215e01525f818161045801528181610781015281816119c901528181611bba0152611e7201525f81816104b901526120f301525f818161047f015281816107a501528181610b2e01528181610efe015281816117a10152818161194b015281816119ed01528181611bde0152611e9601525f81816103ef0152818161091a0152610c4501525f81816103c801526114b601525f818161034c015281816113ca015261161401525f81816104e00152818161058001528181610e460152818161173f01528181611d3001528181611dc301528181611fe8015261208201525f81816102e6015281816105a601528181610e6c015281816113f0015281816114570152818161163a015281816116a1015281816116e401528181611d5601528181611de90152818161200e01526120a801525f818161050701528181610a050152610d3001525f8181610218015281816108200152818161089a0152818161097c01528181610b6301528181610bc50152610ca701526127245ff3fe608060405234801561000f575f80fd5b50600436106101e7575f3560e01c8063541adcca11610109578063b5b7a1841161009e578063d5e6a9df1161006e578063d5e6a9df14610502578063da2b7bc414610529578063df19e6ff1461053c578063e813a7551461055c575f80fd5b8063b5b7a1841461047a578063b633b944146104a1578063c2114a16146104b4578063d0e30db0146104db575f80fd5b8063930f28af116100d9578063930f28af146104115780639588eca214610424578063aa22a1c61461042c578063b044397e14610453575f80fd5b8063541adcca146103a75780637ffc2a6e146103ba578063836e344b146103c35780638d96fdea146103ea575f80fd5b806331ddf7431161017f57806344df8e701161014f57806344df8e70146103475780634788cb381461036e57806349b4299e146103815780634a439cfe14610394575f80fd5b806331ddf743146102bb5780633ce43cfd146102ce5780633fc8cef3146102e157806343b066d514610308575f80fd5b80632639c060116101ba5780632639c0601461026d57806327ee6bdd1461028c5780632c1925191461029557806331d14457146102a8575f80fd5b806301139b68146101eb5780630f0adca5146102005780631062b39a14610213578063222ae78614610257575b5f80fd5b6101fe6101f9366004612293565b610565565b005b6101fe61020e3660046122bf565b61077f565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61025f610b28565b60405190815260200161024e565b61025f61027b3660046122f3565b60026020525f908152604090205481565b61025f60015481565b6101fe6102a336600461230a565b610b58565b6101fe6102b636600461230a565b610e2b565b6101fe6102c9366004612386565b61107a565b6101fe6102dc36600461243f565b61130a565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6103376103163660046122f3565b600881901c5f90815260036020526040902054600160ff9092161c81161490565b604051901515815260200161024e565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe61037c36600461243f565b61153a565b6101fe61038f366004612293565b61176b565b61025f6103a23660046122f3565b611945565b61025f6103b5366004612475565b611976565b61025f60055481565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe61041f366004612293565b6119c7565b61025f5f5481565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe6104af366004612293565b611bb8565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe610537366004612293565b611e70565b61054f61054a366004612475565b6120d7565b60405161024e91906124aa565b61025f60045481565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af11580156105f4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061891906124c4565b61063d5760405162461bcd60e51b8152600401610634906124e3565b60405180910390fd5b61064681611976565b5f83815260026020526040902054146106715760405162461bcd60e51b815260040161063490612512565b60c08101516001600160a01b0316156106cc5760405162461bcd60e51b815260206004820152601960248201527f436c61696d20616c7265616479206368616c6c656e6765642e000000000000006044820152606401610634565b5f8160a0015160028111156106e3576106e3612496565b146107305760405162461bcd60e51b815260206004820152601760248201527f436c61696d20616c72656164792076657269666965642e0000000000000000006044820152606401610634565b3360c082015261073f81611976565b5f83815260026020526040808220929092559051339184917fcfe09ca25f55d949baba5e280f5750c9ba4b9048fca5532f916067d433afe4d79190a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f000000000000000000000000000000000000000000000000000000000000000042816107d2576107d261253a565b040311156108155760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b6044820152606401610634565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108985760405162461bcd60e51b815260206004820152602260248201527f4e6f742066726f6d206e617469766520476e6f73697320414d42206272696467604482015261329760f11b6064820152608401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610918919061254e565b7f00000000000000000000000000000000000000000000000000000000000000001461097a5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fa9190612565565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610a6d5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b6044820152606401610634565b60015483118015610a7d57508115155b15610abf5760018390555f8290556040518381527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b610ac881611976565b5f8481526002602052604090205403610b23578051829003610af057600160a0820152610b0b565b60c08101516001600160a01b031615610b0b57600260a08201525b610b1481611976565b5f848152600260205260409020555b505050565b5f610b537f000000000000000000000000000000000000000000000000000000000000000042612594565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bc35760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c43919061254e565b7f000000000000000000000000000000000000000000000000000000000000000014610ca55760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d259190612565565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610d985760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b6044820152606401610634565b8060055410610de05760405162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29034b99037baba3230ba32b21760611b6044820152606401610634565b8160045414610e2757600482905560058190556040518281527f684f6fb71cbcb798156dcca2a95dbd142fa1f8957637833b1897ab89e05aa7079060200160405180910390a15b5050565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af1158015610eba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ede91906124c4565b610efa5760405162461bcd60e51b8152600401610634906124e3565b60017f00000000000000000000000000000000000000000000000000000000000000004281610f2b57610f2b61253a565b04038214610f7b5760405162461bcd60e51b815260206004820152601960248201527f45706f636820686173206e6f7420796574207061737365642e000000000000006044820152606401610634565b80610f985760405162461bcd60e51b815260040161063490612512565b5f8281526002602052604090205415610fe95760405162461bcd60e51b815260206004820152601360248201527221b630b4b69030b63932b0b23c9036b0b2329760691b6044820152606401610634565b6040805160e0810182528281523360208201524263ffffffff16918101919091525f606082018190526080820181905260a0820181905260c082015261102e90611976565b5f838152600260209081526040918290209290925551828152839133917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a35050565b604085106110bc5760405162461bcd60e51b815260206004820152600f60248201526e283937b7b3103a37b7903637b7339760891b6044820152606401610634565b5f848484846040516020016110d494939291906125b3565b604051602081830303815290604052805190602001209050805f5260205f2090505f5b8681101561114c575f888883818110611112576111126125f4565b9050602002013590508281111561113557825f528060205260405f209250611143565b805f528260205260405f2092505b506001016110f7565b50805f541461118e5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b210383937b7b31760911b6044820152606401610634565b600885901c66ffffffffffffff165f8181526003602052604090205460ff87169080821c600116156112025760405162461bcd60e51b815260206004820152601760248201527f4d65737361676520616c72656164792072656c617965640000000000000000006044820152606401610634565b5f838152600360205260408082206001851b84179055516001600160a01b038916906112319089908990612608565b5f604051808303815f865af19150503d805f811461126a576040519150601f19603f3d011682016040523d82523d5f602084013e61126f565b606091505b50509050806112c05760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f2063616c6c20636f6e74726163740000000000000000006044820152606401610634565b60405167ffffffffffffffff8a1681527f54303fab361bc52c2f1f56ace7351189582264f74ce47a6e7c3f478d64c429439060200160405180910390a15050505050505050505050565b61131c6103b536839003830183612475565b5f83815260026020526040902054146113475760405162461bcd60e51b815260040161063490612512565b600261135960c0830160a08401612617565b600281111561136a5761136a612496565b146113ab5760405162461bcd60e51b815260206004820152601160248201527021b430b63632b733b2903330b4b632b21760791b6044820152606401610634565b5f828152600260205260408082209190915551630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c68906024015f604051808303815f87803b158015611439575f80fd5b505af115801561144b573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061149060e0840160c08501612630565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044015b6020604051808303815f875af11580156114fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061151e91906124c4565b610e275760405162461bcd60e51b8152600401610634906124e3565b61154c6103b536839003830183612475565b5f83815260026020526040902054146115775760405162461bcd60e51b815260040161063490612512565b600161158960c0830160a08401612617565b600281111561159a5761159a612496565b146115d75760405162461bcd60e51b815260206004820152600d60248201526c21b630b4b6903330b4b632b21760991b6044820152606401610634565b5f8281526002602052604081208190556115f760e0830160c08401612630565b6001600160a01b0316146116da57604051630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c68906024015f604051808303815f87803b158015611683575f80fd5b505af1158015611695573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb90506114906040840160208501612630565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb6117196040840160208501612630565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044016114de565b61177481611976565b5f838152600260205260409020541461179f5760405162461bcd60e51b815260040161063490612512565b7f00000000000000000000000000000000000000000000000000000000000000006004546117cd919061264b565b60408201516117e29063ffffffff164261265e565b10156118455760405162461bcd60e51b815260206004820152602c60248201527f436c61696d206d75737420776169742061746c65617374206d61784c3253746160448201526b3a32a9bcb731a232b630bc9760a11b6064820152608401610634565b5f61184f826120d7565b9050600281600381111561186557611865612496565b148061188157505f81600381111561187f5761187f612496565b145b6118ea5760405162461bcd60e51b815260206004820152603460248201527f436c61696d20766572696669636174696f6e20696e2070726f6772657373206f604482015273391030b63932b0b23c9031b7b6b83632ba32b21760611b6064820152608401610634565b63ffffffff42811660608401524316608083015261190782611976565b5f8481526002602052604080822092909255905184917f37b700b61b9b4710dddb0c3316b2be7ef6088ed4b1d7bfe0fb98be8f9a163e1691a2505050565b5f6119707f000000000000000000000000000000000000000000000000000000000000000083612594565b92915050565b80516020808301516040808501516060860151608087015160a088015160c089015194515f986119aa989097969101612671565b604051602081830303815290604052805190602001209050919050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611a1a57611a1a61253a565b04031115611a5d5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b6044820152606401610634565b611a6681611976565b5f8381526002602052604090205414611a915760405162461bcd60e51b815260040161063490612512565b60c08101516001600160a01b031615611ae35760405162461bcd60e51b815260206004820152601460248201527321b630b4b69034b99031b430b63632b733b2b21760611b6044820152606401610634565b6001611aee826120d7565b6003811115611aff57611aff612496565b14611b4c5760405162461bcd60e51b815260206004820152601b60248201527f43656e736f72736869702074657374206e6f74207061737365642e00000000006044820152606401610634565b600154821115611b9357600182905580515f556040518281527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b600160a0820152611ba381611976565b5f928352600260205260409092209190915550565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611c0b57611c0b61253a565b040311611c4c5760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b6044820152606401610634565b611c5581611976565b5f8381526002602052604090205414611c805760405162461bcd60e51b815260040161063490612512565b5f8160a001516002811115611c9757611c97612496565b14611cd65760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b6044820152606401610634565b60c08101516001600160a01b031615610e275760208101516001600160a01b0316611d87575f828152600260205260408082209190915560c0820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016114de565b60c0810180515f909152611d9a82611976565b505f839052600260205260405163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044015b6020604051808303815f875af1158015611e30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e5491906124c4565b610b235760405162461bcd60e51b8152600401610634906124e3565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611ec357611ec361253a565b040311611f045760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b6044820152606401610634565b611f0d81611976565b5f8381526002602052604090205414611f385760405162461bcd60e51b815260040161063490612512565b5f8160a001516002811115611f4f57611f4f612496565b14611f8e5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b6044820152606401610634565b60208101516001600160a01b031615610e275760c08101516001600160a01b031661203f575f82815260026020908152604080832092909255820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016114de565b6020810180515f90915261205282611976565b5f8481526002602052604090819020919091555163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401611e14565b5f816060015163ffffffff165f036120f157506002919050565b7f0000000000000000000000000000000000000000000000000000000000000000826060015163ffffffff164203101561212d57506003919050565b5f6005836060015163ffffffff1642038161214a5761214a61253a565b608085015163ffffffff16919004019050437f00000000000000000000000000000000000000000000000000000000000000008183031161218e5760019250612192565b5f92505b50505b919050565b6001600160a01b03811681146121ae575f80fd5b50565b80356121958161219a565b803563ffffffff81168114612195575f80fd5b803560038110612195575f80fd5b5f60e082840312156121ed575f80fd5b60405160e0810181811067ffffffffffffffff8211171561221c57634e487b7160e01b5f52604160045260245ffd5b60405282358152905080612232602084016121b1565b6020820152612243604084016121bc565b6040820152612254606084016121bc565b6060820152612265608084016121bc565b608082015261227660a084016121cf565b60a082015261228760c084016121b1565b60c08201525092915050565b5f8061010083850312156122a5575f80fd5b823591506122b684602085016121dd565b90509250929050565b5f805f61012084860312156122d2575f80fd5b83359250602084013591506122ea85604086016121dd565b90509250925092565b5f60208284031215612303575f80fd5b5035919050565b5f806040838503121561231b575f80fd5b50508035926020909101359150565b803567ffffffffffffffff81168114612195575f80fd5b5f8083601f840112612351575f80fd5b50813567ffffffffffffffff811115612368575f80fd5b60208301915083602082850101111561237f575f80fd5b9250929050565b5f805f805f806080878903121561239b575f80fd5b863567ffffffffffffffff808211156123b2575f80fd5b818901915089601f8301126123c5575f80fd5b8135818111156123d3575f80fd5b8a60208260051b85010111156123e7575f80fd5b602083019850809750506123fd60208a0161232a565b955061240b60408a016121b1565b94506060890135915080821115612420575f80fd5b5061242d89828a01612341565b979a9699509497509295939492505050565b5f80828403610100811215612452575f80fd5b8335925060e0601f1982011215612467575f80fd5b506020830190509250929050565b5f60e08284031215612485575f80fd5b61248f83836121dd565b9392505050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106124be576124be612496565b91905290565b5f602082840312156124d4575f80fd5b8151801515811461248f575f80fd5b6020808252601590820152742330b4b632b2102ba2aa24103a3930b739b332b91760591b604082015260600190565b6020808252600e908201526d24b73b30b634b21031b630b4b69760911b604082015260600190565b634e487b7160e01b5f52601260045260245ffd5b5f6020828403121561255e575f80fd5b5051919050565b5f60208284031215612575575f80fd5b815161248f8161219a565b634e487b7160e01b5f52601160045260245ffd5b5f826125ae57634e487b7160e01b5f52601260045260245ffd5b500490565b60c085901b6001600160c01b0319168152606084901b6bffffffffffffffffffffffff191660088201528183601c8301375f9101601c019081529392505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b5f60208284031215612627575f80fd5b61248f826121cf565b5f60208284031215612640575f80fd5b813561248f8161219a565b8082018082111561197057611970612580565b8181038181111561197057611970612580565b8781525f6bffffffffffffffffffffffff19808960601b16602084015263ffffffff60e01b808960e01b166034850152808860e01b166038850152808760e01b16603c85015250600385106126c8576126c8612496565b60f89490941b60408301525060609190911b90911660418201526055019594505050505056fea2646970667358221220085a7f7ce89fabfee13037425388b7d529faac1107a11bebfa1730d16cdf9fb264736f6c63430008180033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106101e7575f3560e01c8063541adcca11610109578063b5b7a1841161009e578063d5e6a9df1161006e578063d5e6a9df14610502578063da2b7bc414610529578063df19e6ff1461053c578063e813a7551461055c575f80fd5b8063b5b7a1841461047a578063b633b944146104a1578063c2114a16146104b4578063d0e30db0146104db575f80fd5b8063930f28af116100d9578063930f28af146104115780639588eca214610424578063aa22a1c61461042c578063b044397e14610453575f80fd5b8063541adcca146103a75780637ffc2a6e146103ba578063836e344b146103c35780638d96fdea146103ea575f80fd5b806331ddf7431161017f57806344df8e701161014f57806344df8e70146103475780634788cb381461036e57806349b4299e146103815780634a439cfe14610394575f80fd5b806331ddf743146102bb5780633ce43cfd146102ce5780633fc8cef3146102e157806343b066d514610308575f80fd5b80632639c060116101ba5780632639c0601461026d57806327ee6bdd1461028c5780632c1925191461029557806331d14457146102a8575f80fd5b806301139b68146101eb5780630f0adca5146102005780631062b39a14610213578063222ae78614610257575b5f80fd5b6101fe6101f9366004612293565b610565565b005b6101fe61020e3660046122bf565b61077f565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61025f610b28565b60405190815260200161024e565b61025f61027b3660046122f3565b60026020525f908152604090205481565b61025f60015481565b6101fe6102a336600461230a565b610b58565b6101fe6102b636600461230a565b610e2b565b6101fe6102c9366004612386565b61107a565b6101fe6102dc36600461243f565b61130a565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6103376103163660046122f3565b600881901c5f90815260036020526040902054600160ff9092161c81161490565b604051901515815260200161024e565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe61037c36600461243f565b61153a565b6101fe61038f366004612293565b61176b565b61025f6103a23660046122f3565b611945565b61025f6103b5366004612475565b611976565b61025f60055481565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe61041f366004612293565b6119c7565b61025f5f5481565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe6104af366004612293565b611bb8565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61023a7f000000000000000000000000000000000000000000000000000000000000000081565b6101fe610537366004612293565b611e70565b61054f61054a366004612475565b6120d7565b60405161024e91906124aa565b61025f60045481565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af11580156105f4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061891906124c4565b61063d5760405162461bcd60e51b8152600401610634906124e3565b60405180910390fd5b61064681611976565b5f83815260026020526040902054146106715760405162461bcd60e51b815260040161063490612512565b60c08101516001600160a01b0316156106cc5760405162461bcd60e51b815260206004820152601960248201527f436c61696d20616c7265616479206368616c6c656e6765642e000000000000006044820152606401610634565b5f8160a0015160028111156106e3576106e3612496565b146107305760405162461bcd60e51b815260206004820152601760248201527f436c61696d20616c72656164792076657269666965642e0000000000000000006044820152606401610634565b3360c082015261073f81611976565b5f83815260026020526040808220929092559051339184917fcfe09ca25f55d949baba5e280f5750c9ba4b9048fca5532f916067d433afe4d79190a35050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f000000000000000000000000000000000000000000000000000000000000000042816107d2576107d261253a565b040311156108155760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b6044820152606401610634565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108985760405162461bcd60e51b815260206004820152602260248201527f4e6f742066726f6d206e617469766520476e6f73697320414d42206272696467604482015261329760f11b6064820152608401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108f4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610918919061254e565b7f00000000000000000000000000000000000000000000000000000000000000001461097a5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109fa9190612565565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610a6d5760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b6044820152606401610634565b60015483118015610a7d57508115155b15610abf5760018390555f8290556040518381527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b610ac881611976565b5f8481526002602052604090205403610b23578051829003610af057600160a0820152610b0b565b60c08101516001600160a01b031615610b0b57600260a08201525b610b1481611976565b5f848152600260205260409020555b505050565b5f610b537f000000000000000000000000000000000000000000000000000000000000000042612594565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bc35760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e307dff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c43919061254e565b7f000000000000000000000000000000000000000000000000000000000000000014610ca55760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21031b430b4b71034b21760791b6044820152606401610634565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d67bdd256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d259190612565565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610d985760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b6903937baba32b91760811b6044820152606401610634565b8060055410610de05760405162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29034b99037baba3230ba32b21760611b6044820152606401610634565b8160045414610e2757600482905560058190556040518281527f684f6fb71cbcb798156dcca2a95dbd142fa1f8957637833b1897ab89e05aa7079060200160405180910390a15b5050565b6040516323b872dd60e01b81523360048201523060248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af1158015610eba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ede91906124c4565b610efa5760405162461bcd60e51b8152600401610634906124e3565b60017f00000000000000000000000000000000000000000000000000000000000000004281610f2b57610f2b61253a565b04038214610f7b5760405162461bcd60e51b815260206004820152601960248201527f45706f636820686173206e6f7420796574207061737365642e000000000000006044820152606401610634565b80610f985760405162461bcd60e51b815260040161063490612512565b5f8281526002602052604090205415610fe95760405162461bcd60e51b815260206004820152601360248201527221b630b4b69030b63932b0b23c9036b0b2329760691b6044820152606401610634565b6040805160e0810182528281523360208201524263ffffffff16918101919091525f606082018190526080820181905260a0820181905260c082015261102e90611976565b5f838152600260209081526040918290209290925551828152839133917fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d57910160405180910390a35050565b604085106110bc5760405162461bcd60e51b815260206004820152600f60248201526e283937b7b3103a37b7903637b7339760891b6044820152606401610634565b5f848484846040516020016110d494939291906125b3565b604051602081830303815290604052805190602001209050805f5260205f2090505f5b8681101561114c575f888883818110611112576111126125f4565b9050602002013590508281111561113557825f528060205260405f209250611143565b805f528260205260405f2092505b506001016110f7565b50805f541461118e5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b210383937b7b31760911b6044820152606401610634565b600885901c66ffffffffffffff165f8181526003602052604090205460ff87169080821c600116156112025760405162461bcd60e51b815260206004820152601760248201527f4d65737361676520616c72656164792072656c617965640000000000000000006044820152606401610634565b5f838152600360205260408082206001851b84179055516001600160a01b038916906112319089908990612608565b5f604051808303815f865af19150503d805f811461126a576040519150601f19603f3d011682016040523d82523d5f602084013e61126f565b606091505b50509050806112c05760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f2063616c6c20636f6e74726163740000000000000000006044820152606401610634565b60405167ffffffffffffffff8a1681527f54303fab361bc52c2f1f56ace7351189582264f74ce47a6e7c3f478d64c429439060200160405180910390a15050505050505050505050565b61131c6103b536839003830183612475565b5f83815260026020526040902054146113475760405162461bcd60e51b815260040161063490612512565b600261135960c0830160a08401612617565b600281111561136a5761136a612496565b146113ab5760405162461bcd60e51b815260206004820152601160248201527021b430b63632b733b2903330b4b632b21760791b6044820152606401610634565b5f828152600260205260408082209190915551630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c68906024015f604051808303815f87803b158015611439575f80fd5b505af115801561144b573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb905061149060e0840160c08501612630565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044015b6020604051808303815f875af11580156114fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061151e91906124c4565b610e275760405162461bcd60e51b8152600401610634906124e3565b61154c6103b536839003830183612475565b5f83815260026020526040902054146115775760405162461bcd60e51b815260040161063490612512565b600161158960c0830160a08401612617565b600281111561159a5761159a612496565b146115d75760405162461bcd60e51b815260206004820152600d60248201526c21b630b4b6903330b4b632b21760991b6044820152606401610634565b5f8281526002602052604081208190556115f760e0830160c08401612630565b6001600160a01b0316146116da57604051630852cd8d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c68906024015f604051808303815f87803b158015611683575f80fd5b505af1158015611695573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063a9059cbb90506114906040840160208501612630565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb6117196040840160208501612630565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201527f000000000000000000000000000000000000000000000000000000000000000060248201526044016114de565b61177481611976565b5f838152600260205260409020541461179f5760405162461bcd60e51b815260040161063490612512565b7f00000000000000000000000000000000000000000000000000000000000000006004546117cd919061264b565b60408201516117e29063ffffffff164261265e565b10156118455760405162461bcd60e51b815260206004820152602c60248201527f436c61696d206d75737420776169742061746c65617374206d61784c3253746160448201526b3a32a9bcb731a232b630bc9760a11b6064820152608401610634565b5f61184f826120d7565b9050600281600381111561186557611865612496565b148061188157505f81600381111561187f5761187f612496565b145b6118ea5760405162461bcd60e51b815260206004820152603460248201527f436c61696d20766572696669636174696f6e20696e2070726f6772657373206f604482015273391030b63932b0b23c9031b7b6b83632ba32b21760611b6064820152608401610634565b63ffffffff42811660608401524316608083015261190782611976565b5f8481526002602052604080822092909255905184917f37b700b61b9b4710dddb0c3316b2be7ef6088ed4b1d7bfe0fb98be8f9a163e1691a2505050565b5f6119707f000000000000000000000000000000000000000000000000000000000000000083612594565b92915050565b80516020808301516040808501516060860151608087015160a088015160c089015194515f986119aa989097969101612671565b604051602081830303815290604052805190602001209050919050565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611a1a57611a1a61253a565b04031115611a5d5760405162461bcd60e51b815260206004820152601060248201526f213934b233b29029b43aba3237bbb71760811b6044820152606401610634565b611a6681611976565b5f8381526002602052604090205414611a915760405162461bcd60e51b815260040161063490612512565b60c08101516001600160a01b031615611ae35760405162461bcd60e51b815260206004820152601460248201527321b630b4b69034b99031b430b63632b733b2b21760611b6044820152606401610634565b6001611aee826120d7565b6003811115611aff57611aff612496565b14611b4c5760405162461bcd60e51b815260206004820152601b60248201527f43656e736f72736869702074657374206e6f74207061737365642e00000000006044820152606401610634565b600154821115611b9357600182905580515f556040518281527ff786e7f77ede00a02a5464f8f0555798f42ba99a4a920ef2778db8d75e4656f79060200160405180910390a15b600160a0820152611ba381611976565b5f928352600260205260409092209190915550565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611c0b57611c0b61253a565b040311611c4c5760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b6044820152606401610634565b611c5581611976565b5f8381526002602052604090205414611c805760405162461bcd60e51b815260040161063490612512565b5f8160a001516002811115611c9757611c97612496565b14611cd65760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b6044820152606401610634565b60c08101516001600160a01b031615610e275760208101516001600160a01b0316611d87575f828152600260205260408082209190915560c0820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016114de565b60c0810180515f909152611d9a82611976565b505f839052600260205260405163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044015b6020604051808303815f875af1158015611e30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e5491906124c4565b610b235760405162461bcd60e51b8152600401610634906124e3565b7f00000000000000000000000000000000000000000000000000000000000000006001547f00000000000000000000000000000000000000000000000000000000000000004281611ec357611ec361253a565b040311611f045760405162461bcd60e51b815260206004820152600f60248201526e213934b233b290293ab73734b7339760891b6044820152606401610634565b611f0d81611976565b5f8381526002602052604090205414611f385760405162461bcd60e51b815260040161063490612512565b5f8160a001516002811115611f4f57611f4f612496565b14611f8e5760405162461bcd60e51b815260206004820152600f60248201526e21b630b4b6903932b9b7b63b32b21760891b6044820152606401610634565b60208101516001600160a01b031615610e275760c08101516001600160a01b031661203f575f82815260026020908152604080832092909255820151905163a9059cbb60e01b81526001600160a01b0391821660048201527f000000000000000000000000000000000000000000000000000000000000000060248201527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016114de565b6020810180515f90915261205282611976565b5f8481526002602052604090819020919091555163a9059cbb60e01b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401611e14565b5f816060015163ffffffff165f036120f157506002919050565b7f0000000000000000000000000000000000000000000000000000000000000000826060015163ffffffff164203101561212d57506003919050565b5f6005836060015163ffffffff1642038161214a5761214a61253a565b608085015163ffffffff16919004019050437f00000000000000000000000000000000000000000000000000000000000000008183031161218e5760019250612192565b5f92505b50505b919050565b6001600160a01b03811681146121ae575f80fd5b50565b80356121958161219a565b803563ffffffff81168114612195575f80fd5b803560038110612195575f80fd5b5f60e082840312156121ed575f80fd5b60405160e0810181811067ffffffffffffffff8211171561221c57634e487b7160e01b5f52604160045260245ffd5b60405282358152905080612232602084016121b1565b6020820152612243604084016121bc565b6040820152612254606084016121bc565b6060820152612265608084016121bc565b608082015261227660a084016121cf565b60a082015261228760c084016121b1565b60c08201525092915050565b5f8061010083850312156122a5575f80fd5b823591506122b684602085016121dd565b90509250929050565b5f805f61012084860312156122d2575f80fd5b83359250602084013591506122ea85604086016121dd565b90509250925092565b5f60208284031215612303575f80fd5b5035919050565b5f806040838503121561231b575f80fd5b50508035926020909101359150565b803567ffffffffffffffff81168114612195575f80fd5b5f8083601f840112612351575f80fd5b50813567ffffffffffffffff811115612368575f80fd5b60208301915083602082850101111561237f575f80fd5b9250929050565b5f805f805f806080878903121561239b575f80fd5b863567ffffffffffffffff808211156123b2575f80fd5b818901915089601f8301126123c5575f80fd5b8135818111156123d3575f80fd5b8a60208260051b85010111156123e7575f80fd5b602083019850809750506123fd60208a0161232a565b955061240b60408a016121b1565b94506060890135915080821115612420575f80fd5b5061242d89828a01612341565b979a9699509497509295939492505050565b5f80828403610100811215612452575f80fd5b8335925060e0601f1982011215612467575f80fd5b506020830190509250929050565b5f60e08284031215612485575f80fd5b61248f83836121dd565b9392505050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106124be576124be612496565b91905290565b5f602082840312156124d4575f80fd5b8151801515811461248f575f80fd5b6020808252601590820152742330b4b632b2102ba2aa24103a3930b739b332b91760591b604082015260600190565b6020808252600e908201526d24b73b30b634b21031b630b4b69760911b604082015260600190565b634e487b7160e01b5f52601260045260245ffd5b5f6020828403121561255e575f80fd5b5051919050565b5f60208284031215612575575f80fd5b815161248f8161219a565b634e487b7160e01b5f52601160045260245ffd5b5f826125ae57634e487b7160e01b5f52601260045260245ffd5b500490565b60c085901b6001600160c01b0319168152606084901b6bffffffffffffffffffffffff191660088201528183601c8301375f9101601c019081529392505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b5f60208284031215612627575f80fd5b61248f826121cf565b5f60208284031215612640575f80fd5b813561248f8161219a565b8082018082111561197057611970612580565b8181038181111561197057611970612580565b8781525f6bffffffffffffffffffffffff19808960601b16602084015263ffffffff60e01b808960e01b166034850152808860e01b166038850152808760e01b16603c85015250600385106126c8576126c8612496565b60f89490941b60408301525060609190911b90911660418201526055019594505050505056fea2646970667358221220085a7f7ce89fabfee13037425388b7d529faac1107a11bebfa1730d16cdf9fb264736f6c63430008180033", "devdoc": { "details": "Vea Outbox From Arbitrum to Gnosis. Note: This contract is deployed on Gnosis.", "events": { @@ -1267,7 +1267,7 @@ "storageLayout": { "storage": [ { - "astId": 1495, + "astId": 450, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "stateRoot", "offset": 0, @@ -1275,7 +1275,7 @@ "type": "t_bytes32" }, { - "astId": 1497, + "astId": 452, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "latestVerifiedEpoch", "offset": 0, @@ -1283,7 +1283,7 @@ "type": "t_uint256" }, { - "astId": 1501, + "astId": 456, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "claimHashes", "offset": 0, @@ -1291,7 +1291,7 @@ "type": "t_mapping(t_uint256,t_bytes32)" }, { - "astId": 1505, + "astId": 460, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "relayed", "offset": 0, @@ -1299,7 +1299,7 @@ "type": "t_mapping(t_uint256,t_bytes32)" }, { - "astId": 1507, + "astId": 462, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "sequencerDelayLimit", "offset": 0, @@ -1307,7 +1307,7 @@ "type": "t_uint256" }, { - "astId": 1509, + "astId": 464, "contract": "src/arbitrumToGnosis/VeaOutboxArbToGnosis.sol:VeaOutboxArbToGnosis", "label": "timestampDelayUpdated", "offset": 0, diff --git a/contracts/deployments/sepolia/RouterArbToGnosisTestnet.json b/contracts/deployments/sepolia/RouterArbToGnosisTestnet.json new file mode 100644 index 00000000..8d9c6620 --- /dev/null +++ b/contracts/deployments/sepolia/RouterArbToGnosisTestnet.json @@ -0,0 +1,395 @@ +{ + "address": "0x22d70804d4Ef5BB206C6B39e3267DFe8a0f97d27", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IBridge", + "name": "_bridge", + "type": "address" + }, + { + "internalType": "contract IAMB", + "name": "_amb", + "type": "address" + }, + { + "internalType": "address", + "name": "_veaInboxArbToGnosis", + "type": "address" + }, + { + "internalType": "address", + "name": "_veaOutboxArbToGnosis", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "_ticketID", + "type": "bytes32" + } + ], + "name": "Routed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_requestedSequencerDelayLimit", + "type": "uint256" + } + ], + "name": "sequencerDelayLimitDecreaseRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "_ticketID", + "type": "bytes32" + } + ], + "name": "sequencerDelayLimitSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_newSequencerDelayLimit", + "type": "uint256" + } + ], + "name": "sequencerDelayLimitUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "amb", + "outputs": [ + { + "internalType": "contract IAMB", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "executeSequencerDelayLimitDecreaseRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_stateroot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "claimer", + "type": "address" + }, + { + "internalType": "uint32", + "name": "timestampClaimed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "timestampVerification", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blocknumberVerification", + "type": "uint32" + }, + { + "internalType": "enum Party", + "name": "honest", + "type": "uint8" + }, + { + "internalType": "address", + "name": "challenger", + "type": "address" + } + ], + "internalType": "struct Claim", + "name": "_claim", + "type": "tuple" + } + ], + "name": "route", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sequencerDelayLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sequencerDelayLimitDecreaseRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "requestedSequencerLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updatesequencerDelayLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "veaInboxArbToGnosis", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "veaOutboxArbToGnosis", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x6ce9144ad70f3773de005f80c3995eaec001593d90a4760cd44b3c0271614930", + "receipt": { + "to": null, + "from": "0xcAf9AdE1fDDf1b31d490A4629ADA638d104e9543", + "contractAddress": "0x22d70804d4Ef5BB206C6B39e3267DFe8a0f97d27", + "transactionIndex": 110, + "gasUsed": "848386", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6e7e69581ab3b83daf309bf58b4d0c938d2a49880e14392392bce28095f16578", + "transactionHash": "0x6ce9144ad70f3773de005f80c3995eaec001593d90a4760cd44b3c0271614930", + "logs": [], + "blockNumber": 6696213, + "cumulativeGasUsed": "11619625", + "status": 1, + "byzantium": true + }, + "args": [ + "0x38f918D0E9F1b721EDaA41302E399fa1B79333a9", + "0xf2546D6648BD2af6a008A7e7C1542BB240329E11", + "0x72c7d51647cBeaca636d0E20A66ca2F682da3539", + "0xa3C6608539693C13434e4E29c9aB53Dd029178BE" + ], + "numDeployments": 2, + "solcInputHash": "f928479ba06eba5cf30d89f1e4f4841c", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IBridge\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"contract IAMB\",\"name\":\"_amb\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_veaInboxArbToGnosis\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_veaOutboxArbToGnosis\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_ticketID\",\"type\":\"bytes32\"}],\"name\":\"Routed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_requestedSequencerDelayLimit\",\"type\":\"uint256\"}],\"name\":\"sequencerDelayLimitDecreaseRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"_ticketID\",\"type\":\"bytes32\"}],\"name\":\"sequencerDelayLimitSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newSequencerDelayLimit\",\"type\":\"uint256\"}],\"name\":\"sequencerDelayLimitUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"contract IBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"executeSequencerDelayLimitDecreaseRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_stateroot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"timestampClaimed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"timestampVerification\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blocknumberVerification\",\"type\":\"uint32\"},{\"internalType\":\"enum Party\",\"name\":\"honest\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"}],\"internalType\":\"struct Claim\",\"name\":\"_claim\",\"type\":\"tuple\"}],\"name\":\"route\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequencerDelayLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequencerDelayLimitDecreaseRequest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requestedSequencerLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updatesequencerDelayLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"veaInboxArbToGnosis\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"veaOutboxArbToGnosis\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Router from Arbitrum to Gnosis Chain. Note: This contract is deployed on Ethereum.\",\"events\":{\"Routed(uint256,bytes32)\":{\"details\":\"Event emitted when a message is relayed to another Safe Bridge.\",\"params\":{\"_epoch\":\"The epoch of the batch requested to send.\",\"_ticketID\":\"The unique identifier provided by the underlying canonical bridge.\"}},\"sequencerDelayLimitDecreaseRequested(uint256)\":{\"details\":\"This event indicates that a request to decrease the sequencer limit has been made.\",\"params\":{\"_requestedSequencerDelayLimit\":\"The new sequencer limit requested.\"}},\"sequencerDelayLimitSent(bytes32)\":{\"details\":\"This event indicates a cross-chain message was sent to inform the veaOutbox of the sequencer limit value\",\"params\":{\"_ticketID\":\"The ticketID from the AMB of the cross-chain message.\"}},\"sequencerDelayLimitUpdated(uint256)\":{\"details\":\"This event indicates the sequencer limit updated.\",\"params\":{\"_newSequencerDelayLimit\":\"The new sequencer delay limit.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_amb\":\"The address of the AMB contract on Ethereum.\",\"_bridge\":\"The address of the arbitrum bridge contract on Ethereum.\",\"_veaInboxArbToGnosis\":\"The vea inbox on Arbitrum.\",\"_veaOutboxArbToGnosis\":\"The vea outbox on Gnosis Chain.\"}},\"executeSequencerDelayLimitDecreaseRequest()\":{\"details\":\"execute sequencerDelayLimitDecreaseRequest\"},\"route(uint256,bytes32,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"details\":\"Resolves any challenge of the optimistic claim for '_epoch'.\",\"params\":{\"_claim\":\"The claim associated with the epoch.\",\"_epoch\":\"The epoch to verify.\",\"_gasLimit\":\"The true batch gas limit for the epoch.\",\"_stateroot\":\"The true batch merkle root for the epoch.\"}},\"updatesequencerDelayLimit()\":{\"details\":\"Update the sequencerDelayLimit. If decreasing, a delayed request is created for later execution.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"route(uint256,bytes32,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))\":{\"notice\":\"Note: Access restricted to arbitrum canonical bridge.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitrumToGnosis/RouterArbToGnosis.sol\":\"RouterArbToGnosis\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/arbitrumToGnosis/RouterArbToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@shotaronowhere, @jaybuidl]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../canonical/gnosis-chain/IAMB.sol\\\";\\nimport \\\"../canonical/arbitrum/IBridge.sol\\\";\\nimport \\\"../canonical/arbitrum/IOutbox.sol\\\";\\nimport \\\"../canonical/arbitrum/ISequencerInbox.sol\\\";\\nimport \\\"../interfaces/routers/IRouterToGnosis.sol\\\";\\nimport \\\"../interfaces/outboxes/IVeaOutboxOnL1.sol\\\";\\nimport \\\"../interfaces/updaters/ISequencerDelayUpdatable.sol\\\";\\n\\n/// @dev Router from Arbitrum to Gnosis Chain.\\n/// Note: This contract is deployed on Ethereum.\\ncontract RouterArbToGnosis is IRouterToGnosis {\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n IBridge public immutable bridge; // The address of the Arbitrum bridge contract.\\n IAMB public immutable amb; // The address of the AMB contract on Ethereum.\\n address public immutable veaInboxArbToGnosis; // The address of the veaInbox on Arbitrum.\\n address public immutable veaOutboxArbToGnosis; // The address of the veaOutbox on Gnosis Chain.\\n\\n uint256 public sequencerDelayLimit; // This is MaxTimeVariation.delaySeconds from the arbitrum sequencer inbox, it is the maximum seconds the sequencer can backdate L2 txns relative to the L1 clock.\\n SequencerLimitDecreaseRequest public sequencerDelayLimitDecreaseRequest; // Decreasing the sequencerDelayLimit requires a delay to avoid griefing by sequencer, so we keep track of the request here.\\n\\n struct SequencerLimitDecreaseRequest {\\n uint256 requestedSequencerLimit;\\n uint256 timestamp;\\n }\\n\\n // ************************************* //\\n // * Events * //\\n // ************************************* //\\n\\n /// @dev Event emitted when a message is relayed to another Safe Bridge.\\n /// @param _epoch The epoch of the batch requested to send.\\n /// @param _ticketID The unique identifier provided by the underlying canonical bridge.\\n event Routed(uint256 indexed _epoch, bytes32 _ticketID);\\n\\n /// @dev This event indicates a cross-chain message was sent to inform the veaOutbox of the sequencer limit value\\n /// @param _ticketID The ticketID from the AMB of the cross-chain message.\\n event sequencerDelayLimitSent(bytes32 _ticketID);\\n\\n /// @dev This event indicates the sequencer limit updated.\\n /// @param _newSequencerDelayLimit The new sequencer delay limit.\\n event sequencerDelayLimitUpdated(uint256 _newSequencerDelayLimit);\\n\\n /// @dev This event indicates that a request to decrease the sequencer limit has been made.\\n /// @param _requestedSequencerDelayLimit The new sequencer limit requested.\\n event sequencerDelayLimitDecreaseRequested(uint256 _requestedSequencerDelayLimit);\\n\\n /// @dev Constructor.\\n /// @param _bridge The address of the arbitrum bridge contract on Ethereum.\\n /// @param _amb The address of the AMB contract on Ethereum.\\n /// @param _veaInboxArbToGnosis The vea inbox on Arbitrum.\\n /// @param _veaOutboxArbToGnosis The vea outbox on Gnosis Chain.\\n constructor(IBridge _bridge, IAMB _amb, address _veaInboxArbToGnosis, address _veaOutboxArbToGnosis) {\\n bridge = _bridge;\\n amb = _amb;\\n veaInboxArbToGnosis = _veaInboxArbToGnosis;\\n veaOutboxArbToGnosis = _veaOutboxArbToGnosis;\\n (, , sequencerDelayLimit, ) = ISequencerInbox(bridge.sequencerInbox()).maxTimeVariation();\\n }\\n\\n // ************************************* //\\n // * Parameter Updates * //\\n // ************************************* //\\n\\n /// @dev Update the sequencerDelayLimit. If decreasing, a delayed request is created for later execution.\\n function updatesequencerDelayLimit() public {\\n // the maximum asynchronous lag between the L2 and L1 clocks\\n (, , uint256 newsequencerDelayLimit, ) = ISequencerInbox(bridge.sequencerInbox()).maxTimeVariation();\\n\\n if (newsequencerDelayLimit > sequencerDelayLimit) {\\n // For sequencerDelayLimit / epochPeriod > timeoutEpochs, claims cannot be verified by the timeout period and the bridge will shutdown.\\n sequencerDelayLimit = newsequencerDelayLimit;\\n sendSequencerDelayLimit();\\n emit sequencerDelayLimitUpdated(newsequencerDelayLimit);\\n } else if (newsequencerDelayLimit < sequencerDelayLimit) {\\n require(\\n sequencerDelayLimitDecreaseRequest.timestamp == 0,\\n \\\"Sequencer limit decrease request already pending.\\\"\\n );\\n\\n sequencerDelayLimitDecreaseRequest = SequencerLimitDecreaseRequest({\\n requestedSequencerLimit: newsequencerDelayLimit,\\n timestamp: block.timestamp\\n });\\n emit sequencerDelayLimitDecreaseRequested(newsequencerDelayLimit);\\n }\\n }\\n\\n /// @dev execute sequencerDelayLimitDecreaseRequest\\n function executeSequencerDelayLimitDecreaseRequest() external {\\n require(sequencerDelayLimitDecreaseRequest.timestamp != 0, \\\"No pending sequencer limit decrease request.\\\");\\n require(\\n block.timestamp > sequencerDelayLimitDecreaseRequest.timestamp + sequencerDelayLimit,\\n \\\"Sequencer limit decrease request is still pending.\\\"\\n );\\n\\n uint256 requestedSequencerDelayLimit = sequencerDelayLimitDecreaseRequest.requestedSequencerLimit;\\n delete sequencerDelayLimitDecreaseRequest;\\n\\n (, , uint256 currentSequencerDelayLimit, ) = ISequencerInbox(bridge.sequencerInbox()).maxTimeVariation();\\n\\n // check the request is still consistent with the arbiturm bridge\\n if (currentSequencerDelayLimit == requestedSequencerDelayLimit) {\\n sequencerDelayLimit = requestedSequencerDelayLimit;\\n sendSequencerDelayLimit();\\n emit sequencerDelayLimitUpdated(requestedSequencerDelayLimit);\\n }\\n }\\n\\n /// @dev Send the sequencer delay limit.\\n function sendSequencerDelayLimit() internal {\\n bytes memory data = abi.encodeCall(\\n ISequencerDelayUpdatable.updateSequencerDelayLimit,\\n (sequencerDelayLimit, block.timestamp)\\n );\\n // Note: using maxGasPerTx here means the relaying txn on Gnosis will need to pass that (large) amount of gas, though almost all will be unused and refunded. This is preferred over hardcoding a gas limit.\\n bytes32 ticketID = amb.requireToPassMessage(veaOutboxArbToGnosis, data, amb.maxGasPerTx());\\n emit sequencerDelayLimitSent(ticketID);\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// Note: Access restricted to arbitrum canonical bridge.\\n /// @dev Resolves any challenge of the optimistic claim for '_epoch'.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateroot The true batch merkle root for the epoch.\\n /// @param _gasLimit The true batch gas limit for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function route(uint256 _epoch, bytes32 _stateroot, uint256 _gasLimit, Claim calldata _claim) external {\\n // Arbitrum -> Ethereum message sender authentication\\n // docs: https://developer.arbitrum.io/arbos/l2-to-l1-messaging/\\n // example: https://github.com/OffchainLabs/arbitrum-tutorials/blob/2c1b7d2db8f36efa496e35b561864c0f94123a5f/packages/greeter/contracts/ethereum/GreeterL1.sol#L50\\n // example: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/dfef6a68ee18dbd2e1f5a099061a3b8a0e404485/contracts/crosschain/arbitrum/LibArbitrumL1.sol#L34\\n // note: we use the bridge address as a source of truth for the activeOutbox address\\n\\n require(msg.sender == address(bridge), \\\"Not from bridge.\\\");\\n require(IOutbox(bridge.activeOutbox()).l2ToL1Sender() == veaInboxArbToGnosis, \\\"veaInbox only.\\\");\\n\\n // Ethereum -> Gnosis message passing with the AMB, the canonical Ethereum <-> Gnosis bridge.\\n // https://docs.tokenbridge.net/amb-bridge/development-of-a-cross-chain-application/how-to-develop-xchain-apps-by-amb#receive-a-method-call-from-the-amb-bridge\\n\\n bytes memory data = abi.encodeCall(IVeaOutboxOnL1.resolveDisputedClaim, (_epoch, _stateroot, _claim));\\n\\n uint256 maxGasPerTx = amb.maxGasPerTx();\\n uint256 gasLimitCapped = _gasLimit > maxGasPerTx ? maxGasPerTx : _gasLimit;\\n\\n bytes32 ticketID = amb.requireToPassMessage(veaOutboxArbToGnosis, data, gasLimitCapped);\\n emit Routed(_epoch, ticketID);\\n }\\n}\\n\",\"keccak256\":\"0x6aa5d93df7274bbed40b67e23656699aa9178ac1b64ea44b4e71cf9f2e630971\",\"license\":\"MIT\"},\"src/canonical/arbitrum/IBridge.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n// https://github.com/OffchainLabs/nitro-contracts/blob/08ac127e966fa87a4d5ba3d23cd3132b57701132/src/bridge/IBridge.sol\\n// proxy: https://etherscan.io/address/0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a\\n// implementation: https://etherscan.io/address/0x1066cecc8880948fe55e427e94f1ff221d626591#code\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\ninterface IBridge {\\n function activeOutbox() external view returns (address);\\n\\n function sequencerInbox() external view returns (address);\\n\\n function allowedDelayedInboxList(uint256) external returns (address);\\n}\\n\",\"keccak256\":\"0x0e7981b3e9b179caa0085d1ad900b19e88e29fec65923f41fde0315773fa9a3c\",\"license\":\"BUSL-1.1\"},\"src/canonical/arbitrum/IOutbox.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\n// https://github.com/OffchainLabs/nitro-contracts/blob/08ac127e966fa87a4d5ba3d23cd3132b57701132/src/bridge/IBridge.sol\\n// proxy: https://etherscan.io/address/0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840#code\\n// implementation: https://etherscan.io/address/0x0ea7372338a589e7f0b00e463a53aa464ef04e17#code\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\ninterface IOutbox {\\n /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account\\n /// When the return value is zero, that means this is a system message\\n /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies\\n function l2ToL1Sender() external view returns (address);\\n}\\n\",\"keccak256\":\"0x4d815542262727a2a3182332a7c16b0b1d33c031997de91c12e67e87e748b8ca\",\"license\":\"BUSL-1.1\"},\"src/canonical/arbitrum/ISequencerInbox.sol\":{\"content\":\"// Copyright 2021-2022, Offchain Labs, Inc.\\n// For license information, see https://github.com/nitro/blob/master/LICENSE\\n// SPDX-License-Identifier: BUSL-1.1\\n// https://github.com/OffchainLabs/nitro-contracts/blob/08ac127e966fa87a4d5ba3d23cd3132b57701132/src/bridge/ISequencerInbox.sol\\n// proxy: https://etherscan.io/address/0x1c479675ad559DC151F6Ec7ed3FbF8ceE79582B6#code\\n// implementation: https://etherscan.io/address/0xD03bFe2CE83632F4E618a97299cc91B1335BB2d9#code\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"./IBridge.sol\\\";\\n\\ninterface ISequencerInbox {\\n struct MaxTimeVariation {\\n uint256 delayBlocks;\\n uint256 futureBlocks;\\n uint256 delaySeconds;\\n uint256 futureSeconds;\\n }\\n\\n function maxTimeVariation() external view returns (uint256, uint256, uint256, uint256);\\n}\\n\",\"keccak256\":\"0xf972282dbad5eae92a352e0de6b588000bf4c58f45d90a30ef8863d5878313bc\",\"license\":\"BUSL-1.1\"},\"src/canonical/gnosis-chain/IAMB.sol\":{\"content\":\"// https://docs.gnosischain.com/bridges/tokenbridge/amb-bridge#gnosis\\n// https://github.com/omni/tokenbridge-contracts/blob/908a48107919d4ab127f9af07d44d47eac91547e/contracts/interfaces/IAMB.sol\\n// interface is pruned for relevant function stubs\\n\\npragma solidity 0.8.24;\\n\\ninterface IAMB {\\n function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);\\n\\n function maxGasPerTx() external view returns (uint256);\\n\\n function messageSender() external view returns (address);\\n\\n function messageSourceChainId() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xc94fccde4d2c5ede32856f84b8fd4275c353fce8a3f449a1d2a7246eafb7bc53\"},\"src/interfaces/outboxes/IVeaOutboxOnL1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../types/VeaClaim.sol\\\";\\n\\n/// @dev Interface of the Vea Outbox on L1 chains like Ethereum, Gnosis, Polygon POS where storage is expensive.\\ninterface IVeaOutboxOnL1 {\\n /// @dev Verifies and relays the message.\\n /// Note: Gateways expect first argument of message call to be the arbitrum message sender, used for authentication.\\n /// @param _proof The merkle proof to prove the message.\\n /// @param _msgId The zero based index of the message in the inbox.\\n /// @param _to The address to send the message to.\\n /// @param _message The message to relay.\\n function sendMessage(bytes32[] calldata _proof, uint64 _msgId, address _to, bytes calldata _message) external;\\n\\n /// @dev Resolves any challenge of the optimistic claim for 'epoch' using the canonical bridge.\\n /// Note: Access restricted to canonical bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _claim The claim associated with the epoch.\\n function resolveDisputedClaim(uint256 _epoch, bytes32 _stateRoot, Claim memory _claim) external;\\n}\\n\",\"keccak256\":\"0xf1d52e289e790088502b7909f11f47bc33ddd3fc545636b7fb29c01ed00d3ff3\",\"license\":\"MIT\"},\"src/interfaces/routers/IRouterToGnosis.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"../types/VeaClaim.sol\\\";\\n\\n/// @dev Interface of the Vea Router which routes messages to Gnosis through the AMB.\\n/// @dev eg. L2 on Ethereum -> Ethereum (L1) -> Gnosis (L1), the IRouterToL1 will be deployed on Ethereum (L1) routing messages to Gnosis (L1).\\ninterface IRouterToGnosis {\\n /// @dev Routes state root snapshots through intermediary chains to the final destination L1 chain.\\n /// Note: Access restricted to canonical sending-chain bridge.\\n /// @param _epoch The epoch to verify.\\n /// @param _stateRoot The true state root for the epoch.\\n /// @param _gasLimit The gas limit for the AMB message.\\n /// @param _claim The claim associated with the epoch.\\n function route(uint256 _epoch, bytes32 _stateRoot, uint256 _gasLimit, Claim memory _claim) external;\\n}\\n\",\"keccak256\":\"0x9d78c7872bd2bc3b206fc6d6dfa8f8b2dab4122b10bfe0d0ab1f76bec92613b6\",\"license\":\"MIT\"},\"src/interfaces/types/VeaClaim.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nenum Party {\\n None,\\n Claimer,\\n Challenger\\n}\\n\\nstruct Claim {\\n bytes32 stateRoot;\\n address claimer;\\n uint32 timestampClaimed;\\n uint32 timestampVerification;\\n uint32 blocknumberVerification;\\n Party honest;\\n address challenger;\\n}\\n\",\"keccak256\":\"0xfef781e359c97aebbe8dbfcb75edb7cb962139fd9ea538b8b89a3f2e13a05bfe\",\"license\":\"MIT\"},\"src/interfaces/updaters/ISequencerDelayUpdatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@jaybuidl, @shotaronowhere]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\n/// @dev Interface of a contract which is updatable, receiving parameter updates from an L1 contract through a cross-chain call.\\n/// @dev eg. Arbitrum (L2) -> Ethereum (L1) -> Gnosis (L1), the veaOutbox on Gnosis will be an ISequencerDelayUpdatable contract which receives updates from the router on Ethereum.\\ninterface ISequencerDelayUpdatable {\\n /// @dev Updates the sequencer limit.\\n /// Note: Access restricted to ensure the argument is passed from the Sequencer contract.\\n /// @param _newSequencerDelayLimit The delaySeconds from the MaxTimeVariation struct in the Arbitrum Sequencer contract.\\n /// @param _timestamp The timestamp of the message.\\n function updateSequencerDelayLimit(uint256 _newSequencerDelayLimit, uint256 _timestamp) external;\\n}\\n\",\"keccak256\":\"0x95ca3cc0dfaddee5c94a7e6b68bb9a90ce6d1b9cdd3b59241f5b1b5831ed89ec\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61010060405234801562000011575f80fd5b5060405162000fda38038062000fda833981016040819052620000349162000140565b6001600160a01b03808516608081905284821660a05283821660c05290821660e0526040805163ee35f32760e01b8152905163ee35f327916004808201926020929091908290030181865afa15801562000090573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620000b69190620001a5565b6001600160a01b031663ebea461d6040518163ffffffff1660e01b8152600401608060405180830381865afa158015620000f2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001189190620001ca565b505f5550620001fe945050505050565b6001600160a01b03811681146200013d575f80fd5b50565b5f805f806080858703121562000154575f80fd5b8451620001618162000128565b6020860151909450620001748162000128565b6040860151909350620001878162000128565b60608601519092506200019a8162000128565b939692955090935050565b5f60208284031215620001b6575f80fd5b8151620001c38162000128565b9392505050565b5f805f8060808587031215620001de575f80fd5b505082516020840151604085015160609095015191969095509092509050565b60805160a05160c05160e051610d63620002775f395f818161010a0152818161089301526109e001525f8181610131015261063701525f818160cb015281816107e30152818161086401526109b701525f8181610173015281816102b9015281816103d9015281816105d501526106610152610d635ff3fe608060405234801561000f575f80fd5b5060043610610090575f3560e01c80638c5f173f116100635780638c5f173f1461012c57806390784ae814610153578063b1126dad1461015b578063e78cea921461016e578063e813a75514610195575f80fd5b8063051d1970146100945780630c63fa84146100bc5780631062b39a146100c65780632fa70aa714610105575b5f80fd5b6001546002546100a2919082565b604080519283526020830191909152015b60405180910390f35b6100c46101ab565b005b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b3565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6100c46103d6565b6100c4610169366004610adc565b6105ca565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b61019d5f5481565b6040519081526020016100b3565b6002545f036102165760405162461bcd60e51b815260206004820152602c60248201527f4e6f2070656e64696e672073657175656e636572206c696d697420646563726560448201526b30b9b2903932b8bab2b9ba1760a11b60648201526084015b60405180910390fd5b5f546002546102259190610b22565b421161028e5760405162461bcd60e51b815260206004820152603260248201527f53657175656e636572206c696d697420646563726561736520726571756573746044820152711034b99039ba34b636103832b73234b7339760711b606482015260840161020d565b600180545f9182905560028290556040805163ee35f32760e01b815290519192916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163ee35f3279160048083019260209291908290030181865afa158015610302573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103269190610b5b565b6001600160a01b031663ebea461d6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610361573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103859190610b7d565b50925050508181036103d2575f82905561039d610958565b6040518281527f611c2e4a78552f908fb0eb2cc503efc1f947cde8574277ab3b0f10fdd510258b906020015b60405180910390a15b5050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ee35f3276040518163ffffffff1660e01b8152600401602060405180830381865afa158015610433573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104579190610b5b565b6001600160a01b031663ebea461d6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610492573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b69190610b7d565b50925050505f54811115610506575f8190556104d0610958565b6040518181527f611c2e4a78552f908fb0eb2cc503efc1f947cde8574277ab3b0f10fdd510258b9060200160405180910390a150565b5f548110156105c757600254156105795760405162461bcd60e51b815260206004820152603160248201527f53657175656e636572206c696d697420646563726561736520726571756573746044820152701030b63932b0b23c903832b73234b7339760791b606482015260840161020d565b604080518082018252828152426020918201819052600184905560025590518281527fa552b382e128c9d0732f01f09502c18999aec5dce0ed78c5af0ea2274ce9bd7d910160405180910390a15b50565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106355760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b604482015260640161020d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab5d89436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106df9190610b5b565b6001600160a01b03166380648b026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561071a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073e9190610b5b565b6001600160a01b0316146107855760405162461bcd60e51b815260206004820152600e60248201526d3b32b0a4b73137bc1037b7363c9760911b604482015260640161020d565b5f84848360405160240161079b93929190610c01565b60408051601f19818403018152918152602080830180516001600160e01b0316630f0adca560e01b179052815163e5789d0360e01b815291519293505f926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e5789d039260048083019391928290030181865afa158015610829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084d9190610cb3565b90505f81851161085d578461085f565b815b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dc8601b37f000000000000000000000000000000000000000000000000000000000000000086856040518463ffffffff1660e01b81526004016108d293929190610cca565b6020604051808303815f875af11580156108ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109129190610cb3565b9050877f888a9bef5168f83425ebe9503cb6d29081cf58d52c60126f8a85a22c9d9935548260405161094691815260200190565b60405180910390a25050505050505050565b5f8054604051602481019190915242604482015260640160408051601f19818403018152918152602080830180516001600160e01b0316632c19251960e01b179052815163e5789d0360e01b815291519293505f926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263dc8601b3927f0000000000000000000000000000000000000000000000000000000000000000928792869263e5789d03926004808401938290030181865afa158015610a27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a4b9190610cb3565b6040518463ffffffff1660e01b8152600401610a6993929190610cca565b6020604051808303815f875af1158015610a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa99190610cb3565b90507fb38aa59aca3a7ad85f6c314d96b54cae25fc75a92e95994a90c63ae93c63d687816040516103c991815260200190565b5f805f80848603610140811215610af1575f80fd5b85359450602086013593506040860135925060e0605f1982011215610b14575f80fd5b509295919450926060019150565b80820180821115610b4157634e487b7160e01b5f52601160045260245ffd5b92915050565b6001600160a01b03811681146105c7575f80fd5b5f60208284031215610b6b575f80fd5b8151610b7681610b47565b9392505050565b5f805f8060808587031215610b90575f80fd5b505082516020840151604085015160609095015191969095509092509050565b8035610bbb81610b47565b919050565b803563ffffffff81168114610bbb575f80fd5b803560038110610bbb575f80fd5b60038110610bfd57634e487b7160e01b5f52602160045260245ffd5b9052565b838152602080820184905282356040830152610120820190830135610c2581610b47565b6001600160a01b03166060830152610c3f60408401610bc0565b63ffffffff808216608085015280610c5960608701610bc0565b1660a085015280610c6c60808701610bc0565b1660c08501525050610c8060a08401610bd3565b610c8d60e0840182610be1565b50610c9a60c08401610bb0565b6001600160a01b03811661010084015250949350505050565b5f60208284031215610cc3575f80fd5b5051919050565b60018060a01b03841681525f60206060602084015284518060608501525f5b81811015610d0557868101830151858201608001528201610ce9565b505f608082860101526080601f19601f8301168501019250505082604083015294935050505056fea2646970667358221220dca82595a68b87899c3f877b03eb1d1b4281744168df20f3df3de470ffead3f164736f6c63430008180033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610090575f3560e01c80638c5f173f116100635780638c5f173f1461012c57806390784ae814610153578063b1126dad1461015b578063e78cea921461016e578063e813a75514610195575f80fd5b8063051d1970146100945780630c63fa84146100bc5780631062b39a146100c65780632fa70aa714610105575b5f80fd5b6001546002546100a2919082565b604080519283526020830191909152015b60405180910390f35b6100c46101ab565b005b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b3565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b6100c46103d6565b6100c4610169366004610adc565b6105ca565b6100ed7f000000000000000000000000000000000000000000000000000000000000000081565b61019d5f5481565b6040519081526020016100b3565b6002545f036102165760405162461bcd60e51b815260206004820152602c60248201527f4e6f2070656e64696e672073657175656e636572206c696d697420646563726560448201526b30b9b2903932b8bab2b9ba1760a11b60648201526084015b60405180910390fd5b5f546002546102259190610b22565b421161028e5760405162461bcd60e51b815260206004820152603260248201527f53657175656e636572206c696d697420646563726561736520726571756573746044820152711034b99039ba34b636103832b73234b7339760711b606482015260840161020d565b600180545f9182905560028290556040805163ee35f32760e01b815290519192916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163ee35f3279160048083019260209291908290030181865afa158015610302573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103269190610b5b565b6001600160a01b031663ebea461d6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610361573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103859190610b7d565b50925050508181036103d2575f82905561039d610958565b6040518281527f611c2e4a78552f908fb0eb2cc503efc1f947cde8574277ab3b0f10fdd510258b906020015b60405180910390a15b5050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ee35f3276040518163ffffffff1660e01b8152600401602060405180830381865afa158015610433573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104579190610b5b565b6001600160a01b031663ebea461d6040518163ffffffff1660e01b8152600401608060405180830381865afa158015610492573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b69190610b7d565b50925050505f54811115610506575f8190556104d0610958565b6040518181527f611c2e4a78552f908fb0eb2cc503efc1f947cde8574277ab3b0f10fdd510258b9060200160405180910390a150565b5f548110156105c757600254156105795760405162461bcd60e51b815260206004820152603160248201527f53657175656e636572206c696d697420646563726561736520726571756573746044820152701030b63932b0b23c903832b73234b7339760791b606482015260840161020d565b604080518082018252828152426020918201819052600184905560025590518281527fa552b382e128c9d0732f01f09502c18999aec5dce0ed78c5af0ea2274ce9bd7d910160405180910390a15b50565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106355760405162461bcd60e51b815260206004820152601060248201526f2737ba10333937b690313934b233b29760811b604482015260640161020d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab5d89436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106df9190610b5b565b6001600160a01b03166380648b026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561071a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073e9190610b5b565b6001600160a01b0316146107855760405162461bcd60e51b815260206004820152600e60248201526d3b32b0a4b73137bc1037b7363c9760911b604482015260640161020d565b5f84848360405160240161079b93929190610c01565b60408051601f19818403018152918152602080830180516001600160e01b0316630f0adca560e01b179052815163e5789d0360e01b815291519293505f926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e5789d039260048083019391928290030181865afa158015610829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084d9190610cb3565b90505f81851161085d578461085f565b815b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dc8601b37f000000000000000000000000000000000000000000000000000000000000000086856040518463ffffffff1660e01b81526004016108d293929190610cca565b6020604051808303815f875af11580156108ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109129190610cb3565b9050877f888a9bef5168f83425ebe9503cb6d29081cf58d52c60126f8a85a22c9d9935548260405161094691815260200190565b60405180910390a25050505050505050565b5f8054604051602481019190915242604482015260640160408051601f19818403018152918152602080830180516001600160e01b0316632c19251960e01b179052815163e5789d0360e01b815291519293505f926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263dc8601b3927f0000000000000000000000000000000000000000000000000000000000000000928792869263e5789d03926004808401938290030181865afa158015610a27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a4b9190610cb3565b6040518463ffffffff1660e01b8152600401610a6993929190610cca565b6020604051808303815f875af1158015610a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa99190610cb3565b90507fb38aa59aca3a7ad85f6c314d96b54cae25fc75a92e95994a90c63ae93c63d687816040516103c991815260200190565b5f805f80848603610140811215610af1575f80fd5b85359450602086013593506040860135925060e0605f1982011215610b14575f80fd5b509295919450926060019150565b80820180821115610b4157634e487b7160e01b5f52601160045260245ffd5b92915050565b6001600160a01b03811681146105c7575f80fd5b5f60208284031215610b6b575f80fd5b8151610b7681610b47565b9392505050565b5f805f8060808587031215610b90575f80fd5b505082516020840151604085015160609095015191969095509092509050565b8035610bbb81610b47565b919050565b803563ffffffff81168114610bbb575f80fd5b803560038110610bbb575f80fd5b60038110610bfd57634e487b7160e01b5f52602160045260245ffd5b9052565b838152602080820184905282356040830152610120820190830135610c2581610b47565b6001600160a01b03166060830152610c3f60408401610bc0565b63ffffffff808216608085015280610c5960608701610bc0565b1660a085015280610c6c60808701610bc0565b1660c08501525050610c8060a08401610bd3565b610c8d60e0840182610be1565b50610c9a60c08401610bb0565b6001600160a01b03811661010084015250949350505050565b5f60208284031215610cc3575f80fd5b5051919050565b60018060a01b03841681525f60206060602084015284518060608501525f5b81811015610d0557868101830151858201608001528201610ce9565b505f608082860101526080601f19601f8301168501019250505082604083015294935050505056fea2646970667358221220dca82595a68b87899c3f877b03eb1d1b4281744168df20f3df3de470ffead3f164736f6c63430008180033", + "devdoc": { + "details": "Router from Arbitrum to Gnosis Chain. Note: This contract is deployed on Ethereum.", + "events": { + "Routed(uint256,bytes32)": { + "details": "Event emitted when a message is relayed to another Safe Bridge.", + "params": { + "_epoch": "The epoch of the batch requested to send.", + "_ticketID": "The unique identifier provided by the underlying canonical bridge." + } + }, + "sequencerDelayLimitDecreaseRequested(uint256)": { + "details": "This event indicates that a request to decrease the sequencer limit has been made.", + "params": { + "_requestedSequencerDelayLimit": "The new sequencer limit requested." + } + }, + "sequencerDelayLimitSent(bytes32)": { + "details": "This event indicates a cross-chain message was sent to inform the veaOutbox of the sequencer limit value", + "params": { + "_ticketID": "The ticketID from the AMB of the cross-chain message." + } + }, + "sequencerDelayLimitUpdated(uint256)": { + "details": "This event indicates the sequencer limit updated.", + "params": { + "_newSequencerDelayLimit": "The new sequencer delay limit." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "details": "Constructor.", + "params": { + "_amb": "The address of the AMB contract on Ethereum.", + "_bridge": "The address of the arbitrum bridge contract on Ethereum.", + "_veaInboxArbToGnosis": "The vea inbox on Arbitrum.", + "_veaOutboxArbToGnosis": "The vea outbox on Gnosis Chain." + } + }, + "executeSequencerDelayLimitDecreaseRequest()": { + "details": "execute sequencerDelayLimitDecreaseRequest" + }, + "route(uint256,bytes32,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))": { + "details": "Resolves any challenge of the optimistic claim for '_epoch'.", + "params": { + "_claim": "The claim associated with the epoch.", + "_epoch": "The epoch to verify.", + "_gasLimit": "The true batch gas limit for the epoch.", + "_stateroot": "The true batch merkle root for the epoch." + } + }, + "updatesequencerDelayLimit()": { + "details": "Update the sequencerDelayLimit. If decreasing, a delayed request is created for later execution." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "route(uint256,bytes32,uint256,(bytes32,address,uint32,uint32,uint32,uint8,address))": { + "notice": "Note: Access restricted to arbitrum canonical bridge." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 23, + "contract": "src/arbitrumToGnosis/RouterArbToGnosis.sol:RouterArbToGnosis", + "label": "sequencerDelayLimit", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 26, + "contract": "src/arbitrumToGnosis/RouterArbToGnosis.sol:RouterArbToGnosis", + "label": "sequencerDelayLimitDecreaseRequest", + "offset": 0, + "slot": "1", + "type": "t_struct(SequencerLimitDecreaseRequest)31_storage" + } + ], + "types": { + "t_struct(SequencerLimitDecreaseRequest)31_storage": { + "encoding": "inplace", + "label": "struct RouterArbToGnosis.SequencerLimitDecreaseRequest", + "members": [ + { + "astId": 28, + "contract": "src/arbitrumToGnosis/RouterArbToGnosis.sol:RouterArbToGnosis", + "label": "requestedSequencerLimit", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 30, + "contract": "src/arbitrumToGnosis/RouterArbToGnosis.sol:RouterArbToGnosis", + "label": "timestamp", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} From f11393d0c84a72376abcd35ae465255970a9cc60 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Mon, 14 Oct 2024 16:02:24 +0530 Subject: [PATCH 3/7] feat(validtor-bot): function to find latest l2 batch on l1 --- .../VeaInboxArbToGnosisTestnet.json | 2 +- .../chiado/VeaOutboxArbToGnosisTestnet.json | 2 +- relayer-cli/package.json | 3 + validator-cli/package.json | 6 +- .../src/ArbToEth/watcherArbToGnosis.ts | 225 ++++++++++++++++-- 5 files changed, 210 insertions(+), 28 deletions(-) diff --git a/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json b/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json index 3e914f1f..5d99b675 100644 --- a/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json +++ b/contracts/deployments/arbitrumSepolia/VeaInboxArbToGnosisTestnet.json @@ -1,5 +1,5 @@ { - "address": "0x72c7d51647cBeaca636d0E20A66ca2F682da3539", + "address": "0x854374483572FFcD4d0225290346279d0718240b", "abi": [ { "inputs": [ diff --git a/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json b/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json index 194539ba..531b47c3 100644 --- a/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json +++ b/contracts/deployments/chiado/VeaOutboxArbToGnosisTestnet.json @@ -1,5 +1,5 @@ { - "address": "0xa3C6608539693C13434e4E29c9aB53Dd029178BE", + "address": "0x2f1788F7B74e01c4C85578748290467A5f063B0b", "abi": [ { "inputs": [ diff --git a/relayer-cli/package.json b/relayer-cli/package.json index 3944cb86..dc6d8296 100644 --- a/relayer-cli/package.json +++ b/relayer-cli/package.json @@ -21,5 +21,8 @@ "typescript": "^4.9.5", "web3": "^1.10.4", "web3-batched-send": "^1.0.3" + }, + "devDependencies": { + "ts-node": "^10.9.2" } } diff --git a/validator-cli/package.json b/validator-cli/package.json index 664e339a..8d2a4f05 100644 --- a/validator-cli/package.json +++ b/validator-cli/package.json @@ -13,7 +13,8 @@ "start": "npx ts-node ./src/ArbToEth/watcher.ts", "start-chiado-devnet": "npx ts-node ./src/devnet/arbToChiado/happyPath.ts", "start-sepolia-devnet": "npx ts-node ./src/devnet/arbToSepolia/happyPath.ts", - "start-sepolia-testnet": "npx ts-node ./src/ArbToEth/watcherArbToEth.ts" + "start-sepolia-testnet": "npx ts-node ./src/ArbToEth/watcherArbToEth.ts", + "start-chaido-testnet": "npx ts-node ./src/ArbToEth/watcherArbToGnosis.ts" }, "dependencies": { "@arbitrum/sdk": "4.0.1", @@ -25,5 +26,8 @@ "typescript": "^4.9.5", "web3": "^1.10.4", "web3-batched-send": "^1.0.3" + }, + "devDependencies": { + "ts-node": "^10.9.2" } } diff --git a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts index 2f254d5d..82c0b4be 100644 --- a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts +++ b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts @@ -5,19 +5,20 @@ import { getWalletRPC, } from "../utils/ethers"; import { JsonRpcProvider } from "@ethersproject/providers"; -import { getL2Network } from "@arbitrum/sdk"; +import { getArbitrumNetwork } from "@arbitrum/sdk"; import { NODE_INTERFACE_ADDRESS } from "@arbitrum/sdk/dist/lib/dataEntities/constants"; import { NodeInterface__factory } from "@arbitrum/sdk/dist/lib/abi/factories/NodeInterface__factory"; import { SequencerInbox__factory } from "@arbitrum/sdk/dist/lib/abi/factories/SequencerInbox__factory"; import { BigNumber, ContractTransaction, constants } from "ethers"; import { Block, Log, TransactionReceipt, BlockWithTransactions } from "@ethersproject/abstract-provider"; import { SequencerInbox } from "@arbitrum/sdk/dist/lib/abi/SequencerInbox"; +import { NodeInterface } from "@arbitrum/sdk/dist/lib/abi/NodeInterface"; require("dotenv").config(); -interface ChallengeTxn { - timeSent: string; - timeRamp: number; +interface ChallengeProgess { + challengeTnxHash: string; + sentSnapshotTnxHash?: string; } // https://github.com/prysmaticlabs/prysm/blob/493905ee9e33a64293b66823e69704f012b39627/config/params/mainnet_config.go#L103 @@ -52,7 +53,7 @@ const watch = async () => { )) as BigNumber; // get Arb sequencer params - const l2Network = await getL2Network(providerArb); + const l2Network = await getArbitrumNetwork(providerArb); const sequencer = SequencerInbox__factory.connect(l2Network.ethBridge.sequencerInbox, providerEth); const maxDelaySeconds = ( (await retryOperation(() => sequencer.maxTimeVariation(), 1000, 10))[1] as BigNumber @@ -115,7 +116,8 @@ const watch = async () => { .fill(veaEpochOutboxWacthLowerBound) .map((el, i) => el + i); // epoch => (minChallengePeriodDeadline, maxPriorityFeePerGas, maxFeePerGas) - const challengeTxnHashes = new Map(); + + const challenges = new Map(); console.log( "cold start: checking past claim history from epoch " + @@ -346,11 +348,20 @@ const watch = async () => { } } else { console.log("claim " + veaEpochOutboxCheck + " is already challenged"); + console.log("challenge is finalized"); if (logChallenges[0].blockNumber < blockFinalizedGnosis.number) { - veaEpochOutboxCheckClaimsRangeArray.splice(index, 1); - index--; - // the challenge is finalized, no further action needed - console.log("challenge is finalized"); + if (logChallenges[0].topics[1] === watcherAddress) { + console.log("challenge by bot detected, calling sendSnaphot"); + const txnReceipt = (await retryOperation( + () => providerArb.getTransactionReceipt(challenges.get(index)), + 10, + 1000 + )) as TransactionReceipt; + if (!txnReceipt) { + console.log("challenge txn " + challengeTxnHashes.get(index) + " not mined yet"); + continue; + } + } continue; } else { console.log( @@ -360,14 +371,15 @@ const watch = async () => { continue; } - if (challengeTxnHashes.has(index)) { + if (challenges.has(index)) { + const challengeProgess = challenges.get(index); const txnReceipt = (await retryOperation( - () => providerGnosis.getTransactionReceipt(challengeTxnHashes.get(index)), + () => providerGnosis.getTransactionReceipt(challengeProgess.challengeTnxHash), 10, 1000 )) as TransactionReceipt; if (!txnReceipt) { - console.log("challenge txn " + challengeTxnHashes.get(index) + " not mined yet"); + console.log("challenge txn " + challengeProgess.challengeTnxHash + " not mined yet"); continue; } const blockNumber = txnReceipt.blockNumber; @@ -378,7 +390,6 @@ const watch = async () => { )) as Block; if (challengeBlock.number < blockFinalizedGnosis.number) { veaEpochOutboxCheckClaimsRangeArray.splice(index, 1); - challengeTxnHashes.get(index); index--; // the challenge is finalized, no further action needed console.log("challenge is finalized"); @@ -464,13 +475,146 @@ const watch = async () => { 10 )) as ContractTransaction; - challengeTxnHashes.set(index, txnChallenge.hash); + challenges.set(index, { challengeTnxHash: txnChallenge.hash }); console.log( "challenging claim for epoch " + veaEpochOutboxCheck + " with txn hash " + txnChallenge.hash ); } } } + if (challenges.has(index)) { + const challengeProgress = challenges.get(index); + const txnReceipt = (await retryOperation( + () => providerGnosis.getTransactionReceipt(challenges.get(index).challengeTnxHash), + 10, + 1000 + )) as TransactionReceipt; + if (!txnReceipt) { + console.log("challenge txn " + challenges.get(index).challengeTnxHash + " not mined yet"); + continue; + } + const blockNumber = txnReceipt.blockNumber; + const challengeBlock = (await retryOperation( + () => providerGnosis.getBlock(blockNumber), + 1000, + 10 + )) as Block; + if (challengeBlock.number < blockFinalizedGnosis.number) { + if (!challengeProgress.sentSnapshotTnxHash) { + console.log("Sending snapshot for challenged claim in epoch " + veaEpochOutboxCheck); + try { + const sendSnapshotTx = await veaInbox.sendSnapshot( + veaEpochOutboxCheck, + 30000000, // gas limit, you might want to adjust this + { + stateRoot: claimSnapshot, + claimer: claim.claimer, + timestampClaimed: claim.timestampClaimed, + timestampVerification: claim.timestampVerification, + blocknumberVerification: claim.blocknumberVerification, + honest: claim.honest, + challenger: watcherAddress, + }, + { gasLimit: 30000000 } + ); + console.log("Sent snapshot with transaction hash: " + sendSnapshotTx.hash); + challenges.set(index, { + ...challengeProgress, + sentSnapshotTnxHash: sendSnapshotTx.hash, + }); + } catch (error) { + console.error("Failed to send snapshot: ", error); + } + } else { + console.log("Snapshot already sent for challenge in epoch " + veaEpochOutboxCheck); + } + } + } else { + let gasEstimate: BigNumber; + try { + gasEstimate = (await retryOperation( + () => veaOutbox.estimateGas.challenge(veaEpochOutboxCheck, claim), + 1000, + 10 + )) as BigNumber; + } catch (e) { + console.log(e); + console.log("Challenge failed to estimate gas, skipping."); + const logChallenges = (await retryOperation( + () => + providerGnosis.getLogs({ + address: veaOutboxAddress, + topics: veaOutbox.filters.Challenged(veaEpochOutboxCheck, null).topics, + fromBlock: blockNumberOutboxLowerBound, + toBlock: blockTagGnosis, + }), + 1000, + 10 + )) as Log[]; + + // if already challenged, no action needed + + // if not challenged, keep checking all claim struct variables + if (logChallenges.length == 0) { + } + } + // deposit / 2 is the profit for challengers + // the initial challenge txn is roughly 1/3 of the cost of completing the challenge process. + const maxFeePerGasProfitable = deposit.div(gasEstimate.mul(3 * 2)); + + // there's practically very little MEV on gnosis + // priority fee should just be a small amount to get the txn included in a block + + let maxPriorityFeePerGas = BigNumber.from("3000000000"); // 3 gwei + + // if claim is in min challenge period, we can use a higher priority fee + // this ensures the txn is always competitive during the censorship test (min challenge period) + if (claim.timestampClaimed < timeLocal - sequencerDelayLimit - epochPeriod) { + try { + const blockPendingGnosis = (await retryOperation( + () => providerGnosis.getBlockWithTransactions("pending"), + 1000, + 10 + )) as BlockWithTransactions; + // can't access actual gas used from pending block, consider all txns equal weight + let maxPriorityFeePerGasAvg = BigNumber.from("0"); + for (const txn of blockPendingGnosis.transactions) { + maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.add(txn.maxPriorityFeePerGas); + } + maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.div(blockPendingGnosis.transactions.length); + if (maxPriorityFeePerGas.lt(maxPriorityFeePerGasAvg)) { + maxPriorityFeePerGas = maxPriorityFeePerGasAvg; + } + } catch (e) {} + + // there's almost no MEV on gnosis + // will update this default value if there is more MEV on gnosis in the future + if (maxPriorityFeePerGas.lt(BigNumber.from("100000000000"))) { + maxPriorityFeePerGas = BigNumber.from("100000000000"); // 100 gwei + } + + if (maxPriorityFeePerGas.gt(maxFeePerGasProfitable)) { + maxPriorityFeePerGas = maxFeePerGasProfitable; + } + } + + if (!inactive) { + const txnChallenge = (await retryOperation( + () => + veaOutbox.challenge(veaEpochOutboxCheck, claim, { + maxFeePerGas: maxFeePerGasProfitable, + maxPriorityFeePerGas: maxPriorityFeePerGas, + }), + 1000, + 10 + )) as ContractTransaction; + + challenges.set(index, { challengeTnxHash: txnChallenge.hash }); + console.log( + "challenging claim for epoch " + veaEpochOutboxCheck + " with txn hash " + txnChallenge.hash + ); + } + } } } else { console.log("claim hash matches snapshot for epoch " + veaEpochOutboxCheck); @@ -522,7 +666,6 @@ const getBlocksAndCheckFinality = async ( const blockFinalizedArb = (await retryOperation(() => ArbProvider.getBlock("finalized"), 1000, 10)) as Block; const blockFinalizedEth = (await retryOperation(() => EthProvider.getBlock("finalized"), 1000, 10)) as Block; const blockFinalizedGnosis = (await retryOperation(() => GnosisProvider.getBlock("finalized"), 1000, 10)) as Block; - const finalityBuffer = 300; // 5 minutes, allows for network delays const maxFinalityTimeSecondsEth = (slotsPerEpochEth * 3 - 1) * secondsPerSlotEth; // finalization after 2 justified epochs const maxFinalityTimeSecondsGnosis = (slotsPerEpochGnosis * 3 - 1) * secondsPerSlotGnosis; // finalization after 2 justified epochs @@ -530,9 +673,12 @@ const getBlocksAndCheckFinality = async ( let finalityIssueFlagArb = false; let finalityIssueFlagEth = false; let finalityIssueFlagGnosis = false; - // check latest arb block to see if there are any sequencer issues let blockLatestArb = (await retryOperation(() => ArbProvider.getBlock("latest"), 1000, 10)) as Block; + let blockoldArb = (await retryOperation(() => ArbProvider.getBlock(blockLatestArb.number - 100), 1000, 10)) as Block; + const arbAverageBlockTime = (blockLatestArb.timestamp - blockoldArb.timestamp) / 100; + const maxDelayInSeconds = 7 * 24 * 60 * 60; // 7 days in seconds + const fromBlockArbFinalized = blockFinalizedArb.number - Math.ceil(maxDelayInSeconds / arbAverageBlockTime); // to performantly query the sequencerInbox's SequencerBatchDelivered event on Eth, we limit the block range // we use the heuristic that. delta blocknumber <= delta timestamp / secondsPerSlot @@ -553,6 +699,7 @@ const getBlocksAndCheckFinality = async ( sequencer, blockFinalizedArb, fromBlockEthFinalized, + fromBlockArbFinalized, false ); @@ -570,6 +717,7 @@ const getBlocksAndCheckFinality = async ( sequencer, blockLatestArb, fromBlockEthFinalized, + fromBlockArbFinalized, true ); @@ -635,10 +783,10 @@ const ArbBlockToL1Block = async ( sequencer: SequencerInbox, L2Block: Block, fromBlockEth: number, + fromArbBlock: number, fallbackLatest: boolean ): Promise<[Block, number] | undefined> => { const nodeInterface = NodeInterface__factory.connect(NODE_INTERFACE_ADDRESS, L2Provider); - let latestL2batchOnEth: number; let latestL2BlockNumberOnEth: number; let result = (await nodeInterface.functions @@ -651,16 +799,20 @@ const ArbBlockToL1Block = async ( const errMsg = JSON.parse(JSON.parse(JSON.stringify(e)).error.body).error.message; if (fallbackLatest) { - latestL2batchOnEth = parseInt(errMsg.split(" published in batch ")[1]); - latestL2BlockNumberOnEth = parseInt(errMsg.split(" is after latest on-chain block ")[1]); - if (Number.isNaN(latestL2batchOnEth)) { - console.error(errMsg); - } } })) as [BigNumber] & { batch: BigNumber }; - if (!result && !fallbackLatest) return undefined; - + if (!result) { + if (!fallbackLatest) { + return undefined; + } else { + [latestL2batchOnEth, latestL2BlockNumberOnEth] = await findLatestL2BatchAndBlock( + nodeInterface, + fromArbBlock, + L2Block.number + ); + } + } const batch = result?.batch?.toNumber() ?? latestL2batchOnEth; const L2BlockNumberFallback = latestL2BlockNumberOnEth ?? L2Block.number; /** @@ -682,6 +834,29 @@ const ArbBlockToL1Block = async ( return [L1Block, L2BlockNumberFallback]; }; +const findLatestL2BatchAndBlock = async ( + nodeInterface: NodeInterface, + fromArbBlock: number, + latestBlockNumber: number +): Promise<[number, number]> => { + let low = fromArbBlock; + let high = latestBlockNumber; + + while (low <= high) { + const mid = Math.floor((low + high) / 2); + try { + (await nodeInterface.functions.findBatchContainingBlock(mid, { blockTag: "latest" })) as any; + low = mid + 1; + } catch (e) { + high = mid - 1; + } + } + if (high < low) return [undefined, undefined]; + // high is now the latest L2 block number that has a corresponding batch on L1 + const result = (await nodeInterface.functions.findBatchContainingBlock(high, { blockTag: "latest" })) as any; + return [result.batch.toNumber(), high]; +}; + (async () => { await watch(); })(); From 4af6323f25dc122ff466a2a95feced9783892acd Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Mon, 18 Nov 2024 17:31:49 +0700 Subject: [PATCH 4/7] feat(validator-bot): complete unhappy path execution --- contracts/src/canonical/gnosis-chain/IAMB.sol | 7 + validator-cli/.env.dist | 10 +- .../src/ArbToEth/watcherArbToGnosis.ts | 995 +++++++++++------- validator-cli/src/utils/ethers.ts | 11 + yarn.lock | 2 + 5 files changed, 642 insertions(+), 383 deletions(-) diff --git a/contracts/src/canonical/gnosis-chain/IAMB.sol b/contracts/src/canonical/gnosis-chain/IAMB.sol index b6c326a3..836c8801 100644 --- a/contracts/src/canonical/gnosis-chain/IAMB.sol +++ b/contracts/src/canonical/gnosis-chain/IAMB.sol @@ -12,4 +12,11 @@ interface IAMB { function messageSender() external view returns (address); function messageSourceChainId() external view returns (bytes32); + + event AffirmationCompleted( + address indexed sender, + address indexed executor, + bytes32 indexed messageId, + bool status + ); } diff --git a/validator-cli/.env.dist b/validator-cli/.env.dist index 1f909c5b..6fae1c80 100644 --- a/validator-cli/.env.dist +++ b/validator-cli/.env.dist @@ -3,6 +3,8 @@ PRIVATE_KEY= # Devnet RPCs RPC_CHIADO=https://rpc.chiadochain.net RPC_ARB_SEPOLIA=https://sepolia-rollup.arbitrum.io/rpc +RPC_GNOSIS=https://rpc.chiadochain.net +RPC_ARB=https://sepolia-rollup.arbitrum.io/rpc RPC_SEPOLIA= # Testnet or Mainnet RPCs @@ -16,9 +18,13 @@ VEAOUTBOX_ARB_TO_ETH_ADDRESS=0x209BFdC6B7c66b63A8382196Ba3d06619d0F12c9 # Devnet Addresses VEAINBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 -VEAINBOX_ARBSEPOLIA_TO_CHIADO_ADDRESS=0xAb53e341121448Ae259Da8fa17f216Cb0e21199C VEAOUTBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 -VEAOUTBOX_ARBSEPOLIA_TO_CHIADO_ADDRESS=0xAb53e341121448Ae259Da8fa17f216Cb0e21199C + +#For arbToGnosis bridge +VEAINBOX_ARB_TO_GNOSIS_ADDRESS=0x854374483572FFcD4d0225290346279d0718240b +VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS=0x2f1788F7B74e01c4C85578748290467A5f063B0b +VEAROUTER_ARB_TO_GNOSIS_ADDRESS=0x5BE03fDE7794Bc188416ba16932510Ed1277b193 +GNO_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d TRANSACTION_BATCHER_CONTRACT_ADDRESS_SEPOLIA=0xe7953da7751063d0a41ba727c32c762d3523ade8 TRANSACTION_BATCHER_CONTRACT_ADDRESS_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73 \ No newline at end of file diff --git a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts index 82c0b4be..9f6b702f 100644 --- a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts +++ b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts @@ -3,24 +3,79 @@ import { getVeaInboxArbToGnosisProvider, getWETHProvider, getWalletRPC, + getVeaRouterArbToGnosisProvider, + getAMBProvider, } from "../utils/ethers"; import { JsonRpcProvider } from "@ethersproject/providers"; -import { getArbitrumNetwork } from "@arbitrum/sdk"; +import { ChildToParentMessageStatus, ChildTransactionReceipt, getArbitrumNetwork } from "@arbitrum/sdk"; import { NODE_INTERFACE_ADDRESS } from "@arbitrum/sdk/dist/lib/dataEntities/constants"; import { NodeInterface__factory } from "@arbitrum/sdk/dist/lib/abi/factories/NodeInterface__factory"; import { SequencerInbox__factory } from "@arbitrum/sdk/dist/lib/abi/factories/SequencerInbox__factory"; -import { BigNumber, ContractTransaction, constants } from "ethers"; -import { Block, Log, TransactionReceipt, BlockWithTransactions } from "@ethersproject/abstract-provider"; +import { BigNumber, ContractTransaction, Wallet, constants } from "ethers"; +import { Block, Log } from "@ethersproject/abstract-provider"; import { SequencerInbox } from "@arbitrum/sdk/dist/lib/abi/SequencerInbox"; import { NodeInterface } from "@arbitrum/sdk/dist/lib/abi/NodeInterface"; +import { + IAMB, + RouterArbToGnosis, + VeaInboxArbToGnosis, + VeaOutboxArbToGnosis, +} from "@kleros/vea-contracts/typechain-types"; +import { ClaimStruct } from "@kleros/vea-contracts/typechain-types/arbitrumToEth/VeaInboxArbToEth"; +import messageExecutor from "../utils/arbMsgExecutor"; require("dotenv").config(); -interface ChallengeProgess { - challengeTnxHash: string; - sentSnapshotTnxHash?: string; +interface ChallengeProgress { + challenge: { + txHash: string; + timestamp: number; + finalized: boolean; + status: "mined" | "pending" | "none"; + }; + snapshot: { + txHash: string; + timestamp: number; + finalized: boolean; + status: "mined" | "pending" | "none"; + }; + + L2toL1Message: { + status: ChildToParentMessageStatus; + }; + route: { + txHash: string; + timestamp: number; + finalized: boolean; + status: "mined" | "pending" | "none"; + }; + AMB: { + ambMessageId: string; + txHash: string; + timestamp: number; + finalized: boolean; + status: "mined" | "pending" | "none"; + }; + withdrawal: { + txHash: string; + timestamp: number; + finalized: boolean; + status: "mined" | "pending" | "none"; + }; + status: + | "Unclaimed" + | "Claimed" + | "Challenged" + | "ChallengePending" + | "SnapshotSent" + | "SnapshotPending" + | "Routed" + | "RoutePending" + | "AMBMessageSent" + | "AMBMessagePending" + | "WithdrawalPending" + | "Completed"; } - // https://github.com/prysmaticlabs/prysm/blob/493905ee9e33a64293b66823e69704f012b39627/config/params/mainnet_config.go#L103 const slotsPerEpochEth = 32; const secondsPerSlotEth = 12; @@ -30,6 +85,9 @@ const secondsPerSlotGnosis = 5; const veaOutboxAddress = process.env.VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS; const veaInboxAddress = process.env.VEAINBOX_ARB_TO_GNOSIS_ADDRESS; +const veaRouterAddress = process.env.VEAROUTER_ARB_TO_GNOSIS_ADDRESS; + +const challenges = new Map(); const watch = async () => { // connect to RPCs @@ -42,6 +100,8 @@ const watch = async () => { // use typechain generated contract factories for vea outbox and inbox const veaOutbox = getVeaOutboxArbToGnosisProvider(veaOutboxAddress, process.env.PRIVATE_KEY, providerGnosis); const veaInbox = getVeaInboxArbToGnosisProvider(veaInboxAddress, process.env.PRIVATE_KEY, providerArb); + const veaRouter = getVeaRouterArbToGnosisProvider(veaRouterAddress, process.env.PRIVATE_KEY, providerEth); + const amb = getAMBProvider(process.env.PRIVATE_KEY, providerGnosis); const wethAddress = (await retryOperation(() => veaOutbox.weth(), 1000, 10)) as string; const weth = getWETHProvider(wethAddress, process.env.PRIVATE_KEY, providerGnosis); @@ -97,7 +157,7 @@ const watch = async () => { )) as Block; const coldStartBacklog = 7 * 24 * 60 * 60; // when starting the watcher, specify an extra backlog to check - + const sevenDaysInSeconds = 7 * 24 * 60 * 60; // When Sequencer is malicious, even when L1 is finalized, L2 state might be unknown for up to sequencerDelayLimit + epochPeriod. const L2SyncPeriod = sequencerDelayLimit + epochPeriod; // When we start the watcher, we need to go back far enough to check for claims which may have been pending L2 state finalization. @@ -117,8 +177,6 @@ const watch = async () => { .map((el, i) => el + i); // epoch => (minChallengePeriodDeadline, maxPriorityFeePerGas, maxFeePerGas) - const challenges = new Map(); - console.log( "cold start: checking past claim history from epoch " + veaEpochOutboxCheckClaimsRangeArray[0] + @@ -153,6 +211,7 @@ const watch = async () => { const veaEpochOutboxClaimableNowOld = veaEpochOutboxClaimableNow; veaEpochOutboxClaimableNow = Math.floor(timeGnosis / epochPeriod) - 1; + // TODO: sometimes veaEpochOutboxClaimableNow is 1 epoch behind veaEpochOutboxClaimableNowOld const veaEpochsOutboxClaimableNew: number[] = new Array(veaEpochOutboxClaimableNow - veaEpochOutboxClaimableNowOld) .fill(veaEpochOutboxClaimableNowOld + 1) .map((el, i) => el + i); @@ -178,7 +237,7 @@ const watch = async () => { )) as string; // no claim - if (claimHash == "0x0000000000000000000000000000000000000000000000000000000000000000") { + if (claimHash == constants.HashZero) { // if epoch is not claimable anymore, remove from array if (veaEpochOutboxCheck <= veaEpochOutboxClaimableFinalized) { console.log( @@ -188,6 +247,7 @@ const watch = async () => { ); veaEpochOutboxCheckClaimsRangeArray.splice(index, 1); index--; + if (challenges.has(index)) challenges.delete(index); continue; } else { console.log( @@ -245,374 +305,90 @@ const watch = async () => { if (!finalityIssueFlagEth && veaEpochInboxFinalized < veaEpochOutboxCheck) { // note as long as L1 does not have finalization probelms, sequencer could still be malfunctioning console.log("L2 snapshot is not yet finalized, waiting for finalization to determine challengable status"); - } else { - console.log("claim " + veaEpochOutboxCheck + " is challengable"); - - const timestampClaimed = ( - (await retryOperation(() => providerGnosis.getBlock(logClaimed.blockNumber), 1000, 10)) as Block - ).timestamp; - - var claim = { - stateRoot: logClaimed.data, - claimer: "0x" + logClaimed.topics[1].substring(26), - timestampClaimed: timestampClaimed, - timestampVerification: 0, - blocknumberVerification: 0, - honest: 0, - challenger: constants.AddressZero, - }; - - const claimHashCalculated = (await retryOperation( - () => veaOutbox.hashClaim(claim, { blockTag: blockTagGnosis }), + continue; + } + console.log("claim " + veaEpochOutboxCheck + " is challengable"); + let claim = await getClaimForEpoch( + veaEpochOutboxCheck, + veaOutbox, + providerGnosis, + blockNumberOutboxLowerBound + ); + if (claim === null) { + console.error("Error finding claim for epoch " + veaEpochOutboxCheck); + continue; + } + console.log(veaEpochOutboxCheck, "claim found ", { claim }); + const previousProgress = challenges.get(index) || ({} as any); + let challengeProgress = await reconstructChallengeProgress( + veaEpochOutboxCheck, + veaOutbox, + veaInbox, + veaRouter, + providerGnosis, + providerArb, + providerEth, + blockNumberOutboxLowerBound, + amb, + previousProgress + ); + challenges.set(index, challengeProgress); + console.log( + "challenge progess for epoch " + veaEpochOutboxCheck + " is " + JSON.stringify(challengeProgress) + ); + //TODO : check profitablity of the whole dispute resolution + //const profitablity = await calculateDisputeResolutionProfitability(veaEpochOutboxCheck,claim,veaOutbox,veaInbox,providerGnosis,providerArb,providerEth); + if (claim.challenger == constants.AddressZero) { + if (challengeProgress?.challenge.status == "pending") continue; + const txnChallenge = (await retryOperation( + () => veaOutbox.challenge(veaEpochOutboxCheck, claim), 1000, 10 - )) as string; - if (claimHashCalculated != claimHash) { - // either claim is already challenged - // or claim is in verification or verified - - const logChallenges = (await retryOperation( - () => - providerGnosis.getLogs({ - address: veaOutboxAddress, - topics: veaOutbox.filters.Challenged(veaEpochOutboxCheck, null).topics, - fromBlock: blockNumberOutboxLowerBound, - toBlock: "latest", - }), - 1000, - 10 - )) as Log[]; - - // if already challenged, no action needed - - // if not challenged, keep checking all claim struct variables - if (logChallenges.length == 0) { - // verification is possible - if (claim.timestampClaimed > timeLocal - sequencerDelayLimit - epochPeriod) { - const logVerficiationStarted = (await retryOperation( - () => - providerGnosis.getLogs({ - address: veaOutboxAddress, - topics: veaOutbox.filters.VerificationStarted(veaEpochOutboxCheck).topics, - fromBlock: blockNumberOutboxLowerBound, - toBlock: "latest", - }), - 1000, - 10 - )) as Log[]; - - if (logVerficiationStarted.length > 1) { - let blockNumberVerificationMax = 0; - for (const log of logVerficiationStarted) { - if (log.blockNumber > blockNumberVerificationMax) { - blockNumberVerificationMax = log.blockNumber; - } - } - const timestampVerification = ( - (await retryOperation( - () => providerGnosis.getBlock(blockNumberVerificationMax), - 1000, - 10 - )) as Block - ).timestamp; - - claim.timestampVerification = timestampVerification; - claim.blocknumberVerification = - logVerficiationStarted[logVerficiationStarted.length - 1].blockNumber; - - const claimHashCalculated = (await retryOperation( - () => veaOutbox.hashClaim(claim, { blockTag: "latest" }), - 1000, - 10 - )) as string; - if (claimHashCalculated != claimHash) { - claim.honest = 1; - const claimHashCalculated = (await retryOperation( - () => veaOutbox.hashClaim(claim, { blockTag: "latest" }), - 1000, - 10 - )) as string; - if (claimHashCalculated != claimHash) { - console.error( - "Invalid claim hash calculated for epoch " + - veaEpochOutboxCheck + - " claim " + - claimHashCalculated + - " expected " + - claimHash - ); - continue; - } - } - } - } - } else { - console.log("claim " + veaEpochOutboxCheck + " is already challenged"); - console.log("challenge is finalized"); - if (logChallenges[0].blockNumber < blockFinalizedGnosis.number) { - if (logChallenges[0].topics[1] === watcherAddress) { - console.log("challenge by bot detected, calling sendSnaphot"); - const txnReceipt = (await retryOperation( - () => providerArb.getTransactionReceipt(challenges.get(index)), - 10, - 1000 - )) as TransactionReceipt; - if (!txnReceipt) { - console.log("challenge txn " + challengeTxnHashes.get(index) + " not mined yet"); - continue; - } - } - continue; - } else { - console.log( - "challenge is not finalized yet, waiting for finalization to remove epoch from watch list." - ); - } - continue; - } - - if (challenges.has(index)) { - const challengeProgess = challenges.get(index); - const txnReceipt = (await retryOperation( - () => providerGnosis.getTransactionReceipt(challengeProgess.challengeTnxHash), - 10, - 1000 - )) as TransactionReceipt; - if (!txnReceipt) { - console.log("challenge txn " + challengeProgess.challengeTnxHash + " not mined yet"); - continue; - } - const blockNumber = txnReceipt.blockNumber; - const challengeBlock = (await retryOperation( - () => providerGnosis.getBlock(blockNumber), + )) as ContractTransaction; + console.log("Epoch " + veaEpochOutboxCheck + " challenged with txn " + txnChallenge.hash); + continue; + } + if (claim?.challenger === watcherAddress) { + if (challengeProgress.challenge.finalized) { + console.log(veaEpochInboxFinalized, "A finalized challenge made by bot detected"); + if (!challengeProgress?.snapshot.txHash) { + const txnSendSnapshot = (await retryOperation( + () => veaInbox.sendSnapshot(veaEpochOutboxCheck, 200000, claim), // execute transaction required around 142000 gas so we set gas limit to 200000 1000, 10 - )) as Block; - if (challengeBlock.number < blockFinalizedGnosis.number) { - veaEpochOutboxCheckClaimsRangeArray.splice(index, 1); - index--; - // the challenge is finalized, no further action needed - console.log("challenge is finalized"); - continue; - } - } else { - let gasEstimate: BigNumber; - try { - gasEstimate = (await retryOperation( - () => veaOutbox.estimateGas.challenge(veaEpochOutboxCheck, claim), - 1000, - 10 - )) as BigNumber; - } catch (e) { - console.log(e); - console.log("Challenge failed to estimate gas, skipping."); - const logChallenges = (await retryOperation( - () => - providerGnosis.getLogs({ - address: veaOutboxAddress, - topics: veaOutbox.filters.Challenged(veaEpochOutboxCheck, null).topics, - fromBlock: blockNumberOutboxLowerBound, - toBlock: blockTagGnosis, - }), - 1000, - 10 - )) as Log[]; - - // if already challenged, no action needed - - // if not challenged, keep checking all claim struct variables - if (logChallenges.length == 0) { - } - } - // deposit / 2 is the profit for challengers - // the initial challenge txn is roughly 1/3 of the cost of completing the challenge process. - const maxFeePerGasProfitable = deposit.div(gasEstimate.mul(3 * 2)); - - // there's practically very little MEV on gnosis - // priority fee should just be a small amount to get the txn included in a block - - let maxPriorityFeePerGas = BigNumber.from("3000000000"); // 3 gwei - - // if claim is in min challenge period, we can use a higher priority fee - // this ensures the txn is always competitive during the censorship test (min challenge period) - if (claim.timestampClaimed < timeLocal - sequencerDelayLimit - epochPeriod) { - try { - const blockPendingGnosis = (await retryOperation( - () => providerGnosis.getBlockWithTransactions("pending"), - 1000, - 10 - )) as BlockWithTransactions; - // can't access actual gas used from pending block, consider all txns equal weight - let maxPriorityFeePerGasAvg = BigNumber.from("0"); - for (const txn of blockPendingGnosis.transactions) { - maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.add(txn.maxPriorityFeePerGas); - } - maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.div(blockPendingGnosis.transactions.length); - if (maxPriorityFeePerGas.lt(maxPriorityFeePerGasAvg)) { - maxPriorityFeePerGas = maxPriorityFeePerGasAvg; - } - } catch (e) {} - - // there's almost no MEV on gnosis - // will update this default value if there is more MEV on gnosis in the future - if (maxPriorityFeePerGas.lt(BigNumber.from("100000000000"))) { - maxPriorityFeePerGas = BigNumber.from("100000000000"); // 100 gwei - } - - if (maxPriorityFeePerGas.gt(maxFeePerGasProfitable)) { - maxPriorityFeePerGas = maxFeePerGasProfitable; - } - } - - if (!inactive) { - const txnChallenge = (await retryOperation( - () => - veaOutbox.challenge(veaEpochOutboxCheck, claim, { - maxFeePerGas: maxFeePerGasProfitable, - maxPriorityFeePerGas: maxPriorityFeePerGas, - }), - 1000, - 10 - )) as ContractTransaction; - - challenges.set(index, { challengeTnxHash: txnChallenge.hash }); - console.log( - "challenging claim for epoch " + veaEpochOutboxCheck + " with txn hash " + txnChallenge.hash - ); - } + )) as ContractTransaction; + console.log("Epoch " + veaEpochOutboxCheck + " sendSnapshot called with txn " + txnSendSnapshot.hash); } } - if (challenges.has(index)) { - const challengeProgress = challenges.get(index); - const txnReceipt = (await retryOperation( - () => providerGnosis.getTransactionReceipt(challenges.get(index).challengeTnxHash), - 10, - 1000 - )) as TransactionReceipt; - if (!txnReceipt) { - console.log("challenge txn " + challenges.get(index).challengeTnxHash + " not mined yet"); - continue; - } - const blockNumber = txnReceipt.blockNumber; - const challengeBlock = (await retryOperation( - () => providerGnosis.getBlock(blockNumber), + if ( + challengeProgress.snapshot.finalized && + challengeProgress.snapshot.timestamp <= Math.floor(Date.now() / 1000) - sevenDaysInSeconds + ) { + if (challengeProgress.L2toL1Message.status === ChildToParentMessageStatus.CONFIRMED) { + console.log("epoch " + veaEpochOutboxCheck + " L2 to L1 transaction ready to be executed"); + await messageExecutor(challengeProgress.snapshot.txHash, process.env.RPC_ARB, process.env.RPC_ETH); + } else if (challengeProgress.L2toL1Message.status === ChildToParentMessageStatus.UNCONFIRMED) + console.log("epoch " + veaEpochOutboxCheck + " L2 to L1 transaction waiting for confirmation"); + } + if (challengeProgress.route.finalized && challengeProgress.AMB.finalized) { + const txnWithdrawalDeposit = (await retryOperation( + () => veaOutbox.withdrawChallengeDeposit(veaEpochOutboxCheck, claim), 1000, 10 - )) as Block; - if (challengeBlock.number < blockFinalizedGnosis.number) { - if (!challengeProgress.sentSnapshotTnxHash) { - console.log("Sending snapshot for challenged claim in epoch " + veaEpochOutboxCheck); - try { - const sendSnapshotTx = await veaInbox.sendSnapshot( - veaEpochOutboxCheck, - 30000000, // gas limit, you might want to adjust this - { - stateRoot: claimSnapshot, - claimer: claim.claimer, - timestampClaimed: claim.timestampClaimed, - timestampVerification: claim.timestampVerification, - blocknumberVerification: claim.blocknumberVerification, - honest: claim.honest, - challenger: watcherAddress, - }, - { gasLimit: 30000000 } - ); - console.log("Sent snapshot with transaction hash: " + sendSnapshotTx.hash); - challenges.set(index, { - ...challengeProgress, - sentSnapshotTnxHash: sendSnapshotTx.hash, - }); - } catch (error) { - console.error("Failed to send snapshot: ", error); - } - } else { - console.log("Snapshot already sent for challenge in epoch " + veaEpochOutboxCheck); - } - } - } else { - let gasEstimate: BigNumber; - try { - gasEstimate = (await retryOperation( - () => veaOutbox.estimateGas.challenge(veaEpochOutboxCheck, claim), - 1000, - 10 - )) as BigNumber; - } catch (e) { - console.log(e); - console.log("Challenge failed to estimate gas, skipping."); - const logChallenges = (await retryOperation( - () => - providerGnosis.getLogs({ - address: veaOutboxAddress, - topics: veaOutbox.filters.Challenged(veaEpochOutboxCheck, null).topics, - fromBlock: blockNumberOutboxLowerBound, - toBlock: blockTagGnosis, - }), - 1000, - 10 - )) as Log[]; - - // if already challenged, no action needed - - // if not challenged, keep checking all claim struct variables - if (logChallenges.length == 0) { - } - } - // deposit / 2 is the profit for challengers - // the initial challenge txn is roughly 1/3 of the cost of completing the challenge process. - const maxFeePerGasProfitable = deposit.div(gasEstimate.mul(3 * 2)); - - // there's practically very little MEV on gnosis - // priority fee should just be a small amount to get the txn included in a block - - let maxPriorityFeePerGas = BigNumber.from("3000000000"); // 3 gwei - - // if claim is in min challenge period, we can use a higher priority fee - // this ensures the txn is always competitive during the censorship test (min challenge period) - if (claim.timestampClaimed < timeLocal - sequencerDelayLimit - epochPeriod) { - try { - const blockPendingGnosis = (await retryOperation( - () => providerGnosis.getBlockWithTransactions("pending"), - 1000, - 10 - )) as BlockWithTransactions; - // can't access actual gas used from pending block, consider all txns equal weight - let maxPriorityFeePerGasAvg = BigNumber.from("0"); - for (const txn of blockPendingGnosis.transactions) { - maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.add(txn.maxPriorityFeePerGas); - } - maxPriorityFeePerGasAvg = maxPriorityFeePerGasAvg.div(blockPendingGnosis.transactions.length); - if (maxPriorityFeePerGas.lt(maxPriorityFeePerGasAvg)) { - maxPriorityFeePerGas = maxPriorityFeePerGasAvg; - } - } catch (e) {} - - // there's almost no MEV on gnosis - // will update this default value if there is more MEV on gnosis in the future - if (maxPriorityFeePerGas.lt(BigNumber.from("100000000000"))) { - maxPriorityFeePerGas = BigNumber.from("100000000000"); // 100 gwei - } - - if (maxPriorityFeePerGas.gt(maxFeePerGasProfitable)) { - maxPriorityFeePerGas = maxFeePerGasProfitable; - } - } - - if (!inactive) { - const txnChallenge = (await retryOperation( - () => - veaOutbox.challenge(veaEpochOutboxCheck, claim, { - maxFeePerGas: maxFeePerGasProfitable, - maxPriorityFeePerGas: maxPriorityFeePerGas, - }), - 1000, - 10 - )) as ContractTransaction; + )) as ContractTransaction; - challenges.set(index, { challengeTnxHash: txnChallenge.hash }); + if (txnWithdrawalDeposit.hash) { console.log( - "challenging claim for epoch " + veaEpochOutboxCheck + " with txn hash " + txnChallenge.hash + "Epoch " + veaEpochOutboxCheck + " Withdrawal called with txn " + txnWithdrawalDeposit.hash ); + challengeProgress.withdrawal = { + status: "pending", + txHash: txnWithdrawalDeposit.hash, + timestamp: 0, + finalized: false, + }; + challengeProgress.status = "WithdrawalPending"; + challenges.set(index, challengeProgress); } } } @@ -629,7 +405,6 @@ const watch = async () => { } } } - // 3 second delay for potential block and attestation propogation console.log("waiting 3 seconds for potential block and attestation propogation. . ."); await wait(1000 * 3); @@ -791,16 +566,7 @@ const ArbBlockToL1Block = async ( let latestL2BlockNumberOnEth: number; let result = (await nodeInterface.functions .findBatchContainingBlock(L2Block.number, { blockTag: "latest" }) - .catch((e) => { - // if L2 block is ahead of latest L2 batch on L1, we get an error - // catch the error and parse it to get the latest L2 batch on L1 - - // https://github.com/OffchainLabs/nitro/blob/af87ba29bc34c27bd4d85b3066a1cc3a759bab66/nodeInterface/NodeInterface.go#L544 - const errMsg = JSON.parse(JSON.parse(JSON.stringify(e)).error.body).error.message; - - if (fallbackLatest) { - } - })) as [BigNumber] & { batch: BigNumber }; + .catch((e) => {})) as [BigNumber] & { batch: BigNumber }; if (!result) { if (!fallbackLatest) { @@ -853,11 +619,478 @@ const findLatestL2BatchAndBlock = async ( } if (high < low) return [undefined, undefined]; // high is now the latest L2 block number that has a corresponding batch on L1 - const result = (await nodeInterface.functions.findBatchContainingBlock(high, { blockTag: "latest" })) as any; + const result = (await nodeInterface.functions + .findBatchContainingBlock(high, { blockTag: "latest" }) + .catch(console.error)) as any; return [result.batch.toNumber(), high]; }; +async function getClaimForEpoch( + epoch: number, + veaOutbox: VeaOutboxArbToGnosis, + providerGnosis: JsonRpcProvider, + blockNumberOutboxLowerBound: number +) { + // Get the claim hash from the contract + const claimHash = (await retryOperation(() => veaOutbox.claimHashes(epoch), 1000, 10)) as any; + + // If there's no claim, return null + if (claimHash === constants.HashZero) { + return null; + } + + // Query for the Claimed event + const claimedFilter = veaOutbox.filters.Claimed(null, epoch, null); + const claimedEvents = (await retryOperation( + () => + providerGnosis.getLogs({ + ...claimedFilter, + fromBlock: blockNumberOutboxLowerBound, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + // If we can't find the event, something is wrong + if (claimedEvents.length === 0) { + console.error(`No Claimed event found for epoch ${epoch}`); + return null; + } + + // Parse the event data + const event = veaOutbox.interface.parseLog(claimedEvents[0]); + + const timestampClaimed = ( + (await retryOperation(() => providerGnosis.getBlock(claimedEvents[0].blockNumber), 1000, 10)) as any + ).timestamp; + // Reconstruct the basic claim struct + let claim = { + stateRoot: event.args._stateRoot, + claimer: event.args._claimer, + timestampClaimed: timestampClaimed, + timestampVerification: 0, + blocknumberVerification: 0, + honest: 0, // 0 for None, 1 for Claimer, 2 for Challenger + challenger: constants.AddressZero, + }; + let other = {} as any; + let calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + if (calculatedHash == claimHash) return claim; + + // Check for Challenged event + const challengedFilter = veaOutbox.filters.Challenged(epoch, null); + const challengedEvents = (await retryOperation( + () => + providerGnosis.getLogs({ + ...challengedFilter, + fromBlock: claimedEvents[0].blockNumber, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (challengedEvents.length > 0) { + const challengeEvent = veaOutbox.interface.parseLog(challengedEvents[challengedEvents.length - 1]); + claim.challenger = challengeEvent.args._challenger; + other.challengeBlock = challengedEvents[0].blockNumber; + } + + calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + if (calculatedHash == claimHash) return claim; + + // Check for VerificationStarted event + const verificationStartedFilter = veaOutbox.filters.VerificationStarted(epoch); + + const verificationStartedEvents = (await retryOperation( + () => + providerGnosis.getLogs({ + ...verificationStartedFilter, + fromBlock: blockNumberOutboxLowerBound, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (verificationStartedEvents.length > 0) { + const verificationBlock = await providerGnosis.getBlock( + verificationStartedEvents[verificationStartedEvents.length - 1].blockNumber + ); + claim.timestampVerification = verificationBlock.timestamp; + claim.blocknumberVerification = verificationBlock.number; + claim.challenger = constants.AddressZero; + } + + calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + if (calculatedHash == claimHash) return claim; + + const [claimBridgerHonest, claimChallengerHonest] = await Promise.all([ + retryOperation(() => veaOutbox.hashClaim({ ...claim, honest: 1 }), 1000, 10) as any, + retryOperation(() => veaOutbox.hashClaim({ ...claim, honest: 2 }), 1000, 10) as any, + ]); + + if (claimBridgerHonest === claimHash) return { ...claim, honest: 1 }; + if (claimChallengerHonest === claimHash) return { ...claim, honest: 2 }; + return null; +} + +async function calculateDisputeResolutionProfitability( + epoch: number, + claim: ClaimStruct, + veaOutbox: VeaOutboxArbToGnosis, + veaInbox: VeaInboxArbToGnosis, + providerGnosis: JsonRpcProvider, + providerArb: JsonRpcProvider, + providerEth: JsonRpcProvider +): Promise<{ profitable: boolean; estimatedProfit: BigNumber }> { + try { + const deposit = (await retryOperation(() => veaOutbox.deposit(), 1000, 10)) as BigNumber; + const totalReward = deposit; + const minimumProfit = totalReward.mul(40).div(100); // 40% of total reward + let maximumAllowableCost = totalReward.sub(minimumProfit); + let totalCost = BigNumber.from(0); + + // 1. Costs on Gnosis Chain + const gnosisGasEstimate = await veaOutbox.estimateGas.challenge(epoch, claim); + + const gnosisGasPrice = await providerGnosis.getGasPrice(); + const gnosisCost = gnosisGasEstimate.mul(gnosisGasPrice); + + if (gnosisCost.gt(maximumAllowableCost)) { + return { profitable: false, estimatedProfit: constants.Zero }; + } + totalCost = totalCost.add(gnosisCost); + maximumAllowableCost = maximumAllowableCost.sub(gnosisCost); + + const l2Network = await getArbitrumNetwork(providerArb); + + const arbGasEstimate = (await retryOperation( + () => veaInbox.estimateGas.sendSnapshot(epoch, 200000, claim), + 1000, + 10 + )) as BigNumber; + + const arbGasPrice = (await retryOperation(() => providerArb.getGasPrice(), 1000, 10)) as BigNumber; + const arbCost = arbGasEstimate.mul(arbGasPrice); + + if (arbCost.gt(maximumAllowableCost)) { + return { profitable: false, estimatedProfit: constants.Zero }; + } + totalCost = totalCost.add(arbCost); + maximumAllowableCost = maximumAllowableCost.sub(arbCost); + + // 3. Costs on Ethereum (for Arbitrum -> Ethereum message) + //TODO : L2 to L1 message execution gas cost + } catch (error) { + console.error("Error calculating profitability:", error); + return { profitable: false, estimatedProfit: constants.Zero }; + } +} + +function needsRetry(current: ChallengeProgress, previous: ChallengeProgress | undefined): boolean { + if (!previous) return false; + + // Check if any pending transaction has been pending too long + const MAX_PENDING_TIME = 3600; // 1 hour + const now = Math.floor(Date.now() / 1000); + + // Helper to check if a state needs retry + const stateNeedsRetry = (state) => state.status === "pending" && now - state.timestamp > MAX_PENDING_TIME; + + return ( + stateNeedsRetry(current.challenge) || + stateNeedsRetry(current.snapshot) || + stateNeedsRetry(current.route) || + stateNeedsRetry(current.AMB) + ); +} + +async function reconstructChallengeProgress( + epoch: number, + veaOutbox: VeaOutboxArbToGnosis, + veaInbox: VeaInboxArbToGnosis, + router: RouterArbToGnosis, + providerGnosis: JsonRpcProvider, + providerArb: JsonRpcProvider, + providerEth: JsonRpcProvider, + blockNumberOutboxLowerBound: number, + amb: IAMB, + previousProgress?: ChallengeProgress +): Promise { + const emptyState = { + txHash: "", + timestamp: 0, + blockNumber: 0, + finalized: false, + status: "none" as const, + }; + + const challengeProgress: ChallengeProgress = { + challenge: { ...emptyState }, + snapshot: { ...emptyState }, + route: { ...emptyState }, + AMB: { + ...emptyState, + ambMessageId: "", + }, + withdrawal: { ...emptyState }, + L2toL1Message: { + status: ChildToParentMessageStatus.UNCONFIRMED, + }, + status: "Unclaimed", + }; + + // Get current and finalized blocks for all chains with retry + const [gnosisFinalized, gnosisLatest] = await Promise.all([ + retryOperation(() => providerGnosis.getBlock("finalized"), 1000, 10) as any, + retryOperation(() => providerGnosis.getBlock("latest"), 1000, 10) as any, + ]); + + // Check for claim with retry + const claimedFilter = veaOutbox.filters.Claimed(null, epoch, null); + const claimedLogs = (await retryOperation( + () => + providerGnosis.getLogs({ + ...claimedFilter, + fromBlock: blockNumberOutboxLowerBound, + toBlock: gnosisFinalized.number, + }), + 1000, + 10 + )) as any; + + if (claimedLogs.length === 0) { + return challengeProgress; + } + + challengeProgress.status = "Claimed"; + + // Check challenge status with retry + if (previousProgress?.challenge?.status === "pending") { + const tx = (await retryOperation( + () => providerGnosis.getTransaction(previousProgress.challenge.txHash), + 1000, + 10 + )) as any; + if (tx) { + if (!tx.blockNumber) { + return previousProgress; + } + } + } + + const challengedFilter = veaOutbox.filters.Challenged(epoch, null); + const challengeLogs = (await retryOperation( + () => + providerGnosis.getLogs({ + ...challengedFilter, + fromBlock: claimedLogs[0].blockNumber, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (challengeLogs.length === 0) { + return challengeProgress; + } + + const challengeBlock = (await retryOperation( + () => providerGnosis.getBlock(challengeLogs[0].blockNumber), + 1000, + 10 + )) as any; + + challengeProgress.challenge = { + txHash: challengeLogs[0].transactionHash, + timestamp: challengeBlock.timestamp, + finalized: challengeLogs[0].blockNumber <= gnosisFinalized.number, + status: "mined", + }; + challengeProgress.status = "Challenged"; + + // Check snapshot status on Arbitrum with retry + if (previousProgress?.snapshot?.status === "pending") { + const tx = (await retryOperation( + () => providerArb.getTransaction(previousProgress.snapshot.txHash), + 1000, + 10 + )) as any; + if (tx && !tx.blockNumber) { + return { + ...challengeProgress, + status: "SnapshotPending", + }; + } + } + + // Get Arbitrum blocks with retry + const [arbFinalized, arbLatest] = await Promise.all([ + retryOperation(() => providerArb.getBlock("finalized"), 1000, 10) as any, + retryOperation(() => providerArb.getBlock("latest"), 1000, 10) as any, + ]); + + const averageArbitrumBlocktime = 0.26; + const estimatedArbBlocks = Math.ceil((arbLatest.timestamp - challengeBlock.timestamp) / averageArbitrumBlocktime); + + const snapshotSentFilter = veaInbox.filters.SnapshotSent(epoch, null); + const snapshotLogs = (await retryOperation( + () => + providerArb.getLogs({ + ...snapshotSentFilter, + fromBlock: arbLatest.number - estimatedArbBlocks, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (snapshotLogs.length === 0) { + return challengeProgress; + } + + const snapshotBlock = (await retryOperation( + () => providerArb.getBlock(snapshotLogs[0].blockNumber), + 1000, + 10 + )) as any; + + challengeProgress.snapshot = { + txHash: snapshotLogs[0].transactionHash, + timestamp: snapshotBlock.timestamp, + finalized: snapshotLogs[0].blockNumber <= arbFinalized.number, + status: "mined", + }; + challengeProgress.status = "SnapshotSent"; + + const snapshotTxnReceipt = (await retryOperation( + () => providerArb.getTransactionReceipt(challengeProgress?.snapshot.txHash), + 1000, + 10 + )) as any; + + const messageReceipt = new ChildTransactionReceipt(snapshotTxnReceipt); + const parentSigner = new Wallet(process.env.PRIVATE_KEY, providerEth); + const messages = await messageReceipt.getChildToParentMessages(parentSigner); + const childToParentMessage = messages[0]; + if (!childToParentMessage) { + throw new Error("No child-to-parent messages found"); + } + const status = await childToParentMessage.status(providerArb); + + challengeProgress.L2toL1Message.status = status; + + // Check route status on Ethereum with retry + if (previousProgress?.route?.status === "pending") { + const tx = (await retryOperation(() => providerEth.getTransaction(previousProgress.route.txHash), 1000, 10)) as any; + if (tx && !tx.blockNumber) { + return { + ...challengeProgress, + status: "RoutePending", + }; + } + } + + // Get Ethereum blocks with retry + const [ethFinalized, ethLatest] = (await Promise.all([ + retryOperation(() => providerEth.getBlock("finalized"), 1000, 10), + retryOperation(() => providerEth.getBlock("latest"), 1000, 10), + ])) as any; + + const estimatedEthBlocks = Math.ceil((ethLatest.timestamp - snapshotBlock.timestamp) / secondsPerSlotEth); + + const routedFilter = router.filters.Routed(epoch, null); + const routedLogs = (await retryOperation( + () => + providerEth.getLogs({ + ...routedFilter, + fromBlock: ethLatest.number - estimatedEthBlocks, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (routedLogs.length === 0) { + return challengeProgress; + } + + const routeBlock = (await retryOperation(() => providerEth.getBlock(routedLogs[0].blockNumber), 1000, 10)) as any; + + challengeProgress.route = { + txHash: routedLogs[0].transactionHash, + timestamp: routeBlock.timestamp, + finalized: routedLogs[0].blockNumber <= ethFinalized.number, + status: "mined", + }; + challengeProgress.status = "Routed"; + + // Check AMB message status on Gnosis with retry + if (previousProgress?.AMB?.status === "pending") { + const tx = (await retryOperation( + () => providerGnosis.getTransaction(previousProgress.AMB.txHash), + 1000, + 10 + )) as any; + if (tx && !tx.blockNumber) { + return { + ...challengeProgress, + status: "AMBMessagePending", + }; + } + } + + const estimatedGnosisBlocks = Math.ceil((gnosisLatest.timestamp - routeBlock.timestamp) / secondsPerSlotGnosis); + + const messageId = routedLogs[0].data; + + const ambFilter = amb.filters.AffirmationCompleted(null, null, messageId, null); + const ambLogs = (await retryOperation( + () => + providerGnosis.getLogs({ + ...ambFilter, + fromBlock: gnosisLatest.number - estimatedGnosisBlocks, + toBlock: "latest", + }), + 1000, + 10 + )) as any; + + if (ambLogs.length > 0) { + const ambBlock = (await retryOperation(() => providerGnosis.getBlock(ambLogs[0].blockNumber), 1000, 10)) as any; + + challengeProgress.AMB = { + ambMessageId: messageId, + txHash: ambLogs[0].transactionHash, + timestamp: ambBlock.timestamp, + finalized: ambLogs[0].blockNumber <= gnosisFinalized.number, + status: "mined", + }; + challengeProgress.status = "AMBMessageSent"; + } + + if (previousProgress?.withdrawal?.status === "pending") { + const tx = (await retryOperation( + () => providerGnosis.getTransaction(previousProgress.withdrawal.txHash), + 1000, + 10 + )) as any; + if (tx && !tx.blockNumber) { + return { + ...challengeProgress, + status: "WithdrawalPending", + }; + } + } + + // there is no event in case of withdrawal hence no way to track it , + // but if a withdrawal is processed ,claimHash for the epoch will be deleted ,challenged progess will not be recontructed in the first place. + return challengeProgress; +} + (async () => { - await watch(); + retryOperation(() => watch(), 1000, 10); })(); export default watch; diff --git a/validator-cli/src/utils/ethers.ts b/validator-cli/src/utils/ethers.ts index 983d08de..8a057680 100644 --- a/validator-cli/src/utils/ethers.ts +++ b/validator-cli/src/utils/ethers.ts @@ -9,6 +9,8 @@ import { VeaInboxArbToEth__factory, VeaInboxArbToGnosis__factory, IWETH__factory, + RouterArbToGnosis__factory, + IAMB__factory, } from "@kleros/vea-contracts/typechain-types"; function getWallet(privateKey: string, web3ProviderURL: string) { @@ -63,6 +65,13 @@ function getVeaOutboxArbToGnosis(veaOutboxAddress: string, privateKey: string, w return VeaOutboxArbToGnosisDevnet__factory.connect(veaOutboxAddress, getWallet(privateKey, web3ProviderURL)); } +function getVeaRouterArbToGnosisProvider(veaRouterAddress: string, privateKey: string, rpc: JsonRpcProvider) { + return RouterArbToGnosis__factory.connect(veaRouterAddress, getWalletRPC(privateKey, rpc)); +} + +function getAMBProvider(privateKey: string, rpc: JsonRpcProvider) { + return IAMB__factory.connect(process.env.GNO_AMB_ADDRESS, getWalletRPC(privateKey, rpc)); +} export { getVeaOutboxArbToEth, getWalletRPC, @@ -72,5 +81,7 @@ export { getVeaOutboxArbToEthProvider, getVeaOutboxArbToGnosisProvider, getVeaInboxArbToGnosisProvider, + getVeaRouterArbToGnosisProvider, getWETHProvider, + getAMBProvider, }; diff --git a/yarn.lock b/yarn.lock index 7d651f49..ffa3cbe3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3269,6 +3269,7 @@ __metadata: "@typechain/ethers-v5": "npm:^10.2.0" dotenv: "npm:^16.4.5" pm2: "npm:^5.2.2" + ts-node: "npm:^10.9.2" typescript: "npm:^4.9.5" web3: "npm:^1.10.4" web3-batched-send: "npm:^1.0.3" @@ -3297,6 +3298,7 @@ __metadata: "@typechain/ethers-v5": "npm:^10.2.0" dotenv: "npm:^16.4.5" pm2: "npm:^5.2.2" + ts-node: "npm:^10.9.2" typescript: "npm:^4.9.5" web3: "npm:^1.10.4" web3-batched-send: "npm:^1.0.3" From c6f623589613b107df5734bc1c236ed0b2dccab1 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 21 Nov 2024 14:47:21 +0700 Subject: [PATCH 5/7] feat(validator-bot): review fixes by the rabbit --- validator-cli/.env.dist | 2 +- validator-cli/src/ArbToEth/watcherArbToGnosis.ts | 7 +++++-- validator-cli/src/utils/ethers.ts | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/validator-cli/.env.dist b/validator-cli/.env.dist index 6fae1c80..ffa74e1c 100644 --- a/validator-cli/.env.dist +++ b/validator-cli/.env.dist @@ -24,7 +24,7 @@ VEAOUTBOX_ARBSEPOLIA_TO_SEPOLIA_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce4 VEAINBOX_ARB_TO_GNOSIS_ADDRESS=0x854374483572FFcD4d0225290346279d0718240b VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS=0x2f1788F7B74e01c4C85578748290467A5f063B0b VEAROUTER_ARB_TO_GNOSIS_ADDRESS=0x5BE03fDE7794Bc188416ba16932510Ed1277b193 -GNO_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d +GNOSIS_AMB_ADDRESS=0x8448E15d0e706C0298dECA99F0b4744030e59d7d TRANSACTION_BATCHER_CONTRACT_ADDRESS_SEPOLIA=0xe7953da7751063d0a41ba727c32c762d3523ade8 TRANSACTION_BATCHER_CONTRACT_ADDRESS_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73 \ No newline at end of file diff --git a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts index 9f6b702f..dae50c7d 100644 --- a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts +++ b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts @@ -86,6 +86,7 @@ const secondsPerSlotGnosis = 5; const veaOutboxAddress = process.env.VEAOUTBOX_ARB_TO_GNOSIS_ADDRESS; const veaInboxAddress = process.env.VEAINBOX_ARB_TO_GNOSIS_ADDRESS; const veaRouterAddress = process.env.VEAROUTER_ARB_TO_GNOSIS_ADDRESS; +const gnosisAMBAddress = process.env.GNOSIS_AMB_ADDRESS; const challenges = new Map(); @@ -101,7 +102,7 @@ const watch = async () => { const veaOutbox = getVeaOutboxArbToGnosisProvider(veaOutboxAddress, process.env.PRIVATE_KEY, providerGnosis); const veaInbox = getVeaInboxArbToGnosisProvider(veaInboxAddress, process.env.PRIVATE_KEY, providerArb); const veaRouter = getVeaRouterArbToGnosisProvider(veaRouterAddress, process.env.PRIVATE_KEY, providerEth); - const amb = getAMBProvider(process.env.PRIVATE_KEY, providerGnosis); + const amb = getAMBProvider(gnosisAMBAddress, process.env.PRIVATE_KEY, providerGnosis); const wethAddress = (await retryOperation(() => veaOutbox.weth(), 1000, 10)) as string; const weth = getWETHProvider(wethAddress, process.env.PRIVATE_KEY, providerGnosis); @@ -932,7 +933,9 @@ async function reconstructChallengeProgress( retryOperation(() => providerArb.getBlock("latest"), 1000, 10) as any, ]); - const averageArbitrumBlocktime = 0.26; + const blockTimeWindow = 100; // Calculate average over last 100 blocks + const oldBlock = await providerArb.getBlock(arbLatest.number - blockTimeWindow); + const averageArbitrumBlocktime = (arbLatest.timestamp - oldBlock.timestamp) / blockTimeWindow; const estimatedArbBlocks = Math.ceil((arbLatest.timestamp - challengeBlock.timestamp) / averageArbitrumBlocktime); const snapshotSentFilter = veaInbox.filters.SnapshotSent(epoch, null); diff --git a/validator-cli/src/utils/ethers.ts b/validator-cli/src/utils/ethers.ts index 8a057680..7a06cbbf 100644 --- a/validator-cli/src/utils/ethers.ts +++ b/validator-cli/src/utils/ethers.ts @@ -69,8 +69,8 @@ function getVeaRouterArbToGnosisProvider(veaRouterAddress: string, privateKey: s return RouterArbToGnosis__factory.connect(veaRouterAddress, getWalletRPC(privateKey, rpc)); } -function getAMBProvider(privateKey: string, rpc: JsonRpcProvider) { - return IAMB__factory.connect(process.env.GNO_AMB_ADDRESS, getWalletRPC(privateKey, rpc)); +function getAMBProvider(ambAddress: string, privateKey: string, rpc: JsonRpcProvider) { + return IAMB__factory.connect(ambAddress, getWalletRPC(privateKey, rpc)); } export { getVeaOutboxArbToEth, From 7588346acf7cfec5e5b5edb909a438bd0febf3fc Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Wed, 27 Nov 2024 17:47:17 +0700 Subject: [PATCH 6/7] feat(validator-bot): review fixes --- validator-cli/package.json | 2 +- .../src/ArbToEth/watcherArbToGnosis.ts | 73 ++++++++++++++----- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/validator-cli/package.json b/validator-cli/package.json index 8d2a4f05..0ccddd01 100644 --- a/validator-cli/package.json +++ b/validator-cli/package.json @@ -14,7 +14,7 @@ "start-chiado-devnet": "npx ts-node ./src/devnet/arbToChiado/happyPath.ts", "start-sepolia-devnet": "npx ts-node ./src/devnet/arbToSepolia/happyPath.ts", "start-sepolia-testnet": "npx ts-node ./src/ArbToEth/watcherArbToEth.ts", - "start-chaido-testnet": "npx ts-node ./src/ArbToEth/watcherArbToGnosis.ts" + "start-arbitrum-to-gnosis": "npx ts-node ./src/ArbToEth/watcherArbToGnosis.ts" }, "dependencies": { "@arbitrum/sdk": "4.0.1", diff --git a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts index dae50c7d..c5856308 100644 --- a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts +++ b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts @@ -11,7 +11,7 @@ import { ChildToParentMessageStatus, ChildTransactionReceipt, getArbitrumNetwork import { NODE_INTERFACE_ADDRESS } from "@arbitrum/sdk/dist/lib/dataEntities/constants"; import { NodeInterface__factory } from "@arbitrum/sdk/dist/lib/abi/factories/NodeInterface__factory"; import { SequencerInbox__factory } from "@arbitrum/sdk/dist/lib/abi/factories/SequencerInbox__factory"; -import { BigNumber, ContractTransaction, Wallet, constants } from "ethers"; +import { BigNumber, ContractTransaction, Wallet, constants, ethers } from "ethers"; import { Block, Log } from "@ethersproject/abstract-provider"; import { SequencerInbox } from "@arbitrum/sdk/dist/lib/abi/SequencerInbox"; import { NodeInterface } from "@arbitrum/sdk/dist/lib/abi/NodeInterface"; @@ -212,12 +212,15 @@ const watch = async () => { const veaEpochOutboxClaimableNowOld = veaEpochOutboxClaimableNow; veaEpochOutboxClaimableNow = Math.floor(timeGnosis / epochPeriod) - 1; - // TODO: sometimes veaEpochOutboxClaimableNow is 1 epoch behind veaEpochOutboxClaimableNowOld - const veaEpochsOutboxClaimableNew: number[] = new Array(veaEpochOutboxClaimableNow - veaEpochOutboxClaimableNowOld) - .fill(veaEpochOutboxClaimableNowOld + 1) - .map((el, i) => el + i); - veaEpochOutboxCheckClaimsRangeArray.concat(veaEpochsOutboxClaimableNew); + if (veaEpochOutboxClaimableNow > veaEpochOutboxClaimableNowOld) { + const veaEpochsOutboxClaimableNew: number[] = new Array( + veaEpochOutboxClaimableNow - veaEpochOutboxClaimableNowOld + ) + .fill(veaEpochOutboxClaimableNowOld + 1) + .map((el, i) => el + i); + veaEpochOutboxCheckClaimsRangeArray.push(...veaEpochsOutboxClaimableNew); + } if (veaEpochOutboxCheckClaimsRangeArray.length == 0) { console.log("no claims to check"); @@ -248,7 +251,7 @@ const watch = async () => { ); veaEpochOutboxCheckClaimsRangeArray.splice(index, 1); index--; - if (challenges.has(index)) challenges.delete(index); + if (challenges.has(veaEpochOutboxCheck)) challenges.delete(veaEpochOutboxCheck); continue; } else { console.log( @@ -320,7 +323,7 @@ const watch = async () => { continue; } console.log(veaEpochOutboxCheck, "claim found ", { claim }); - const previousProgress = challenges.get(index) || ({} as any); + const previousProgress = challenges.get(veaEpochOutboxCheck) || ({} as any); let challengeProgress = await reconstructChallengeProgress( veaEpochOutboxCheck, veaOutbox, @@ -333,7 +336,7 @@ const watch = async () => { amb, previousProgress ); - challenges.set(index, challengeProgress); + challenges.set(veaEpochOutboxCheck, challengeProgress); console.log( "challenge progess for epoch " + veaEpochOutboxCheck + " is " + JSON.stringify(challengeProgress) ); @@ -347,6 +350,14 @@ const watch = async () => { 10 )) as ContractTransaction; console.log("Epoch " + veaEpochOutboxCheck + " challenged with txn " + txnChallenge.hash); + challengeProgress.challenge = { + status: "pending", + txHash: txnChallenge.hash, + timestamp: 0, + finalized: false, + }; + challengeProgress.status = "ChallengePending"; + challenges.set(veaEpochOutboxCheck, challengeProgress); continue; } if (claim?.challenger === watcherAddress) { @@ -359,6 +370,14 @@ const watch = async () => { 10 )) as ContractTransaction; console.log("Epoch " + veaEpochOutboxCheck + " sendSnapshot called with txn " + txnSendSnapshot.hash); + challengeProgress.snapshot = { + status: "pending", + txHash: txnSendSnapshot.hash, + timestamp: 0, + finalized: false, + }; + challengeProgress.status = "SnapshotPending"; + challenges.set(veaEpochOutboxCheck, challengeProgress); } } if ( @@ -389,7 +408,7 @@ const watch = async () => { finalized: false, }; challengeProgress.status = "WithdrawalPending"; - challenges.set(index, challengeProgress); + challenges.set(veaEpochOutboxCheck, challengeProgress); } } } @@ -567,7 +586,9 @@ const ArbBlockToL1Block = async ( let latestL2BlockNumberOnEth: number; let result = (await nodeInterface.functions .findBatchContainingBlock(L2Block.number, { blockTag: "latest" }) - .catch((e) => {})) as [BigNumber] & { batch: BigNumber }; + .catch((e) => { + console.error("Error finding batch containing block:", JSON.parse(JSON.stringify(e)).error.body); + })) as [BigNumber] & { batch: BigNumber }; if (!result) { if (!fallbackLatest) { @@ -605,7 +626,7 @@ const findLatestL2BatchAndBlock = async ( nodeInterface: NodeInterface, fromArbBlock: number, latestBlockNumber: number -): Promise<[number, number]> => { +): Promise<[number | undefined, number | undefined]> => { let low = fromArbBlock; let high = latestBlockNumber; @@ -676,7 +697,7 @@ async function getClaimForEpoch( challenger: constants.AddressZero, }; let other = {} as any; - let calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + let calculatedHash = hashClaim(claim); if (calculatedHash == claimHash) return claim; // Check for Challenged event @@ -698,7 +719,7 @@ async function getClaimForEpoch( other.challengeBlock = challengedEvents[0].blockNumber; } - calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + calculatedHash = hashClaim(claim); if (calculatedHash == claimHash) return claim; // Check for VerificationStarted event @@ -721,16 +742,13 @@ async function getClaimForEpoch( ); claim.timestampVerification = verificationBlock.timestamp; claim.blocknumberVerification = verificationBlock.number; - claim.challenger = constants.AddressZero; } - calculatedHash = await retryOperation(() => veaOutbox.hashClaim(claim), 1000, 10); + calculatedHash = hashClaim(claim); if (calculatedHash == claimHash) return claim; - const [claimBridgerHonest, claimChallengerHonest] = await Promise.all([ - retryOperation(() => veaOutbox.hashClaim({ ...claim, honest: 1 }), 1000, 10) as any, - retryOperation(() => veaOutbox.hashClaim({ ...claim, honest: 2 }), 1000, 10) as any, - ]); + const claimBridgerHonest = hashClaim({ ...claim, honest: 1 }); + const claimChallengerHonest = hashClaim({ ...claim, honest: 2 }); if (claimBridgerHonest === claimHash) return { ...claim, honest: 1 }; if (claimChallengerHonest === claimHash) return { ...claim, honest: 2 }; @@ -1093,6 +1111,21 @@ async function reconstructChallengeProgress( return challengeProgress; } +const hashClaim = (claim) => { + return ethers.utils.solidityKeccak256( + ["bytes32", "address", "uint32", "uint32", "uint32", "uint8", "address"], + [ + claim.stateRoot, + claim.claimer, + claim.timestampClaimed, + claim.timestampVerification, + claim.blocknumberVerification, + claim.honest, + claim.challenger, + ] + ); +}; + (async () => { retryOperation(() => watch(), 1000, 10); })(); From acb800c3bd12d638a6c4ee8c8252125c239937f3 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Fri, 29 Nov 2024 23:27:13 +0700 Subject: [PATCH 7/7] fix(validator-bot): fixes after rebasing --- validator-cli/src/ArbToEth/watcherArbToGnosis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts index c5856308..fb4047e3 100644 --- a/validator-cli/src/ArbToEth/watcherArbToGnosis.ts +++ b/validator-cli/src/ArbToEth/watcherArbToGnosis.ts @@ -22,7 +22,7 @@ import { VeaOutboxArbToGnosis, } from "@kleros/vea-contracts/typechain-types"; import { ClaimStruct } from "@kleros/vea-contracts/typechain-types/arbitrumToEth/VeaInboxArbToEth"; -import messageExecutor from "../utils/arbMsgExecutor"; +import { messageExecutor } from "../utils/arbMsgExecutor"; require("dotenv").config();