From c1a2c000307f365de18e2d9e4470deaf39dc465b Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:54:33 -0500 Subject: [PATCH 1/8] init execution service + gas oralce --- .../contracts/ExecutionService.sol | 45 ++++++++++++ .../contracts/GasOracle.sol | 71 +++++++++++++++++++ .../events/ExecutionServiceEvents.sol | 13 ++++ 3 files changed, 129 insertions(+) create mode 100644 packages/contracts-communication/contracts/ExecutionService.sol create mode 100644 packages/contracts-communication/contracts/GasOracle.sol create mode 100644 packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol new file mode 100644 index 0000000000..27cbcd0399 --- /dev/null +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + + +import { IExecutionService } from "./interfaces/IExecutionService.sol"; +import { ExecutionServiceEvents } from "./events/ExecutionServiceEvents.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + + +contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService { + address public executorEOA; + + constructor() Ownable(msg.sender) {} + + function setExecutorEOA(address _executorEOA) external onlyOwner { + executorEOA = _executorEOA; + emit ExecutorEOAUpdated(executorEOA); + } + + function requestExecution( + uint256 dstChainId, + uint256 txPayloadSize, + bytes32 transactionId, + uint256 executionFee, + bytes memory options + ) + external + override + { + emit ExecutionRequested(dstChainId, txPayloadSize, transactionId, executionFee, options); + } + + function getExecutionFee( + uint256 dstChainId, + uint256 txPayloadSize, + bytes memory options + ) + external + view + override + returns (uint256) + { + // ... + } +} diff --git a/packages/contracts-communication/contracts/GasOracle.sol b/packages/contracts-communication/contracts/GasOracle.sol new file mode 100644 index 0000000000..da84eeb19f --- /dev/null +++ b/packages/contracts-communication/contracts/GasOracle.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.20; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IGasOracle } from "./interfaces/IGasOracle.sol"; +contract GasOracle is Ownable, IGasOracle { + // DstChainId => The estimated current gas price in wei of the destination chain + mapping(uint256 => uint256) public dstGasPriceInWei; + // DstChainId => USD gas ratio of dstGasToken / srcGasToken + mapping(uint256 => uint256) public dstGasTokenRatio; + + constructor() {} + + /** + * @notice Permissioned method to allow an off-chain party to set what each dstChain's + * gas cost is priced in the srcChain's native gas currency. + * Example: call on ETH, setCostPerChain(43114, 30000000000, 25180000000000000) + * chain ID 43114 + * Average of 30 gwei cost to transaction on 43114 + * AVAX/ETH = 0.02518, scaled to gas in wei = 25180000000000000 + * @param _dstChainId The destination chain ID - typically, standard EVM chain ID, but differs on nonEVM chains + * @param _gasUnitPrice The estimated current gas price in wei of the destination chain + * @param _gasTokenPriceRatio USD gas ratio of dstGasToken / srcGasToken + */ + // Example: + // DstChainId = 1666600000 + // Harmony set gwei to 200000000000 + // ONE / JEWEL = 0.05 == 50000000000000000 + + // DstChainId = 53935 + // DFK Chain set 1 gwei = 1000000000 + // JEWEL / ONE = 20000000000000000000 + + // DstChainId = 8217 + // Klaytn Gwei set to 250000000000 + // KLAYTN / JEWEL = 1200000000000000000 + + // DstchainId = 53935 + // DFK Chain set to 1 gwei + // JEWEL / KLAYTN = 900000000000000000 + + function setCostPerChain( + uint256 _dstChainId, + uint256 _gasUnitPrice, + uint256 _gasTokenPriceRatio + ) external onlyOwner { + dstGasPriceInWei[_dstChainId] = _gasUnitPrice; + dstGasTokenRatio[_dstChainId] = _gasTokenPriceRatio; + } + + /** + * @notice Returns srcGasToken fee to charge in wei for the cross-chain message based on the gas limit + * @param _options Versioned struct used to instruct relayer on how to proceed with gas limits. Contains data on gas limit to submit tx with. + */ + function estimateGasFee(uint256 _dstChainId, bytes memory _options) external view returns (uint256) { + uint256 gasLimit; + // temporary gas limit set + if (_options.length != 0) { + (uint16 _txType, uint256 _gasLimit, uint256 _dstAirdrop, bytes32 _dstAddress) = decodeOptions(_options); + gasLimit = _gasLimit; + } else { + gasLimit = 200000; + } + + uint256 minFee = ((dstGasPriceInWei[_dstChainId] * dstGasTokenRatio[_dstChainId] * gasLimit) / 10**18); + + return minFee; + } + +} diff --git a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol new file mode 100644 index 0000000000..d6e140796d --- /dev/null +++ b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +abstract contract ExecutionServiceEvents { + event ExecutionRequested( + uint256 indexed dstChainId, + uint256 indexed txPayloadSize, + bytes32 indexed transactionId, + uint256 executionFee, + bytes options + ); + event ExecutorEOAUpdated(address indexed executorEOA); +} From 596c242fae24e5ae4ad81a8745cecab1a27ee5a8 Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:55:48 -0500 Subject: [PATCH 2/8] gasoracle --- .../contracts/GasOracle.sol | 61 ------------------- 1 file changed, 61 deletions(-) diff --git a/packages/contracts-communication/contracts/GasOracle.sol b/packages/contracts-communication/contracts/GasOracle.sol index da84eeb19f..c8ebf0958e 100644 --- a/packages/contracts-communication/contracts/GasOracle.sol +++ b/packages/contracts-communication/contracts/GasOracle.sol @@ -5,67 +5,6 @@ pragma solidity 0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IGasOracle } from "./interfaces/IGasOracle.sol"; contract GasOracle is Ownable, IGasOracle { - // DstChainId => The estimated current gas price in wei of the destination chain - mapping(uint256 => uint256) public dstGasPriceInWei; - // DstChainId => USD gas ratio of dstGasToken / srcGasToken - mapping(uint256 => uint256) public dstGasTokenRatio; - constructor() {} - - /** - * @notice Permissioned method to allow an off-chain party to set what each dstChain's - * gas cost is priced in the srcChain's native gas currency. - * Example: call on ETH, setCostPerChain(43114, 30000000000, 25180000000000000) - * chain ID 43114 - * Average of 30 gwei cost to transaction on 43114 - * AVAX/ETH = 0.02518, scaled to gas in wei = 25180000000000000 - * @param _dstChainId The destination chain ID - typically, standard EVM chain ID, but differs on nonEVM chains - * @param _gasUnitPrice The estimated current gas price in wei of the destination chain - * @param _gasTokenPriceRatio USD gas ratio of dstGasToken / srcGasToken - */ - // Example: - // DstChainId = 1666600000 - // Harmony set gwei to 200000000000 - // ONE / JEWEL = 0.05 == 50000000000000000 - - // DstChainId = 53935 - // DFK Chain set 1 gwei = 1000000000 - // JEWEL / ONE = 20000000000000000000 - - // DstChainId = 8217 - // Klaytn Gwei set to 250000000000 - // KLAYTN / JEWEL = 1200000000000000000 - - // DstchainId = 53935 - // DFK Chain set to 1 gwei - // JEWEL / KLAYTN = 900000000000000000 - - function setCostPerChain( - uint256 _dstChainId, - uint256 _gasUnitPrice, - uint256 _gasTokenPriceRatio - ) external onlyOwner { - dstGasPriceInWei[_dstChainId] = _gasUnitPrice; - dstGasTokenRatio[_dstChainId] = _gasTokenPriceRatio; - } - - /** - * @notice Returns srcGasToken fee to charge in wei for the cross-chain message based on the gas limit - * @param _options Versioned struct used to instruct relayer on how to proceed with gas limits. Contains data on gas limit to submit tx with. - */ - function estimateGasFee(uint256 _dstChainId, bytes memory _options) external view returns (uint256) { - uint256 gasLimit; - // temporary gas limit set - if (_options.length != 0) { - (uint16 _txType, uint256 _gasLimit, uint256 _dstAirdrop, bytes32 _dstAddress) = decodeOptions(_options); - gasLimit = _gasLimit; - } else { - gasLimit = 200000; - } - - uint256 minFee = ((dstGasPriceInWei[_dstChainId] * dstGasTokenRatio[_dstChainId] * gasLimit) / 10**18); - - return minFee; - } } From 89a1f2a550facd632aa21d45453cba71d6f91e8e Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:02:08 -0500 Subject: [PATCH 3/8] remove gasoracle for later pr --- .../contracts-communication/contracts/GasOracle.sol | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 packages/contracts-communication/contracts/GasOracle.sol diff --git a/packages/contracts-communication/contracts/GasOracle.sol b/packages/contracts-communication/contracts/GasOracle.sol deleted file mode 100644 index c8ebf0958e..0000000000 --- a/packages/contracts-communication/contracts/GasOracle.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.20; - -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { IGasOracle } from "./interfaces/IGasOracle.sol"; -contract GasOracle is Ownable, IGasOracle { - - -} From 5a42ebee1b926381ed5cf7e639413f1c15f3f31e Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Sun, 25 Feb 2024 14:56:29 -0500 Subject: [PATCH 4/8] feat: Enhance ExecutionService with gas oracle and options handling - Introduce IGasOracle interface and OptionsLib for handling execution options. - Add gasOracle state variable and setGasOracle function for updating the gas oracle address. - Implement onlyInterchainClient modifier to restrict execution requests to the designated interchain client. - Update requestExecution to enforce a minimum execution fee based on the calculated fee from getExecutionFee. - Enhance getExecutionFee to calculate fees using the gas oracle and options, supporting versioned options handling. - Add events for updating gas oracle and interchain client addresses. - Minor code style adjustments for consistency. This update enables dynamic execution fee calculation based on gas costs and introduces infrastructure for future options-based execution enhancements. --- .../contracts/ExecutionService.sol | 44 ++++++++++++++++--- .../events/ExecutionServiceEvents.sol | 2 + .../script/MessagingBase.s.sol | 3 +- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol index 27cbcd0399..4be929e046 100644 --- a/packages/contracts-communication/contracts/ExecutionService.sol +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -1,22 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; +import {IExecutionService} from "./interfaces/IExecutionService.sol"; +import {ExecutionServiceEvents} from "./events/ExecutionServiceEvents.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import { IExecutionService } from "./interfaces/IExecutionService.sol"; -import { ExecutionServiceEvents } from "./events/ExecutionServiceEvents.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import {IGasOracle} from "./interfaces/IGasOracle.sol"; +import {OptionsLib, OptionsV1} from "./libs/Options.sol"; contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService { + using OptionsLib for bytes; + + address public interchainClient; address public executorEOA; + IGasOracle public gasOracle; constructor() Ownable(msg.sender) {} + function setInterchainClient(address _interchainClient) external onlyOwner { + interchainClient = _interchainClient; + emit InterchainClientUpdated(_interchainClient); + } + function setExecutorEOA(address _executorEOA) external onlyOwner { executorEOA = _executorEOA; emit ExecutorEOAUpdated(executorEOA); } + function setGasOracle(address _gasOracle) external onlyOwner { + gasOracle = IGasOracle(_gasOracle); + emit GasOracleUpdated(_gasOracle); + } + + modifier onlyInterchainClient() { + require(msg.sender == interchainClient, "ExecutionService: caller is not the InterchainClient"); + _; + } + + // @inheritdoc function requestExecution( uint256 dstChainId, uint256 txPayloadSize, @@ -25,11 +47,13 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService bytes memory options ) external - override + override onlyInterchainClient { + require(executionFee > getExecutionFee(dstChainId, txPayloadSize, options), "ExecutionService: execution fee is not high enough"); emit ExecutionRequested(dstChainId, txPayloadSize, transactionId, executionFee, options); } + // @inheritdoc function getExecutionFee( uint256 dstChainId, uint256 txPayloadSize, @@ -40,6 +64,16 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService override returns (uint256) { - // ... + (uint8 version, bytes memory data) = options.decodeVersionedOptions(); + if (version == OptionsLib.OPTIONS_V1) { + OptionsV1 memory optionsV1 = data.decodeOptionsV1(); + uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize); + if (optionsV1.gasAirdrop > 0) { + baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop); + } + return baseCost; + } else { + revert("Unsupported options version: version must be OPTIONS_V1"); + } } } diff --git a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol index d6e140796d..176479cbfa 100644 --- a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol +++ b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol @@ -10,4 +10,6 @@ abstract contract ExecutionServiceEvents { bytes options ); event ExecutorEOAUpdated(address indexed executorEOA); + event GasOracleUpdated(address indexed gasOracle); + event InterchainClientUpdated(address indexed interchainClient); } diff --git a/packages/contracts-communication/script/MessagingBase.s.sol b/packages/contracts-communication/script/MessagingBase.s.sol index 27fdd2319b..eb413c1f06 100644 --- a/packages/contracts-communication/script/MessagingBase.s.sol +++ b/packages/contracts-communication/script/MessagingBase.s.sol @@ -13,7 +13,7 @@ import {InterchainApp} from "../contracts/InterchainApp.sol"; import {GasOracleMock} from "../test/mocks/GasOracleMock.sol"; -import { ExecutionFeesMock } from "../test/mocks/ExecutionFeesMock.sol"; +import {ExecutionFeesMock} from "../test/mocks/ExecutionFeesMock.sol"; contract MessagingBase is Script { InterchainDB public icDB; @@ -39,5 +39,4 @@ contract MessagingBase is Script { vm.stopBroadcast(); } - } From 8515a04f92d651b3d0e97c480f7eceacef5482c1 Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Sun, 25 Feb 2024 18:15:58 -0500 Subject: [PATCH 5/8] begin test --- .../contracts/ExecutionService.sol | 2 +- .../test/ExecutionService.t.sol | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 packages/contracts-communication/test/ExecutionService.t.sol diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol index 4be929e046..1ed0cb5b8e 100644 --- a/packages/contracts-communication/contracts/ExecutionService.sol +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -59,7 +59,7 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService uint256 txPayloadSize, bytes memory options ) - external + public view override returns (uint256) diff --git a/packages/contracts-communication/test/ExecutionService.t.sol b/packages/contracts-communication/test/ExecutionService.t.sol new file mode 100644 index 0000000000..074508d7ae --- /dev/null +++ b/packages/contracts-communication/test/ExecutionService.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {ExecutionService, ExecutionServiceEvents, IExecutionService } from "../contracts/ExecutionService.sol"; +import {Test} from "forge-std/Test.sol"; +import {GasOracleMock } from "./mocks/GasOracleMock.sol"; +contract ExecutionServiceTest is ExecutionServiceEvents, Test { + ExecutionService public executionService; + GasOracleMock public gasOracle; + + address icClient = address(0x123); + address executorEOA = address(0x456); + + + function setUp() public { + gasOracle = new GasOracleMock(); + executionService = new ExecutionService(); + executionService.setInterchainClient(icClient); + executionService.setExecutorEOA(executorEOA); + executionService.setGasOracle(address(gasOracle)); + } + + +} From ca919c6344ad9e58f819268fc335d96b1f557b39 Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:13:20 -0500 Subject: [PATCH 6/8] Remove unneeded event ExecutionRequested variables --- .../contracts-communication/contracts/ExecutionService.sol | 2 +- .../contracts/events/ExecutionServiceEvents.sol | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol index 1ed0cb5b8e..2de9be192c 100644 --- a/packages/contracts-communication/contracts/ExecutionService.sol +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -50,7 +50,7 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService override onlyInterchainClient { require(executionFee > getExecutionFee(dstChainId, txPayloadSize, options), "ExecutionService: execution fee is not high enough"); - emit ExecutionRequested(dstChainId, txPayloadSize, transactionId, executionFee, options); + emit ExecutionRequested(transactionId); } // @inheritdoc diff --git a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol index 176479cbfa..c23e63b174 100644 --- a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol +++ b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol @@ -3,11 +3,7 @@ pragma solidity ^0.8.0; abstract contract ExecutionServiceEvents { event ExecutionRequested( - uint256 indexed dstChainId, - uint256 indexed txPayloadSize, - bytes32 indexed transactionId, - uint256 executionFee, - bytes options + bytes32 indexed transactionId ); event ExecutorEOAUpdated(address indexed executorEOA); event GasOracleUpdated(address indexed gasOracle); From d590340f2db10e2e919b31186cbee93d42bf94f8 Mon Sep 17 00:00:00 2001 From: Trajan0x Date: Wed, 28 Feb 2024 02:23:06 +0000 Subject: [PATCH 7/8] forge fmt --- .../contracts/ExecutionService.sol | 8 ++++++-- .../contracts/events/ExecutionServiceEvents.sol | 4 +--- .../contracts-communication/test/ExecutionService.t.sol | 8 +++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol index 2de9be192c..a585f8a7cc 100644 --- a/packages/contracts-communication/contracts/ExecutionService.sol +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -47,9 +47,13 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService bytes memory options ) external - override onlyInterchainClient + override + onlyInterchainClient { - require(executionFee > getExecutionFee(dstChainId, txPayloadSize, options), "ExecutionService: execution fee is not high enough"); + require( + executionFee > getExecutionFee(dstChainId, txPayloadSize, options), + "ExecutionService: execution fee is not high enough" + ); emit ExecutionRequested(transactionId); } diff --git a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol index c23e63b174..d512a98d28 100644 --- a/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol +++ b/packages/contracts-communication/contracts/events/ExecutionServiceEvents.sol @@ -2,9 +2,7 @@ pragma solidity ^0.8.0; abstract contract ExecutionServiceEvents { - event ExecutionRequested( - bytes32 indexed transactionId - ); + event ExecutionRequested(bytes32 indexed transactionId); event ExecutorEOAUpdated(address indexed executorEOA); event GasOracleUpdated(address indexed gasOracle); event InterchainClientUpdated(address indexed interchainClient); diff --git a/packages/contracts-communication/test/ExecutionService.t.sol b/packages/contracts-communication/test/ExecutionService.t.sol index 074508d7ae..ecba4ca069 100644 --- a/packages/contracts-communication/test/ExecutionService.t.sol +++ b/packages/contracts-communication/test/ExecutionService.t.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {ExecutionService, ExecutionServiceEvents, IExecutionService } from "../contracts/ExecutionService.sol"; +import {ExecutionService, ExecutionServiceEvents, IExecutionService} from "../contracts/ExecutionService.sol"; import {Test} from "forge-std/Test.sol"; -import {GasOracleMock } from "./mocks/GasOracleMock.sol"; +import {GasOracleMock} from "./mocks/GasOracleMock.sol"; + contract ExecutionServiceTest is ExecutionServiceEvents, Test { ExecutionService public executionService; GasOracleMock public gasOracle; @@ -11,7 +12,6 @@ contract ExecutionServiceTest is ExecutionServiceEvents, Test { address icClient = address(0x123); address executorEOA = address(0x456); - function setUp() public { gasOracle = new GasOracleMock(); executionService = new ExecutionService(); @@ -19,6 +19,4 @@ contract ExecutionServiceTest is ExecutionServiceEvents, Test { executionService.setExecutorEOA(executorEOA); executionService.setGasOracle(address(gasOracle)); } - - } From c807b4f8dd8a3451fd70ca43cd0352e995854cb8 Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Wed, 28 Feb 2024 06:16:42 +0100 Subject: [PATCH 8/8] Execution Service Consolidation (#2125) (#2127) (#2128) Co-authored-by: Trajan0x --- committee/node/node.go | 1 - .../contracts/ExecutionService.sol | 4 +- .../contracts/InterchainApp.sol | 5 +- .../script/MessagingBase.s.sol | 4 +- sin-executor/Makefile | 8 +- sin-executor/cmd/commands.go | 9 +- sin-executor/config/config.go | 11 +- .../executionservice/eventtype_string.go | 24 + .../executionservice.abigen.go | 3163 +++++++++++++++++ .../executionservice.contractinfo.json | 1 + .../executionservice.metadata.go} | 4 +- .../contracts/executionservice/generate.go | 3 + .../contracts/executionservice/helpers.go | 35 + .../contracts/executionservice/parser.go | 64 + .../contracts/executionservice/topics.go | 49 + .../interchainclient/eventtype_string.go | 5 +- .../contracts/interchainclient/parser.go | 2 - .../contracts/interchainclient/topics.go | 5 - .../executionservicemock.abigen.go | 538 --- .../executionservicemock.contractinfo.json | 1 - .../mocks/executionservicemock/generate.go | 3 - .../mocks/executionservicemock/helpers.go | 34 - .../gasoraclemock/gasoraclemock.abigen.go | 558 +++ .../gasoraclemock.contractinfo.json | 1 + .../gasoraclemock/gasoraclemock.metadata.go | 25 + .../contracts/mocks/gasoraclemock/generate.go | 3 + .../contracts/mocks/gasoraclemock/helpers.go | 35 + .../interchainapp/interchainapp.abigen.go | 34 +- .../interchainapp.contractinfo.json | 2 +- sin-executor/executor/executor.go | 99 +- sin-executor/executor/executor_test.go | 22 +- sin-executor/executor/suite_test.go | 50 +- sin-executor/testutil/contracttype.go | 15 +- .../testutil/contracttypeimpl_string.go | 7 +- sin-executor/testutil/deployers.go | 37 +- sin-executor/testutil/typecast.go | 7 + 36 files changed, 4190 insertions(+), 678 deletions(-) mode change 120000 => 100644 sin-executor/Makefile create mode 100644 sin-executor/contracts/executionservice/eventtype_string.go create mode 100644 sin-executor/contracts/executionservice/executionservice.abigen.go create mode 100644 sin-executor/contracts/executionservice/executionservice.contractinfo.json rename sin-executor/contracts/{mocks/executionservicemock/executionservicemock.metadata.go => executionservice/executionservice.metadata.go} (85%) create mode 100644 sin-executor/contracts/executionservice/generate.go create mode 100644 sin-executor/contracts/executionservice/helpers.go create mode 100644 sin-executor/contracts/executionservice/parser.go create mode 100644 sin-executor/contracts/executionservice/topics.go delete mode 100644 sin-executor/contracts/mocks/executionservicemock/executionservicemock.abigen.go delete mode 100644 sin-executor/contracts/mocks/executionservicemock/executionservicemock.contractinfo.json delete mode 100644 sin-executor/contracts/mocks/executionservicemock/generate.go delete mode 100644 sin-executor/contracts/mocks/executionservicemock/helpers.go create mode 100644 sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.abigen.go create mode 100644 sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.contractinfo.json create mode 100644 sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.metadata.go create mode 100644 sin-executor/contracts/mocks/gasoraclemock/generate.go create mode 100644 sin-executor/contracts/mocks/gasoraclemock/helpers.go diff --git a/committee/node/node.go b/committee/node/node.go index c3eb5d08de..3045f87e0a 100644 --- a/committee/node/node.go +++ b/committee/node/node.go @@ -328,7 +328,6 @@ func (n *Node) submit(ctx context.Context, request db.SignRequest) error { logger.Errorf("could not get submission status: %w", err) } - fmt.Println("fuck") fmt.Printf("tx hash: %s\n", yo.TxHash().String()) fmt.Printf("new signed hash: %s \n", request.SignedEntryHash.String()) fmt.Println("you") diff --git a/packages/contracts-communication/contracts/ExecutionService.sol b/packages/contracts-communication/contracts/ExecutionService.sol index a585f8a7cc..ef1e17c50f 100644 --- a/packages/contracts-communication/contracts/ExecutionService.sol +++ b/packages/contracts-communication/contracts/ExecutionService.sol @@ -51,7 +51,7 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService onlyInterchainClient { require( - executionFee > getExecutionFee(dstChainId, txPayloadSize, options), + executionFee >= getExecutionFee(dstChainId, txPayloadSize, options), "ExecutionService: execution fee is not high enough" ); emit ExecutionRequested(transactionId); @@ -70,7 +70,7 @@ contract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService { (uint8 version, bytes memory data) = options.decodeVersionedOptions(); if (version == OptionsLib.OPTIONS_V1) { - OptionsV1 memory optionsV1 = data.decodeOptionsV1(); + OptionsV1 memory optionsV1 = options.decodeOptionsV1(); uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize); if (optionsV1.gasAirdrop > 0) { baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop); diff --git a/packages/contracts-communication/contracts/InterchainApp.sol b/packages/contracts-communication/contracts/InterchainApp.sol index a96df180e9..8b3eb1e977 100644 --- a/packages/contracts-communication/contracts/InterchainApp.sol +++ b/packages/contracts-communication/contracts/InterchainApp.sol @@ -14,6 +14,7 @@ contract InterchainApp is IInterchainApp { address[] private sendingModules; address[] private receivingModules; + address private executionService; struct AppConfig { // ChainID -> Linked IApps @@ -33,6 +34,7 @@ contract InterchainApp is IInterchainApp { address[] memory linkedIApps, address[] memory _sendingModules, address[] memory _receivingModules, + address _executionService, uint256 _requiredResponses, uint64 _optimisticTimePeriod ) @@ -50,6 +52,7 @@ contract InterchainApp is IInterchainApp { localAppConfig.sendingModules = _sendingModules; localAppConfig.receivingModules = _receivingModules; + executionService = _executionService; } // Getters for the application configuration @@ -95,7 +98,7 @@ contract InterchainApp is IInterchainApp { bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1(); // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this interchain.interchainSend{value: msg.value}( - dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message + dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message ); emit AppMessageSent(); } diff --git a/packages/contracts-communication/script/MessagingBase.s.sol b/packages/contracts-communication/script/MessagingBase.s.sol index 339eaafddd..887afe94a4 100644 --- a/packages/contracts-communication/script/MessagingBase.s.sol +++ b/packages/contracts-communication/script/MessagingBase.s.sol @@ -65,7 +65,7 @@ contract MessagingBase is Script { uint256 _requiredResponses = 1; uint64 _optimisticTimePeriod = 1; icApp.setAppConfig( - chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod + chainIDs, linkedIApps, _sendingModules, _receivingModules, address(0), _requiredResponses, _optimisticTimePeriod ); vm.stopBroadcast(); } @@ -84,7 +84,7 @@ contract MessagingBase is Script { uint256 _requiredResponses = 1; uint64 _optimisticTimePeriod = 1; icApp.setAppConfig( - chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod + chainIDs, linkedIApps, _sendingModules, _receivingModules, address(0), _requiredResponses, _optimisticTimePeriod ); vm.stopBroadcast(); } diff --git a/sin-executor/Makefile b/sin-executor/Makefile deleted file mode 120000 index 85ff374d51..0000000000 --- a/sin-executor/Makefile +++ /dev/null @@ -1 +0,0 @@ -../make/go.Makefile \ No newline at end of file diff --git a/sin-executor/Makefile b/sin-executor/Makefile new file mode 100644 index 0000000000..a2fc365231 --- /dev/null +++ b/sin-executor/Makefile @@ -0,0 +1,7 @@ +include ../make/go.Makefile + +generate: ## Generate code + cd $(GIT_ROOT)/packages/contracts-communication && yarn build:go + go generate ./... + + diff --git a/sin-executor/cmd/commands.go b/sin-executor/cmd/commands.go index 621d5f1b9a..4109f468cc 100644 --- a/sin-executor/cmd/commands.go +++ b/sin-executor/cmd/commands.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "github.com/synapsecns/sanguine/core/commandline" "github.com/synapsecns/sanguine/core/metrics" "github.com/synapsecns/sanguine/sin-executor/config" @@ -29,7 +30,7 @@ var runCommand = &cli.Command{ input, err := os.ReadFile(filepath.Clean(c.String(configFlag.Name))) if err != nil { - return err + return fmt.Errorf("failed to read config file: %w", err) } metricsProvider := metrics.Get() @@ -37,17 +38,17 @@ var runCommand = &cli.Command{ var cfg config.Config err = yaml.Unmarshal(input, &cfg) if err != nil { - return err + return fmt.Errorf("failed to unmarshal config: %w", err) } exec, err := executor.NewExecutor(c.Context, metricsProvider, cfg) if err != nil { - return err + return fmt.Errorf("failed to create executor: %w", err) } err = exec.Start(c.Context) if err != nil { - return err + return fmt.Errorf("failed to start executor: %w", err) } return nil diff --git a/sin-executor/config/config.go b/sin-executor/config/config.go index 9257542aad..015bce6cda 100644 --- a/sin-executor/config/config.go +++ b/sin-executor/config/config.go @@ -8,8 +8,8 @@ import ( // Config is the config for the Synapse module. type Config struct { - // Chains is a map of chain IDs to chain configs. - Chains map[int]string `yaml:"chains"` + // Chains is a map of chain IDs to execution service contract addresses. + Chains map[int]ChainConfig `yaml:"chains"` // OmnirpcURL is the URL of the Omni RPC. OmnirpcURL string `yaml:"omnirpc_url"` // Database is the database config. @@ -20,6 +20,13 @@ type Config struct { SubmitterConfig submitterConfig.Config `yaml:"submitter_config"` } +type ChainConfig struct { + // ExecutionService is the address of the execution service contract. + ExecutionService string `yaml:"execution_service"` + // Client is the address of the interchain client contract. + Client string `yaml:"client"` +} + // DatabaseConfig represents the configuration for the database. type DatabaseConfig struct { Type string `yaml:"type"` diff --git a/sin-executor/contracts/executionservice/eventtype_string.go b/sin-executor/contracts/executionservice/eventtype_string.go new file mode 100644 index 0000000000..d9aa87f455 --- /dev/null +++ b/sin-executor/contracts/executionservice/eventtype_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=EventType"; DO NOT EDIT. + +package executionservice + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ExecutionRequestedEvent-1] +} + +const _EventType_name = "ExecutionRequestedEvent" + +var _EventType_index = [...]uint8{0, 23} + +func (i EventType) String() string { + i -= 1 + if i >= EventType(len(_EventType_index)-1) { + return "EventType(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _EventType_name[_EventType_index[i]:_EventType_index[i+1]] +} diff --git a/sin-executor/contracts/executionservice/executionservice.abigen.go b/sin-executor/contracts/executionservice/executionservice.abigen.go new file mode 100644 index 0000000000..b0fa51d90f --- /dev/null +++ b/sin-executor/contracts/executionservice/executionservice.abigen.go @@ -0,0 +1,3163 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package executionservice + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ContextMetaData contains all meta data concerning the Context contract. +var ContextMetaData = &bind.MetaData{ + ABI: "[]", +} + +// ContextABI is the input ABI used to generate the binding from. +// Deprecated: Use ContextMetaData.ABI instead. +var ContextABI = ContextMetaData.ABI + +// Context is an auto generated Go binding around an Ethereum contract. +type Context struct { + ContextCaller // Read-only binding to the contract + ContextTransactor // Write-only binding to the contract + ContextFilterer // Log filterer for contract events +} + +// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContextCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContextTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContextFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContextSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContextSession struct { + Contract *Context // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContextCallerSession struct { + Contract *ContextCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContextTransactorSession struct { + Contract *ContextTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContextRaw struct { + Contract *Context // Generic contract binding to access the raw methods on +} + +// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContextCallerRaw struct { + Contract *ContextCaller // Generic read-only contract binding to access the raw methods on +} + +// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContextTransactorRaw struct { + Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContext creates a new instance of Context, bound to a specific deployed contract. +func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { + contract, err := bindContext(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil +} + +// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. +func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { + contract, err := bindContext(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContextCaller{contract: contract}, nil +} + +// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. +func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { + contract, err := bindContext(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContextTransactor{contract: contract}, nil +} + +// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. +func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { + contract, err := bindContext(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContextFilterer{contract: contract}, nil +} + +// bindContext binds a generic wrapper to an already deployed contract. +func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ContextMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.contract.Transact(opts, method, params...) +} + +// ExecutionServiceMetaData contains all meta data concerning the ExecutionService contract. +var ExecutionServiceMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"ExecutionRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executorEOA\",\"type\":\"address\"}],\"name\":\"ExecutorEOAUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gasOracle\",\"type\":\"address\"}],\"name\":\"GasOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"interchainClient\",\"type\":\"address\"}],\"name\":\"InterchainClientUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasOracle\",\"outputs\":[{\"internalType\":\"contractIGasOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchainClient\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_executorEOA\",\"type\":\"address\"}],\"name\":\"setExecutorEOA\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gasOracle\",\"type\":\"address\"}],\"name\":\"setGasOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchainClient\",\"type\":\"address\"}],\"name\":\"setInterchainClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "62014bad": "executorEOA()", + "5d62a8dd": "gasOracle()", + "c473e7e8": "getExecutionFee(uint256,uint256,bytes)", + "c9a64e91": "interchainClient()", + "8da5cb5b": "owner()", + "715018a6": "renounceOwnership()", + "e4e06522": "requestExecution(uint256,uint256,bytes32,uint256,bytes)", + "2d54566c": "setExecutorEOA(address)", + "a87b8152": "setGasOracle(address)", + "27efcbb7": "setInterchainClient(address)", + "f2fde38b": "transferOwnership(address)", + }, + Bin: "0x608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610c95806100a56000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638da5cb5b11610081578063c9a64e911161005b578063c9a64e91146101ba578063e4e06522146101da578063f2fde38b146101ed57600080fd5b80638da5cb5b14610168578063a87b815214610186578063c473e7e81461019957600080fd5b80635d62a8dd116100b25780635d62a8dd146100f657806362014bad14610140578063715018a61461016057600080fd5b806327efcbb7146100ce5780632d54566c146100e3575b600080fd5b6100e16100dc366004610909565b610200565b005b6100e16100f1366004610909565b610277565b6003546101169073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6002546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16102ee565b60005473ffffffffffffffffffffffffffffffffffffffff16610116565b6100e1610194366004610909565b610302565b6101ac6101a7366004610a59565b610379565b604051908152602001610137565b6001546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16101e8366004610aa9565b6105c4565b6100e16101fb366004610909565b610737565b61020861079b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d6290600090a250565b61027f61079b565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b490600090a250565b6102f661079b565b61030060006107ee565b565b61030a61079b565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb9090600090a250565b600080600061038784610863565b90925090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff8316016105305760006103c185610885565b60035481516040517f5cbd3c48000000000000000000000000000000000000000000000000000000008152600481018b905260248101919091526044810189905291925060009173ffffffffffffffffffffffffffffffffffffffff90911690635cbd3c4890606401602060405180830381865afa158015610447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046b9190610b0d565b6020830151909150156105255760035460208301516040517f1e7b9287000000000000000000000000000000000000000000000000000000008152600481018b9052602481019190915273ffffffffffffffffffffffffffffffffffffffff90911690631e7b928790604401602060405180830381865afa1580156104f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105189190610b0d565b6105229082610b26565b90505b93506105bd92505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f556e737570706f72746564206f7074696f6e732076657273696f6e3a2076657260448201527f73696f6e206d757374206265204f5054494f4e535f563100000000000000000060648201526084015b60405180910390fd5b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461066b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f457865637574696f6e536572766963653a2063616c6c6572206973206e6f742060448201527f74686520496e746572636861696e436c69656e7400000000000000000000000060648201526084016105b4565b610676858583610379565b821015610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f457865637574696f6e536572766963653a20657865637574696f6e206665652060448201527f6973206e6f74206869676820656e6f756768000000000000000000000000000060648201526084016105b4565b60405183907f4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e745016850490600090a25050505050565b61073f61079b565b73ffffffffffffffffffffffffffffffffffffffff811661078f576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016105b4565b610798816107ee565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610300576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016105b4565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060608280602001905181019061087b9190610b66565b9094909350915050565b60408051808201909152600080825260208201526000806108a584610863565b9092509050600160ff831610156108ed576040517fbd91a21500000000000000000000000000000000000000000000000000000000815260ff831660048201526024016105b4565b808060200190518101906109019190610c10565b949350505050565b60006020828403121561091b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105bd57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b5576109b561093f565b604052919050565b600067ffffffffffffffff8211156109d7576109d761093f565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112610a1457600080fd5b8135610a27610a22826109bd565b61096e565b818152846020838601011115610a3c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610a6e57600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a9357600080fd5b610a9f86828701610a03565b9150509250925092565b600080600080600060a08688031215610ac157600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115610af457600080fd5b610b0088828901610a03565b9150509295509295909350565b600060208284031215610b1f57600080fd5b5051919050565b80820180821115610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60008060408385031215610b7957600080fd5b825160ff81168114610b8a57600080fd5b8092505060208084015167ffffffffffffffff811115610ba957600080fd5b8401601f81018613610bba57600080fd5b8051610bc8610a22826109bd565b8181528784838501011115610bdc57600080fd5b60005b82811015610bfa578381018501518282018601528401610bdf565b5060009181019093015250919491935090915050565b600060408284031215610c2257600080fd5b6040516040810181811067ffffffffffffffff82111715610c4557610c4561093f565b60405282518152602092830151928101929092525091905056fea264697066735822122095bc76308f5ab8df49d2f86f8e2e3d0c41f912da2d9ab421958c9a73554d373a64736f6c63430008140033", +} + +// ExecutionServiceABI is the input ABI used to generate the binding from. +// Deprecated: Use ExecutionServiceMetaData.ABI instead. +var ExecutionServiceABI = ExecutionServiceMetaData.ABI + +// Deprecated: Use ExecutionServiceMetaData.Sigs instead. +// ExecutionServiceFuncSigs maps the 4-byte function signature to its string representation. +var ExecutionServiceFuncSigs = ExecutionServiceMetaData.Sigs + +// ExecutionServiceBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ExecutionServiceMetaData.Bin instead. +var ExecutionServiceBin = ExecutionServiceMetaData.Bin + +// DeployExecutionService deploys a new Ethereum contract, binding an instance of ExecutionService to it. +func DeployExecutionService(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ExecutionService, error) { + parsed, err := ExecutionServiceMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ExecutionServiceBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ExecutionService{ExecutionServiceCaller: ExecutionServiceCaller{contract: contract}, ExecutionServiceTransactor: ExecutionServiceTransactor{contract: contract}, ExecutionServiceFilterer: ExecutionServiceFilterer{contract: contract}}, nil +} + +// ExecutionService is an auto generated Go binding around an Ethereum contract. +type ExecutionService struct { + ExecutionServiceCaller // Read-only binding to the contract + ExecutionServiceTransactor // Write-only binding to the contract + ExecutionServiceFilterer // Log filterer for contract events +} + +// ExecutionServiceCaller is an auto generated read-only Go binding around an Ethereum contract. +type ExecutionServiceCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ExecutionServiceTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ExecutionServiceFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ExecutionServiceSession struct { + Contract *ExecutionService // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExecutionServiceCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ExecutionServiceCallerSession struct { + Contract *ExecutionServiceCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ExecutionServiceTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ExecutionServiceTransactorSession struct { + Contract *ExecutionServiceTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExecutionServiceRaw is an auto generated low-level Go binding around an Ethereum contract. +type ExecutionServiceRaw struct { + Contract *ExecutionService // Generic contract binding to access the raw methods on +} + +// ExecutionServiceCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ExecutionServiceCallerRaw struct { + Contract *ExecutionServiceCaller // Generic read-only contract binding to access the raw methods on +} + +// ExecutionServiceTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ExecutionServiceTransactorRaw struct { + Contract *ExecutionServiceTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewExecutionService creates a new instance of ExecutionService, bound to a specific deployed contract. +func NewExecutionService(address common.Address, backend bind.ContractBackend) (*ExecutionService, error) { + contract, err := bindExecutionService(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ExecutionService{ExecutionServiceCaller: ExecutionServiceCaller{contract: contract}, ExecutionServiceTransactor: ExecutionServiceTransactor{contract: contract}, ExecutionServiceFilterer: ExecutionServiceFilterer{contract: contract}}, nil +} + +// NewExecutionServiceCaller creates a new read-only instance of ExecutionService, bound to a specific deployed contract. +func NewExecutionServiceCaller(address common.Address, caller bind.ContractCaller) (*ExecutionServiceCaller, error) { + contract, err := bindExecutionService(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ExecutionServiceCaller{contract: contract}, nil +} + +// NewExecutionServiceTransactor creates a new write-only instance of ExecutionService, bound to a specific deployed contract. +func NewExecutionServiceTransactor(address common.Address, transactor bind.ContractTransactor) (*ExecutionServiceTransactor, error) { + contract, err := bindExecutionService(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ExecutionServiceTransactor{contract: contract}, nil +} + +// NewExecutionServiceFilterer creates a new log filterer instance of ExecutionService, bound to a specific deployed contract. +func NewExecutionServiceFilterer(address common.Address, filterer bind.ContractFilterer) (*ExecutionServiceFilterer, error) { + contract, err := bindExecutionService(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ExecutionServiceFilterer{contract: contract}, nil +} + +// bindExecutionService binds a generic wrapper to an already deployed contract. +func bindExecutionService(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ExecutionServiceMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExecutionService *ExecutionServiceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExecutionService.Contract.ExecutionServiceCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExecutionService *ExecutionServiceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExecutionService.Contract.ExecutionServiceTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExecutionService *ExecutionServiceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExecutionService.Contract.ExecutionServiceTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExecutionService *ExecutionServiceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExecutionService.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExecutionService *ExecutionServiceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExecutionService.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExecutionService *ExecutionServiceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExecutionService.Contract.contract.Transact(opts, method, params...) +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_ExecutionService *ExecutionServiceCaller) ExecutorEOA(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ExecutionService.contract.Call(opts, &out, "executorEOA") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_ExecutionService *ExecutionServiceSession) ExecutorEOA() (common.Address, error) { + return _ExecutionService.Contract.ExecutorEOA(&_ExecutionService.CallOpts) +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_ExecutionService *ExecutionServiceCallerSession) ExecutorEOA() (common.Address, error) { + return _ExecutionService.Contract.ExecutorEOA(&_ExecutionService.CallOpts) +} + +// GasOracle is a free data retrieval call binding the contract method 0x5d62a8dd. +// +// Solidity: function gasOracle() view returns(address) +func (_ExecutionService *ExecutionServiceCaller) GasOracle(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ExecutionService.contract.Call(opts, &out, "gasOracle") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GasOracle is a free data retrieval call binding the contract method 0x5d62a8dd. +// +// Solidity: function gasOracle() view returns(address) +func (_ExecutionService *ExecutionServiceSession) GasOracle() (common.Address, error) { + return _ExecutionService.Contract.GasOracle(&_ExecutionService.CallOpts) +} + +// GasOracle is a free data retrieval call binding the contract method 0x5d62a8dd. +// +// Solidity: function gasOracle() view returns(address) +func (_ExecutionService *ExecutionServiceCallerSession) GasOracle() (common.Address, error) { + return _ExecutionService.Contract.GasOracle(&_ExecutionService.CallOpts) +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_ExecutionService *ExecutionServiceCaller) GetExecutionFee(opts *bind.CallOpts, dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + var out []interface{} + err := _ExecutionService.contract.Call(opts, &out, "getExecutionFee", dstChainId, txPayloadSize, options) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_ExecutionService *ExecutionServiceSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + return _ExecutionService.Contract.GetExecutionFee(&_ExecutionService.CallOpts, dstChainId, txPayloadSize, options) +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_ExecutionService *ExecutionServiceCallerSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + return _ExecutionService.Contract.GetExecutionFee(&_ExecutionService.CallOpts, dstChainId, txPayloadSize, options) +} + +// InterchainClient is a free data retrieval call binding the contract method 0xc9a64e91. +// +// Solidity: function interchainClient() view returns(address) +func (_ExecutionService *ExecutionServiceCaller) InterchainClient(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ExecutionService.contract.Call(opts, &out, "interchainClient") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// InterchainClient is a free data retrieval call binding the contract method 0xc9a64e91. +// +// Solidity: function interchainClient() view returns(address) +func (_ExecutionService *ExecutionServiceSession) InterchainClient() (common.Address, error) { + return _ExecutionService.Contract.InterchainClient(&_ExecutionService.CallOpts) +} + +// InterchainClient is a free data retrieval call binding the contract method 0xc9a64e91. +// +// Solidity: function interchainClient() view returns(address) +func (_ExecutionService *ExecutionServiceCallerSession) InterchainClient() (common.Address, error) { + return _ExecutionService.Contract.InterchainClient(&_ExecutionService.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ExecutionService *ExecutionServiceCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ExecutionService.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ExecutionService *ExecutionServiceSession) Owner() (common.Address, error) { + return _ExecutionService.Contract.Owner(&_ExecutionService.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ExecutionService *ExecutionServiceCallerSession) Owner() (common.Address, error) { + return _ExecutionService.Contract.Owner(&_ExecutionService.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ExecutionService *ExecutionServiceTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ExecutionService *ExecutionServiceSession) RenounceOwnership() (*types.Transaction, error) { + return _ExecutionService.Contract.RenounceOwnership(&_ExecutionService.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ExecutionService *ExecutionServiceTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _ExecutionService.Contract.RenounceOwnership(&_ExecutionService.TransactOpts) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_ExecutionService *ExecutionServiceTransactor) RequestExecution(opts *bind.TransactOpts, dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "requestExecution", dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_ExecutionService *ExecutionServiceSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _ExecutionService.Contract.RequestExecution(&_ExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_ExecutionService *ExecutionServiceTransactorSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _ExecutionService.Contract.RequestExecution(&_ExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// SetExecutorEOA is a paid mutator transaction binding the contract method 0x2d54566c. +// +// Solidity: function setExecutorEOA(address _executorEOA) returns() +func (_ExecutionService *ExecutionServiceTransactor) SetExecutorEOA(opts *bind.TransactOpts, _executorEOA common.Address) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "setExecutorEOA", _executorEOA) +} + +// SetExecutorEOA is a paid mutator transaction binding the contract method 0x2d54566c. +// +// Solidity: function setExecutorEOA(address _executorEOA) returns() +func (_ExecutionService *ExecutionServiceSession) SetExecutorEOA(_executorEOA common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetExecutorEOA(&_ExecutionService.TransactOpts, _executorEOA) +} + +// SetExecutorEOA is a paid mutator transaction binding the contract method 0x2d54566c. +// +// Solidity: function setExecutorEOA(address _executorEOA) returns() +func (_ExecutionService *ExecutionServiceTransactorSession) SetExecutorEOA(_executorEOA common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetExecutorEOA(&_ExecutionService.TransactOpts, _executorEOA) +} + +// SetGasOracle is a paid mutator transaction binding the contract method 0xa87b8152. +// +// Solidity: function setGasOracle(address _gasOracle) returns() +func (_ExecutionService *ExecutionServiceTransactor) SetGasOracle(opts *bind.TransactOpts, _gasOracle common.Address) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "setGasOracle", _gasOracle) +} + +// SetGasOracle is a paid mutator transaction binding the contract method 0xa87b8152. +// +// Solidity: function setGasOracle(address _gasOracle) returns() +func (_ExecutionService *ExecutionServiceSession) SetGasOracle(_gasOracle common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetGasOracle(&_ExecutionService.TransactOpts, _gasOracle) +} + +// SetGasOracle is a paid mutator transaction binding the contract method 0xa87b8152. +// +// Solidity: function setGasOracle(address _gasOracle) returns() +func (_ExecutionService *ExecutionServiceTransactorSession) SetGasOracle(_gasOracle common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetGasOracle(&_ExecutionService.TransactOpts, _gasOracle) +} + +// SetInterchainClient is a paid mutator transaction binding the contract method 0x27efcbb7. +// +// Solidity: function setInterchainClient(address _interchainClient) returns() +func (_ExecutionService *ExecutionServiceTransactor) SetInterchainClient(opts *bind.TransactOpts, _interchainClient common.Address) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "setInterchainClient", _interchainClient) +} + +// SetInterchainClient is a paid mutator transaction binding the contract method 0x27efcbb7. +// +// Solidity: function setInterchainClient(address _interchainClient) returns() +func (_ExecutionService *ExecutionServiceSession) SetInterchainClient(_interchainClient common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetInterchainClient(&_ExecutionService.TransactOpts, _interchainClient) +} + +// SetInterchainClient is a paid mutator transaction binding the contract method 0x27efcbb7. +// +// Solidity: function setInterchainClient(address _interchainClient) returns() +func (_ExecutionService *ExecutionServiceTransactorSession) SetInterchainClient(_interchainClient common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.SetInterchainClient(&_ExecutionService.TransactOpts, _interchainClient) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ExecutionService *ExecutionServiceTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _ExecutionService.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ExecutionService *ExecutionServiceSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.TransferOwnership(&_ExecutionService.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ExecutionService *ExecutionServiceTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ExecutionService.Contract.TransferOwnership(&_ExecutionService.TransactOpts, newOwner) +} + +// ExecutionServiceExecutionRequestedIterator is returned from FilterExecutionRequested and is used to iterate over the raw logs and unpacked data for ExecutionRequested events raised by the ExecutionService contract. +type ExecutionServiceExecutionRequestedIterator struct { + Event *ExecutionServiceExecutionRequested // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceExecutionRequestedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceExecutionRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceExecutionRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceExecutionRequestedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceExecutionRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceExecutionRequested represents a ExecutionRequested event raised by the ExecutionService contract. +type ExecutionServiceExecutionRequested struct { + TransactionId [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterExecutionRequested is a free log retrieval operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionService *ExecutionServiceFilterer) FilterExecutionRequested(opts *bind.FilterOpts, transactionId [][32]byte) (*ExecutionServiceExecutionRequestedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + + logs, sub, err := _ExecutionService.contract.FilterLogs(opts, "ExecutionRequested", transactionIdRule) + if err != nil { + return nil, err + } + return &ExecutionServiceExecutionRequestedIterator{contract: _ExecutionService.contract, event: "ExecutionRequested", logs: logs, sub: sub}, nil +} + +// WatchExecutionRequested is a free log subscription operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionService *ExecutionServiceFilterer) WatchExecutionRequested(opts *bind.WatchOpts, sink chan<- *ExecutionServiceExecutionRequested, transactionId [][32]byte) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + + logs, sub, err := _ExecutionService.contract.WatchLogs(opts, "ExecutionRequested", transactionIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceExecutionRequested) + if err := _ExecutionService.contract.UnpackLog(event, "ExecutionRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseExecutionRequested is a log parse operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionService *ExecutionServiceFilterer) ParseExecutionRequested(log types.Log) (*ExecutionServiceExecutionRequested, error) { + event := new(ExecutionServiceExecutionRequested) + if err := _ExecutionService.contract.UnpackLog(event, "ExecutionRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceExecutorEOAUpdatedIterator is returned from FilterExecutorEOAUpdated and is used to iterate over the raw logs and unpacked data for ExecutorEOAUpdated events raised by the ExecutionService contract. +type ExecutionServiceExecutorEOAUpdatedIterator struct { + Event *ExecutionServiceExecutorEOAUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceExecutorEOAUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceExecutorEOAUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceExecutorEOAUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceExecutorEOAUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceExecutorEOAUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceExecutorEOAUpdated represents a ExecutorEOAUpdated event raised by the ExecutionService contract. +type ExecutionServiceExecutorEOAUpdated struct { + ExecutorEOA common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterExecutorEOAUpdated is a free log retrieval operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionService *ExecutionServiceFilterer) FilterExecutorEOAUpdated(opts *bind.FilterOpts, executorEOA []common.Address) (*ExecutionServiceExecutorEOAUpdatedIterator, error) { + + var executorEOARule []interface{} + for _, executorEOAItem := range executorEOA { + executorEOARule = append(executorEOARule, executorEOAItem) + } + + logs, sub, err := _ExecutionService.contract.FilterLogs(opts, "ExecutorEOAUpdated", executorEOARule) + if err != nil { + return nil, err + } + return &ExecutionServiceExecutorEOAUpdatedIterator{contract: _ExecutionService.contract, event: "ExecutorEOAUpdated", logs: logs, sub: sub}, nil +} + +// WatchExecutorEOAUpdated is a free log subscription operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionService *ExecutionServiceFilterer) WatchExecutorEOAUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceExecutorEOAUpdated, executorEOA []common.Address) (event.Subscription, error) { + + var executorEOARule []interface{} + for _, executorEOAItem := range executorEOA { + executorEOARule = append(executorEOARule, executorEOAItem) + } + + logs, sub, err := _ExecutionService.contract.WatchLogs(opts, "ExecutorEOAUpdated", executorEOARule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceExecutorEOAUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "ExecutorEOAUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseExecutorEOAUpdated is a log parse operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionService *ExecutionServiceFilterer) ParseExecutorEOAUpdated(log types.Log) (*ExecutionServiceExecutorEOAUpdated, error) { + event := new(ExecutionServiceExecutorEOAUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "ExecutorEOAUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceGasOracleUpdatedIterator is returned from FilterGasOracleUpdated and is used to iterate over the raw logs and unpacked data for GasOracleUpdated events raised by the ExecutionService contract. +type ExecutionServiceGasOracleUpdatedIterator struct { + Event *ExecutionServiceGasOracleUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceGasOracleUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceGasOracleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceGasOracleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceGasOracleUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceGasOracleUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceGasOracleUpdated represents a GasOracleUpdated event raised by the ExecutionService contract. +type ExecutionServiceGasOracleUpdated struct { + GasOracle common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterGasOracleUpdated is a free log retrieval operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionService *ExecutionServiceFilterer) FilterGasOracleUpdated(opts *bind.FilterOpts, gasOracle []common.Address) (*ExecutionServiceGasOracleUpdatedIterator, error) { + + var gasOracleRule []interface{} + for _, gasOracleItem := range gasOracle { + gasOracleRule = append(gasOracleRule, gasOracleItem) + } + + logs, sub, err := _ExecutionService.contract.FilterLogs(opts, "GasOracleUpdated", gasOracleRule) + if err != nil { + return nil, err + } + return &ExecutionServiceGasOracleUpdatedIterator{contract: _ExecutionService.contract, event: "GasOracleUpdated", logs: logs, sub: sub}, nil +} + +// WatchGasOracleUpdated is a free log subscription operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionService *ExecutionServiceFilterer) WatchGasOracleUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceGasOracleUpdated, gasOracle []common.Address) (event.Subscription, error) { + + var gasOracleRule []interface{} + for _, gasOracleItem := range gasOracle { + gasOracleRule = append(gasOracleRule, gasOracleItem) + } + + logs, sub, err := _ExecutionService.contract.WatchLogs(opts, "GasOracleUpdated", gasOracleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceGasOracleUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "GasOracleUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseGasOracleUpdated is a log parse operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionService *ExecutionServiceFilterer) ParseGasOracleUpdated(log types.Log) (*ExecutionServiceGasOracleUpdated, error) { + event := new(ExecutionServiceGasOracleUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "GasOracleUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceInterchainClientUpdatedIterator is returned from FilterInterchainClientUpdated and is used to iterate over the raw logs and unpacked data for InterchainClientUpdated events raised by the ExecutionService contract. +type ExecutionServiceInterchainClientUpdatedIterator struct { + Event *ExecutionServiceInterchainClientUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceInterchainClientUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceInterchainClientUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceInterchainClientUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceInterchainClientUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceInterchainClientUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceInterchainClientUpdated represents a InterchainClientUpdated event raised by the ExecutionService contract. +type ExecutionServiceInterchainClientUpdated struct { + InterchainClient common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInterchainClientUpdated is a free log retrieval operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionService *ExecutionServiceFilterer) FilterInterchainClientUpdated(opts *bind.FilterOpts, interchainClient []common.Address) (*ExecutionServiceInterchainClientUpdatedIterator, error) { + + var interchainClientRule []interface{} + for _, interchainClientItem := range interchainClient { + interchainClientRule = append(interchainClientRule, interchainClientItem) + } + + logs, sub, err := _ExecutionService.contract.FilterLogs(opts, "InterchainClientUpdated", interchainClientRule) + if err != nil { + return nil, err + } + return &ExecutionServiceInterchainClientUpdatedIterator{contract: _ExecutionService.contract, event: "InterchainClientUpdated", logs: logs, sub: sub}, nil +} + +// WatchInterchainClientUpdated is a free log subscription operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionService *ExecutionServiceFilterer) WatchInterchainClientUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceInterchainClientUpdated, interchainClient []common.Address) (event.Subscription, error) { + + var interchainClientRule []interface{} + for _, interchainClientItem := range interchainClient { + interchainClientRule = append(interchainClientRule, interchainClientItem) + } + + logs, sub, err := _ExecutionService.contract.WatchLogs(opts, "InterchainClientUpdated", interchainClientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceInterchainClientUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "InterchainClientUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInterchainClientUpdated is a log parse operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionService *ExecutionServiceFilterer) ParseInterchainClientUpdated(log types.Log) (*ExecutionServiceInterchainClientUpdated, error) { + event := new(ExecutionServiceInterchainClientUpdated) + if err := _ExecutionService.contract.UnpackLog(event, "InterchainClientUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the ExecutionService contract. +type ExecutionServiceOwnershipTransferredIterator struct { + Event *ExecutionServiceOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceOwnershipTransferred represents a OwnershipTransferred event raised by the ExecutionService contract. +type ExecutionServiceOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ExecutionService *ExecutionServiceFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ExecutionServiceOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ExecutionService.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &ExecutionServiceOwnershipTransferredIterator{contract: _ExecutionService.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ExecutionService *ExecutionServiceFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ExecutionServiceOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ExecutionService.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceOwnershipTransferred) + if err := _ExecutionService.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ExecutionService *ExecutionServiceFilterer) ParseOwnershipTransferred(log types.Log) (*ExecutionServiceOwnershipTransferred, error) { + event := new(ExecutionServiceOwnershipTransferred) + if err := _ExecutionService.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceEventsMetaData contains all meta data concerning the ExecutionServiceEvents contract. +var ExecutionServiceEventsMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"ExecutionRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executorEOA\",\"type\":\"address\"}],\"name\":\"ExecutorEOAUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gasOracle\",\"type\":\"address\"}],\"name\":\"GasOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"interchainClient\",\"type\":\"address\"}],\"name\":\"InterchainClientUpdated\",\"type\":\"event\"}]", +} + +// ExecutionServiceEventsABI is the input ABI used to generate the binding from. +// Deprecated: Use ExecutionServiceEventsMetaData.ABI instead. +var ExecutionServiceEventsABI = ExecutionServiceEventsMetaData.ABI + +// ExecutionServiceEvents is an auto generated Go binding around an Ethereum contract. +type ExecutionServiceEvents struct { + ExecutionServiceEventsCaller // Read-only binding to the contract + ExecutionServiceEventsTransactor // Write-only binding to the contract + ExecutionServiceEventsFilterer // Log filterer for contract events +} + +// ExecutionServiceEventsCaller is an auto generated read-only Go binding around an Ethereum contract. +type ExecutionServiceEventsCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceEventsTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ExecutionServiceEventsTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceEventsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ExecutionServiceEventsFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ExecutionServiceEventsSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ExecutionServiceEventsSession struct { + Contract *ExecutionServiceEvents // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExecutionServiceEventsCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ExecutionServiceEventsCallerSession struct { + Contract *ExecutionServiceEventsCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ExecutionServiceEventsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ExecutionServiceEventsTransactorSession struct { + Contract *ExecutionServiceEventsTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ExecutionServiceEventsRaw is an auto generated low-level Go binding around an Ethereum contract. +type ExecutionServiceEventsRaw struct { + Contract *ExecutionServiceEvents // Generic contract binding to access the raw methods on +} + +// ExecutionServiceEventsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ExecutionServiceEventsCallerRaw struct { + Contract *ExecutionServiceEventsCaller // Generic read-only contract binding to access the raw methods on +} + +// ExecutionServiceEventsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ExecutionServiceEventsTransactorRaw struct { + Contract *ExecutionServiceEventsTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewExecutionServiceEvents creates a new instance of ExecutionServiceEvents, bound to a specific deployed contract. +func NewExecutionServiceEvents(address common.Address, backend bind.ContractBackend) (*ExecutionServiceEvents, error) { + contract, err := bindExecutionServiceEvents(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ExecutionServiceEvents{ExecutionServiceEventsCaller: ExecutionServiceEventsCaller{contract: contract}, ExecutionServiceEventsTransactor: ExecutionServiceEventsTransactor{contract: contract}, ExecutionServiceEventsFilterer: ExecutionServiceEventsFilterer{contract: contract}}, nil +} + +// NewExecutionServiceEventsCaller creates a new read-only instance of ExecutionServiceEvents, bound to a specific deployed contract. +func NewExecutionServiceEventsCaller(address common.Address, caller bind.ContractCaller) (*ExecutionServiceEventsCaller, error) { + contract, err := bindExecutionServiceEvents(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsCaller{contract: contract}, nil +} + +// NewExecutionServiceEventsTransactor creates a new write-only instance of ExecutionServiceEvents, bound to a specific deployed contract. +func NewExecutionServiceEventsTransactor(address common.Address, transactor bind.ContractTransactor) (*ExecutionServiceEventsTransactor, error) { + contract, err := bindExecutionServiceEvents(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsTransactor{contract: contract}, nil +} + +// NewExecutionServiceEventsFilterer creates a new log filterer instance of ExecutionServiceEvents, bound to a specific deployed contract. +func NewExecutionServiceEventsFilterer(address common.Address, filterer bind.ContractFilterer) (*ExecutionServiceEventsFilterer, error) { + contract, err := bindExecutionServiceEvents(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsFilterer{contract: contract}, nil +} + +// bindExecutionServiceEvents binds a generic wrapper to an already deployed contract. +func bindExecutionServiceEvents(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ExecutionServiceEventsMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExecutionServiceEvents *ExecutionServiceEventsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExecutionServiceEvents.Contract.ExecutionServiceEventsCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExecutionServiceEvents *ExecutionServiceEventsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExecutionServiceEvents.Contract.ExecutionServiceEventsTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExecutionServiceEvents *ExecutionServiceEventsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExecutionServiceEvents.Contract.ExecutionServiceEventsTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ExecutionServiceEvents *ExecutionServiceEventsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ExecutionServiceEvents.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ExecutionServiceEvents *ExecutionServiceEventsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ExecutionServiceEvents.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ExecutionServiceEvents *ExecutionServiceEventsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ExecutionServiceEvents.Contract.contract.Transact(opts, method, params...) +} + +// ExecutionServiceEventsExecutionRequestedIterator is returned from FilterExecutionRequested and is used to iterate over the raw logs and unpacked data for ExecutionRequested events raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsExecutionRequestedIterator struct { + Event *ExecutionServiceEventsExecutionRequested // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceEventsExecutionRequestedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsExecutionRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsExecutionRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceEventsExecutionRequestedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceEventsExecutionRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceEventsExecutionRequested represents a ExecutionRequested event raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsExecutionRequested struct { + TransactionId [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterExecutionRequested is a free log retrieval operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) FilterExecutionRequested(opts *bind.FilterOpts, transactionId [][32]byte) (*ExecutionServiceEventsExecutionRequestedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.FilterLogs(opts, "ExecutionRequested", transactionIdRule) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsExecutionRequestedIterator{contract: _ExecutionServiceEvents.contract, event: "ExecutionRequested", logs: logs, sub: sub}, nil +} + +// WatchExecutionRequested is a free log subscription operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) WatchExecutionRequested(opts *bind.WatchOpts, sink chan<- *ExecutionServiceEventsExecutionRequested, transactionId [][32]byte) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.WatchLogs(opts, "ExecutionRequested", transactionIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceEventsExecutionRequested) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "ExecutionRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseExecutionRequested is a log parse operation binding the contract event 0x4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e7450168504. +// +// Solidity: event ExecutionRequested(bytes32 indexed transactionId) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) ParseExecutionRequested(log types.Log) (*ExecutionServiceEventsExecutionRequested, error) { + event := new(ExecutionServiceEventsExecutionRequested) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "ExecutionRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceEventsExecutorEOAUpdatedIterator is returned from FilterExecutorEOAUpdated and is used to iterate over the raw logs and unpacked data for ExecutorEOAUpdated events raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsExecutorEOAUpdatedIterator struct { + Event *ExecutionServiceEventsExecutorEOAUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceEventsExecutorEOAUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsExecutorEOAUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsExecutorEOAUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceEventsExecutorEOAUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceEventsExecutorEOAUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceEventsExecutorEOAUpdated represents a ExecutorEOAUpdated event raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsExecutorEOAUpdated struct { + ExecutorEOA common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterExecutorEOAUpdated is a free log retrieval operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) FilterExecutorEOAUpdated(opts *bind.FilterOpts, executorEOA []common.Address) (*ExecutionServiceEventsExecutorEOAUpdatedIterator, error) { + + var executorEOARule []interface{} + for _, executorEOAItem := range executorEOA { + executorEOARule = append(executorEOARule, executorEOAItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.FilterLogs(opts, "ExecutorEOAUpdated", executorEOARule) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsExecutorEOAUpdatedIterator{contract: _ExecutionServiceEvents.contract, event: "ExecutorEOAUpdated", logs: logs, sub: sub}, nil +} + +// WatchExecutorEOAUpdated is a free log subscription operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) WatchExecutorEOAUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceEventsExecutorEOAUpdated, executorEOA []common.Address) (event.Subscription, error) { + + var executorEOARule []interface{} + for _, executorEOAItem := range executorEOA { + executorEOARule = append(executorEOARule, executorEOAItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.WatchLogs(opts, "ExecutorEOAUpdated", executorEOARule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceEventsExecutorEOAUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "ExecutorEOAUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseExecutorEOAUpdated is a log parse operation binding the contract event 0x8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b4. +// +// Solidity: event ExecutorEOAUpdated(address indexed executorEOA) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) ParseExecutorEOAUpdated(log types.Log) (*ExecutionServiceEventsExecutorEOAUpdated, error) { + event := new(ExecutionServiceEventsExecutorEOAUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "ExecutorEOAUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceEventsGasOracleUpdatedIterator is returned from FilterGasOracleUpdated and is used to iterate over the raw logs and unpacked data for GasOracleUpdated events raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsGasOracleUpdatedIterator struct { + Event *ExecutionServiceEventsGasOracleUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceEventsGasOracleUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsGasOracleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsGasOracleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceEventsGasOracleUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceEventsGasOracleUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceEventsGasOracleUpdated represents a GasOracleUpdated event raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsGasOracleUpdated struct { + GasOracle common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterGasOracleUpdated is a free log retrieval operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) FilterGasOracleUpdated(opts *bind.FilterOpts, gasOracle []common.Address) (*ExecutionServiceEventsGasOracleUpdatedIterator, error) { + + var gasOracleRule []interface{} + for _, gasOracleItem := range gasOracle { + gasOracleRule = append(gasOracleRule, gasOracleItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.FilterLogs(opts, "GasOracleUpdated", gasOracleRule) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsGasOracleUpdatedIterator{contract: _ExecutionServiceEvents.contract, event: "GasOracleUpdated", logs: logs, sub: sub}, nil +} + +// WatchGasOracleUpdated is a free log subscription operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) WatchGasOracleUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceEventsGasOracleUpdated, gasOracle []common.Address) (event.Subscription, error) { + + var gasOracleRule []interface{} + for _, gasOracleItem := range gasOracle { + gasOracleRule = append(gasOracleRule, gasOracleItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.WatchLogs(opts, "GasOracleUpdated", gasOracleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceEventsGasOracleUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "GasOracleUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseGasOracleUpdated is a log parse operation binding the contract event 0x0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb90. +// +// Solidity: event GasOracleUpdated(address indexed gasOracle) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) ParseGasOracleUpdated(log types.Log) (*ExecutionServiceEventsGasOracleUpdated, error) { + event := new(ExecutionServiceEventsGasOracleUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "GasOracleUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ExecutionServiceEventsInterchainClientUpdatedIterator is returned from FilterInterchainClientUpdated and is used to iterate over the raw logs and unpacked data for InterchainClientUpdated events raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsInterchainClientUpdatedIterator struct { + Event *ExecutionServiceEventsInterchainClientUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ExecutionServiceEventsInterchainClientUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsInterchainClientUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ExecutionServiceEventsInterchainClientUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ExecutionServiceEventsInterchainClientUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ExecutionServiceEventsInterchainClientUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ExecutionServiceEventsInterchainClientUpdated represents a InterchainClientUpdated event raised by the ExecutionServiceEvents contract. +type ExecutionServiceEventsInterchainClientUpdated struct { + InterchainClient common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInterchainClientUpdated is a free log retrieval operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) FilterInterchainClientUpdated(opts *bind.FilterOpts, interchainClient []common.Address) (*ExecutionServiceEventsInterchainClientUpdatedIterator, error) { + + var interchainClientRule []interface{} + for _, interchainClientItem := range interchainClient { + interchainClientRule = append(interchainClientRule, interchainClientItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.FilterLogs(opts, "InterchainClientUpdated", interchainClientRule) + if err != nil { + return nil, err + } + return &ExecutionServiceEventsInterchainClientUpdatedIterator{contract: _ExecutionServiceEvents.contract, event: "InterchainClientUpdated", logs: logs, sub: sub}, nil +} + +// WatchInterchainClientUpdated is a free log subscription operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) WatchInterchainClientUpdated(opts *bind.WatchOpts, sink chan<- *ExecutionServiceEventsInterchainClientUpdated, interchainClient []common.Address) (event.Subscription, error) { + + var interchainClientRule []interface{} + for _, interchainClientItem := range interchainClient { + interchainClientRule = append(interchainClientRule, interchainClientItem) + } + + logs, sub, err := _ExecutionServiceEvents.contract.WatchLogs(opts, "InterchainClientUpdated", interchainClientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ExecutionServiceEventsInterchainClientUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "InterchainClientUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInterchainClientUpdated is a log parse operation binding the contract event 0x33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d62. +// +// Solidity: event InterchainClientUpdated(address indexed interchainClient) +func (_ExecutionServiceEvents *ExecutionServiceEventsFilterer) ParseInterchainClientUpdated(log types.Log) (*ExecutionServiceEventsInterchainClientUpdated, error) { + event := new(ExecutionServiceEventsInterchainClientUpdated) + if err := _ExecutionServiceEvents.contract.UnpackLog(event, "InterchainClientUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IExecutionServiceMetaData contains all meta data concerning the IExecutionService contract. +var IExecutionServiceMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "62014bad": "executorEOA()", + "c473e7e8": "getExecutionFee(uint256,uint256,bytes)", + "e4e06522": "requestExecution(uint256,uint256,bytes32,uint256,bytes)", + }, +} + +// IExecutionServiceABI is the input ABI used to generate the binding from. +// Deprecated: Use IExecutionServiceMetaData.ABI instead. +var IExecutionServiceABI = IExecutionServiceMetaData.ABI + +// Deprecated: Use IExecutionServiceMetaData.Sigs instead. +// IExecutionServiceFuncSigs maps the 4-byte function signature to its string representation. +var IExecutionServiceFuncSigs = IExecutionServiceMetaData.Sigs + +// IExecutionService is an auto generated Go binding around an Ethereum contract. +type IExecutionService struct { + IExecutionServiceCaller // Read-only binding to the contract + IExecutionServiceTransactor // Write-only binding to the contract + IExecutionServiceFilterer // Log filterer for contract events +} + +// IExecutionServiceCaller is an auto generated read-only Go binding around an Ethereum contract. +type IExecutionServiceCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IExecutionServiceTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IExecutionServiceTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IExecutionServiceFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IExecutionServiceFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IExecutionServiceSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IExecutionServiceSession struct { + Contract *IExecutionService // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IExecutionServiceCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IExecutionServiceCallerSession struct { + Contract *IExecutionServiceCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IExecutionServiceTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IExecutionServiceTransactorSession struct { + Contract *IExecutionServiceTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IExecutionServiceRaw is an auto generated low-level Go binding around an Ethereum contract. +type IExecutionServiceRaw struct { + Contract *IExecutionService // Generic contract binding to access the raw methods on +} + +// IExecutionServiceCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IExecutionServiceCallerRaw struct { + Contract *IExecutionServiceCaller // Generic read-only contract binding to access the raw methods on +} + +// IExecutionServiceTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IExecutionServiceTransactorRaw struct { + Contract *IExecutionServiceTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIExecutionService creates a new instance of IExecutionService, bound to a specific deployed contract. +func NewIExecutionService(address common.Address, backend bind.ContractBackend) (*IExecutionService, error) { + contract, err := bindIExecutionService(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IExecutionService{IExecutionServiceCaller: IExecutionServiceCaller{contract: contract}, IExecutionServiceTransactor: IExecutionServiceTransactor{contract: contract}, IExecutionServiceFilterer: IExecutionServiceFilterer{contract: contract}}, nil +} + +// NewIExecutionServiceCaller creates a new read-only instance of IExecutionService, bound to a specific deployed contract. +func NewIExecutionServiceCaller(address common.Address, caller bind.ContractCaller) (*IExecutionServiceCaller, error) { + contract, err := bindIExecutionService(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IExecutionServiceCaller{contract: contract}, nil +} + +// NewIExecutionServiceTransactor creates a new write-only instance of IExecutionService, bound to a specific deployed contract. +func NewIExecutionServiceTransactor(address common.Address, transactor bind.ContractTransactor) (*IExecutionServiceTransactor, error) { + contract, err := bindIExecutionService(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IExecutionServiceTransactor{contract: contract}, nil +} + +// NewIExecutionServiceFilterer creates a new log filterer instance of IExecutionService, bound to a specific deployed contract. +func NewIExecutionServiceFilterer(address common.Address, filterer bind.ContractFilterer) (*IExecutionServiceFilterer, error) { + contract, err := bindIExecutionService(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IExecutionServiceFilterer{contract: contract}, nil +} + +// bindIExecutionService binds a generic wrapper to an already deployed contract. +func bindIExecutionService(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IExecutionServiceMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IExecutionService *IExecutionServiceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IExecutionService.Contract.IExecutionServiceCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IExecutionService *IExecutionServiceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IExecutionService.Contract.IExecutionServiceTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IExecutionService *IExecutionServiceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IExecutionService.Contract.IExecutionServiceTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IExecutionService *IExecutionServiceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IExecutionService.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IExecutionService *IExecutionServiceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IExecutionService.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IExecutionService *IExecutionServiceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IExecutionService.Contract.contract.Transact(opts, method, params...) +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_IExecutionService *IExecutionServiceCaller) ExecutorEOA(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _IExecutionService.contract.Call(opts, &out, "executorEOA") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_IExecutionService *IExecutionServiceSession) ExecutorEOA() (common.Address, error) { + return _IExecutionService.Contract.ExecutorEOA(&_IExecutionService.CallOpts) +} + +// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. +// +// Solidity: function executorEOA() view returns(address) +func (_IExecutionService *IExecutionServiceCallerSession) ExecutorEOA() (common.Address, error) { + return _IExecutionService.Contract.ExecutorEOA(&_IExecutionService.CallOpts) +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_IExecutionService *IExecutionServiceCaller) GetExecutionFee(opts *bind.CallOpts, dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + var out []interface{} + err := _IExecutionService.contract.Call(opts, &out, "getExecutionFee", dstChainId, txPayloadSize, options) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_IExecutionService *IExecutionServiceSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + return _IExecutionService.Contract.GetExecutionFee(&_IExecutionService.CallOpts, dstChainId, txPayloadSize, options) +} + +// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. +// +// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) +func (_IExecutionService *IExecutionServiceCallerSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { + return _IExecutionService.Contract.GetExecutionFee(&_IExecutionService.CallOpts, dstChainId, txPayloadSize, options) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_IExecutionService *IExecutionServiceTransactor) RequestExecution(opts *bind.TransactOpts, dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _IExecutionService.contract.Transact(opts, "requestExecution", dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_IExecutionService *IExecutionServiceSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _IExecutionService.Contract.RequestExecution(&_IExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. +// +// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() +func (_IExecutionService *IExecutionServiceTransactorSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { + return _IExecutionService.Contract.RequestExecution(&_IExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) +} + +// IGasOracleMetaData contains all meta data concerning the IGasOracle contract. +var IGasOracleMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "1e7b9287": "convertRemoteValueToLocalUnits(uint256,uint256)", + "5cbd3c48": "estimateTxCostInLocalUnits(uint256,uint256,uint256)", + "fd6a7167": "estimateTxCostInRemoteUnits(uint256,uint256,uint256)", + }, +} + +// IGasOracleABI is the input ABI used to generate the binding from. +// Deprecated: Use IGasOracleMetaData.ABI instead. +var IGasOracleABI = IGasOracleMetaData.ABI + +// Deprecated: Use IGasOracleMetaData.Sigs instead. +// IGasOracleFuncSigs maps the 4-byte function signature to its string representation. +var IGasOracleFuncSigs = IGasOracleMetaData.Sigs + +// IGasOracle is an auto generated Go binding around an Ethereum contract. +type IGasOracle struct { + IGasOracleCaller // Read-only binding to the contract + IGasOracleTransactor // Write-only binding to the contract + IGasOracleFilterer // Log filterer for contract events +} + +// IGasOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type IGasOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IGasOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IGasOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IGasOracleSession struct { + Contract *IGasOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IGasOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IGasOracleCallerSession struct { + Contract *IGasOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IGasOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IGasOracleTransactorSession struct { + Contract *IGasOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IGasOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type IGasOracleRaw struct { + Contract *IGasOracle // Generic contract binding to access the raw methods on +} + +// IGasOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IGasOracleCallerRaw struct { + Contract *IGasOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// IGasOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IGasOracleTransactorRaw struct { + Contract *IGasOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIGasOracle creates a new instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracle(address common.Address, backend bind.ContractBackend) (*IGasOracle, error) { + contract, err := bindIGasOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IGasOracle{IGasOracleCaller: IGasOracleCaller{contract: contract}, IGasOracleTransactor: IGasOracleTransactor{contract: contract}, IGasOracleFilterer: IGasOracleFilterer{contract: contract}}, nil +} + +// NewIGasOracleCaller creates a new read-only instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleCaller(address common.Address, caller bind.ContractCaller) (*IGasOracleCaller, error) { + contract, err := bindIGasOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IGasOracleCaller{contract: contract}, nil +} + +// NewIGasOracleTransactor creates a new write-only instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*IGasOracleTransactor, error) { + contract, err := bindIGasOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IGasOracleTransactor{contract: contract}, nil +} + +// NewIGasOracleFilterer creates a new log filterer instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*IGasOracleFilterer, error) { + contract, err := bindIGasOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IGasOracleFilterer{contract: contract}, nil +} + +// bindIGasOracle binds a generic wrapper to an already deployed contract. +func bindIGasOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IGasOracleMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IGasOracle *IGasOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IGasOracle.Contract.IGasOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IGasOracle *IGasOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IGasOracle.Contract.IGasOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IGasOracle *IGasOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IGasOracle.Contract.IGasOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IGasOracle *IGasOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IGasOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IGasOracle *IGasOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IGasOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IGasOracle *IGasOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IGasOracle.Contract.contract.Transact(opts, method, params...) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) ConvertRemoteValueToLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "convertRemoteValueToLocalUnits", remoteChainId, value) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.ConvertRemoteValueToLocalUnits(&_IGasOracle.CallOpts, remoteChainId, value) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.ConvertRemoteValueToLocalUnits(&_IGasOracle.CallOpts, remoteChainId, value) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) EstimateTxCostInLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "estimateTxCostInLocalUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInLocalUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInLocalUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) EstimateTxCostInRemoteUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "estimateTxCostInRemoteUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInRemoteUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInRemoteUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// OptionsLibMetaData contains all meta data concerning the OptionsLib contract. +var OptionsLibMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"}]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205a22485b2583acad6f8c2c47520c8dc72b4859c134f0579480fb7948883dcbcf64736f6c63430008140033", +} + +// OptionsLibABI is the input ABI used to generate the binding from. +// Deprecated: Use OptionsLibMetaData.ABI instead. +var OptionsLibABI = OptionsLibMetaData.ABI + +// OptionsLibBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use OptionsLibMetaData.Bin instead. +var OptionsLibBin = OptionsLibMetaData.Bin + +// DeployOptionsLib deploys a new Ethereum contract, binding an instance of OptionsLib to it. +func DeployOptionsLib(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OptionsLib, error) { + parsed, err := OptionsLibMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OptionsLibBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OptionsLib{OptionsLibCaller: OptionsLibCaller{contract: contract}, OptionsLibTransactor: OptionsLibTransactor{contract: contract}, OptionsLibFilterer: OptionsLibFilterer{contract: contract}}, nil +} + +// OptionsLib is an auto generated Go binding around an Ethereum contract. +type OptionsLib struct { + OptionsLibCaller // Read-only binding to the contract + OptionsLibTransactor // Write-only binding to the contract + OptionsLibFilterer // Log filterer for contract events +} + +// OptionsLibCaller is an auto generated read-only Go binding around an Ethereum contract. +type OptionsLibCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptionsLibTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OptionsLibTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptionsLibFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OptionsLibFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptionsLibSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OptionsLibSession struct { + Contract *OptionsLib // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OptionsLibCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OptionsLibCallerSession struct { + Contract *OptionsLibCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OptionsLibTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OptionsLibTransactorSession struct { + Contract *OptionsLibTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OptionsLibRaw is an auto generated low-level Go binding around an Ethereum contract. +type OptionsLibRaw struct { + Contract *OptionsLib // Generic contract binding to access the raw methods on +} + +// OptionsLibCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OptionsLibCallerRaw struct { + Contract *OptionsLibCaller // Generic read-only contract binding to access the raw methods on +} + +// OptionsLibTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OptionsLibTransactorRaw struct { + Contract *OptionsLibTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOptionsLib creates a new instance of OptionsLib, bound to a specific deployed contract. +func NewOptionsLib(address common.Address, backend bind.ContractBackend) (*OptionsLib, error) { + contract, err := bindOptionsLib(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OptionsLib{OptionsLibCaller: OptionsLibCaller{contract: contract}, OptionsLibTransactor: OptionsLibTransactor{contract: contract}, OptionsLibFilterer: OptionsLibFilterer{contract: contract}}, nil +} + +// NewOptionsLibCaller creates a new read-only instance of OptionsLib, bound to a specific deployed contract. +func NewOptionsLibCaller(address common.Address, caller bind.ContractCaller) (*OptionsLibCaller, error) { + contract, err := bindOptionsLib(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OptionsLibCaller{contract: contract}, nil +} + +// NewOptionsLibTransactor creates a new write-only instance of OptionsLib, bound to a specific deployed contract. +func NewOptionsLibTransactor(address common.Address, transactor bind.ContractTransactor) (*OptionsLibTransactor, error) { + contract, err := bindOptionsLib(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OptionsLibTransactor{contract: contract}, nil +} + +// NewOptionsLibFilterer creates a new log filterer instance of OptionsLib, bound to a specific deployed contract. +func NewOptionsLibFilterer(address common.Address, filterer bind.ContractFilterer) (*OptionsLibFilterer, error) { + contract, err := bindOptionsLib(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OptionsLibFilterer{contract: contract}, nil +} + +// bindOptionsLib binds a generic wrapper to an already deployed contract. +func bindOptionsLib(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OptionsLibMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_OptionsLib *OptionsLibRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptionsLib.Contract.OptionsLibCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_OptionsLib *OptionsLibRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptionsLib.Contract.OptionsLibTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptionsLib *OptionsLibRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptionsLib.Contract.OptionsLibTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_OptionsLib *OptionsLibCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptionsLib.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_OptionsLib *OptionsLibTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptionsLib.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptionsLib *OptionsLibTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptionsLib.Contract.contract.Transact(opts, method, params...) +} + +// OwnableMetaData contains all meta data concerning the Ownable contract. +var OwnableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "8da5cb5b": "owner()", + "715018a6": "renounceOwnership()", + "f2fde38b": "transferOwnership(address)", + }, +} + +// OwnableABI is the input ABI used to generate the binding from. +// Deprecated: Use OwnableMetaData.ABI instead. +var OwnableABI = OwnableMetaData.ABI + +// Deprecated: Use OwnableMetaData.Sigs instead. +// OwnableFuncSigs maps the 4-byte function signature to its string representation. +var OwnableFuncSigs = OwnableMetaData.Sigs + +// Ownable is an auto generated Go binding around an Ethereum contract. +type Ownable struct { + OwnableCaller // Read-only binding to the contract + OwnableTransactor // Write-only binding to the contract + OwnableFilterer // Log filterer for contract events +} + +// OwnableCaller is an auto generated read-only Go binding around an Ethereum contract. +type OwnableCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type OwnableTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OwnableFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OwnableSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OwnableSession struct { + Contract *Ownable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OwnableCallerSession struct { + Contract *OwnableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OwnableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OwnableTransactorSession struct { + Contract *OwnableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OwnableRaw is an auto generated low-level Go binding around an Ethereum contract. +type OwnableRaw struct { + Contract *Ownable // Generic contract binding to access the raw methods on +} + +// OwnableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OwnableCallerRaw struct { + Contract *OwnableCaller // Generic read-only contract binding to access the raw methods on +} + +// OwnableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OwnableTransactorRaw struct { + Contract *OwnableTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewOwnable creates a new instance of Ownable, bound to a specific deployed contract. +func NewOwnable(address common.Address, backend bind.ContractBackend) (*Ownable, error) { + contract, err := bindOwnable(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ownable{OwnableCaller: OwnableCaller{contract: contract}, OwnableTransactor: OwnableTransactor{contract: contract}, OwnableFilterer: OwnableFilterer{contract: contract}}, nil +} + +// NewOwnableCaller creates a new read-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableCaller(address common.Address, caller bind.ContractCaller) (*OwnableCaller, error) { + contract, err := bindOwnable(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OwnableCaller{contract: contract}, nil +} + +// NewOwnableTransactor creates a new write-only instance of Ownable, bound to a specific deployed contract. +func NewOwnableTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnableTransactor, error) { + contract, err := bindOwnable(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OwnableTransactor{contract: contract}, nil +} + +// NewOwnableFilterer creates a new log filterer instance of Ownable, bound to a specific deployed contract. +func NewOwnableFilterer(address common.Address, filterer bind.ContractFilterer) (*OwnableFilterer, error) { + contract, err := bindOwnable(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OwnableFilterer{contract: contract}, nil +} + +// bindOwnable binds a generic wrapper to an already deployed contract. +func bindOwnable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OwnableMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ownable *OwnableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.Contract.OwnableCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ownable *OwnableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.OwnableTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Ownable *OwnableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ownable.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Ownable *OwnableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ownable *OwnableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ownable.Contract.contract.Transact(opts, method, params...) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ownable.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Ownable *OwnableCallerSession) Owner() (common.Address, error) { + return _Ownable.Contract.Owner(&_Ownable.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ownable.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableSession) RenounceOwnership() (*types.Transaction, error) { + return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Ownable *OwnableTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Ownable.Contract.RenounceOwnership(&_Ownable.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Ownable.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Ownable *OwnableTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Ownable.Contract.TransferOwnership(&_Ownable.TransactOpts, newOwner) +} + +// OwnableOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Ownable contract. +type OwnableOwnershipTransferredIterator struct { + Event *OwnableOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *OwnableOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(OwnableOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(OwnableOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *OwnableOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OwnableOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OwnableOwnershipTransferred represents a OwnershipTransferred event raised by the Ownable contract. +type OwnableOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*OwnableOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Ownable.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &OwnableOwnershipTransferredIterator{contract: _Ownable.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OwnableOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Ownable.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(OwnableOwnershipTransferred) + if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Ownable *OwnableFilterer) ParseOwnershipTransferred(log types.Log) (*OwnableOwnershipTransferred, error) { + event := new(OwnableOwnershipTransferred) + if err := _Ownable.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/sin-executor/contracts/executionservice/executionservice.contractinfo.json b/sin-executor/contracts/executionservice/executionservice.contractinfo.json new file mode 100644 index 0000000000..0e1769cc94 --- /dev/null +++ b/sin-executor/contracts/executionservice/executionservice.contractinfo.json @@ -0,0 +1 @@ +{"solidity/ExecutionService.sol:Context":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"Context\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{}},"solidity/ExecutionService.sol:ExecutionService":{"code":"0x608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610c95806100a56000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638da5cb5b11610081578063c9a64e911161005b578063c9a64e91146101ba578063e4e06522146101da578063f2fde38b146101ed57600080fd5b80638da5cb5b14610168578063a87b815214610186578063c473e7e81461019957600080fd5b80635d62a8dd116100b25780635d62a8dd146100f657806362014bad14610140578063715018a61461016057600080fd5b806327efcbb7146100ce5780632d54566c146100e3575b600080fd5b6100e16100dc366004610909565b610200565b005b6100e16100f1366004610909565b610277565b6003546101169073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6002546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16102ee565b60005473ffffffffffffffffffffffffffffffffffffffff16610116565b6100e1610194366004610909565b610302565b6101ac6101a7366004610a59565b610379565b604051908152602001610137565b6001546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16101e8366004610aa9565b6105c4565b6100e16101fb366004610909565b610737565b61020861079b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d6290600090a250565b61027f61079b565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b490600090a250565b6102f661079b565b61030060006107ee565b565b61030a61079b565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb9090600090a250565b600080600061038784610863565b90925090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff8316016105305760006103c185610885565b60035481516040517f5cbd3c48000000000000000000000000000000000000000000000000000000008152600481018b905260248101919091526044810189905291925060009173ffffffffffffffffffffffffffffffffffffffff90911690635cbd3c4890606401602060405180830381865afa158015610447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046b9190610b0d565b6020830151909150156105255760035460208301516040517f1e7b9287000000000000000000000000000000000000000000000000000000008152600481018b9052602481019190915273ffffffffffffffffffffffffffffffffffffffff90911690631e7b928790604401602060405180830381865afa1580156104f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105189190610b0d565b6105229082610b26565b90505b93506105bd92505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f556e737570706f72746564206f7074696f6e732076657273696f6e3a2076657260448201527f73696f6e206d757374206265204f5054494f4e535f563100000000000000000060648201526084015b60405180910390fd5b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461066b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f457865637574696f6e536572766963653a2063616c6c6572206973206e6f742060448201527f74686520496e746572636861696e436c69656e7400000000000000000000000060648201526084016105b4565b610676858583610379565b821015610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f457865637574696f6e536572766963653a20657865637574696f6e206665652060448201527f6973206e6f74206869676820656e6f756768000000000000000000000000000060648201526084016105b4565b60405183907f4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e745016850490600090a25050505050565b61073f61079b565b73ffffffffffffffffffffffffffffffffffffffff811661078f576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016105b4565b610798816107ee565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610300576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016105b4565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060608280602001905181019061087b9190610b66565b9094909350915050565b60408051808201909152600080825260208201526000806108a584610863565b9092509050600160ff831610156108ed576040517fbd91a21500000000000000000000000000000000000000000000000000000000815260ff831660048201526024016105b4565b808060200190518101906109019190610c10565b949350505050565b60006020828403121561091b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105bd57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b5576109b561093f565b604052919050565b600067ffffffffffffffff8211156109d7576109d761093f565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112610a1457600080fd5b8135610a27610a22826109bd565b61096e565b818152846020838601011115610a3c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610a6e57600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a9357600080fd5b610a9f86828701610a03565b9150509250925092565b600080600080600060a08688031215610ac157600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115610af457600080fd5b610b0088828901610a03565b9150509295509295909350565b600060208284031215610b1f57600080fd5b5051919050565b80820180821115610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60008060408385031215610b7957600080fd5b825160ff81168114610b8a57600080fd5b8092505060208084015167ffffffffffffffff811115610ba957600080fd5b8401601f81018613610bba57600080fd5b8051610bc8610a22826109bd565b8181528784838501011115610bdc57600080fd5b60005b82811015610bfa578381018501518282018601528401610bdf565b5060009181019093015250919491935090915050565b600060408284031215610c2257600080fd5b6040516040810181811067ffffffffffffffff82111715610c4557610c4561093f565b60405282518152602092830151928101929092525091905056fea264697066735822122095bc76308f5ab8df49d2f86f8e2e3d0c41f912da2d9ab421958c9a73554d373a64736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80638da5cb5b11610081578063c9a64e911161005b578063c9a64e91146101ba578063e4e06522146101da578063f2fde38b146101ed57600080fd5b80638da5cb5b14610168578063a87b815214610186578063c473e7e81461019957600080fd5b80635d62a8dd116100b25780635d62a8dd146100f657806362014bad14610140578063715018a61461016057600080fd5b806327efcbb7146100ce5780632d54566c146100e3575b600080fd5b6100e16100dc366004610909565b610200565b005b6100e16100f1366004610909565b610277565b6003546101169073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6002546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16102ee565b60005473ffffffffffffffffffffffffffffffffffffffff16610116565b6100e1610194366004610909565b610302565b6101ac6101a7366004610a59565b610379565b604051908152602001610137565b6001546101169073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16101e8366004610aa9565b6105c4565b6100e16101fb366004610909565b610737565b61020861079b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f33e3a51bf9fedee6e205cd10237a9a8dd3fffed45ac3dee88d2eba92ef8b5d6290600090a250565b61027f61079b565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f8a101f72b53416c657555bd234f732510711b6f59f28b161db43892c89b6b3b490600090a250565b6102f661079b565b61030060006107ee565b565b61030a61079b565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f0b987d971d57fe66ec2d0cff095b1b547c3076cdd07fdf5b0863f320700dbb9090600090a250565b600080600061038784610863565b90925090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff8316016105305760006103c185610885565b60035481516040517f5cbd3c48000000000000000000000000000000000000000000000000000000008152600481018b905260248101919091526044810189905291925060009173ffffffffffffffffffffffffffffffffffffffff90911690635cbd3c4890606401602060405180830381865afa158015610447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046b9190610b0d565b6020830151909150156105255760035460208301516040517f1e7b9287000000000000000000000000000000000000000000000000000000008152600481018b9052602481019190915273ffffffffffffffffffffffffffffffffffffffff90911690631e7b928790604401602060405180830381865afa1580156104f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105189190610b0d565b6105229082610b26565b90505b93506105bd92505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f556e737570706f72746564206f7074696f6e732076657273696f6e3a2076657260448201527f73696f6e206d757374206265204f5054494f4e535f563100000000000000000060648201526084015b60405180910390fd5b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461066b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f457865637574696f6e536572766963653a2063616c6c6572206973206e6f742060448201527f74686520496e746572636861696e436c69656e7400000000000000000000000060648201526084016105b4565b610676858583610379565b821015610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f457865637574696f6e536572766963653a20657865637574696f6e206665652060448201527f6973206e6f74206869676820656e6f756768000000000000000000000000000060648201526084016105b4565b60405183907f4352366ad6ebd2dce312bff7a3a5691396c030f8f92c6ed8cad31e745016850490600090a25050505050565b61073f61079b565b73ffffffffffffffffffffffffffffffffffffffff811661078f576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016105b4565b610798816107ee565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610300576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016105b4565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060608280602001905181019061087b9190610b66565b9094909350915050565b60408051808201909152600080825260208201526000806108a584610863565b9092509050600160ff831610156108ed576040517fbd91a21500000000000000000000000000000000000000000000000000000000815260ff831660048201526024016105b4565b808060200190518101906109019190610c10565b949350505050565b60006020828403121561091b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105bd57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b5576109b561093f565b604052919050565b600067ffffffffffffffff8211156109d7576109d761093f565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112610a1457600080fd5b8135610a27610a22826109bd565b61096e565b818152846020838601011115610a3c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610a6e57600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a9357600080fd5b610a9f86828701610a03565b9150509250925092565b600080600080600060a08688031215610ac157600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115610af457600080fd5b610b0088828901610a03565b9150509295509295909350565b600060208284031215610b1f57600080fd5b5051919050565b80820180821115610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60008060408385031215610b7957600080fd5b825160ff81168114610b8a57600080fd5b8092505060208084015167ffffffffffffffff811115610ba957600080fd5b8401601f81018613610bba57600080fd5b8051610bc8610a22826109bd565b8181528784838501011115610bdc57600080fd5b60005b82811015610bfa578381018501518282018601528401610bdf565b5060009181019093015250919491935090915050565b600060408284031215610c2257600080fd5b6040516040810181811067ffffffffffffffff82111715610c4557610c4561093f565b60405282518152602092830151928101929092525091905056fea264697066735822122095bc76308f5ab8df49d2f86f8e2e3d0c41f912da2d9ab421958c9a73554d373a64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"10553:2271:0:-:0;;;10775:36;;;;;;;;;-1:-1:-1;10797:10:0;;8684:95;;8737:31;;-1:-1:-1;;;8737:31:0;;8765:1;8737:31;;;160:51:1;133:18;;8737:31:0;;;;;;;8684:95;8788:32;8807:12;8788:18;:32::i;:::-;8640:187;10553:2271;;10327:187;10400:16;10419:6;;-1:-1:-1;;;;;10435:17:0;;;-1:-1:-1;;;;;;10435:17:0;;;;;;10467:40;;10419:6;;;;;;;10467:40;;10400:16;10467:40;10390:124;10327:187;:::o;14:203:1:-;10553:2271:0;;;;;;","srcMapRuntime":"10553:2271:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10817:185;;;;;;:::i;:::-;;:::i;:::-;;11008:154;;;;;;:::i;:::-;;:::i;10741:27::-;;;;;;;;;;;;521:42:1;509:55;;;491:74;;479:2;464:18;10741:27:0;;;;;;;;10709:26;;;;;;;;;9708:101;;;:::i;9053:85::-;9099:7;9125:6;;;9053:85;;11168:155;;;;;;:::i;:::-;;:::i;12012:810::-;;;;;;:::i;:::-;;:::i;:::-;;;2659:25:1;;;2647:2;2632:18;12012:810:0;2513:177:1;10672:31:0;;;;;;;;;11509:478;;;;;;:::i;:::-;;:::i;9958:215::-;;;;;;:::i;:::-;;:::i;10817:185::-;8946:13;:11;:13::i;:::-;10902:16:::1;:36:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;10953:42:::1;::::0;::::1;::::0;-1:-1:-1;;10953:42:0::1;10817:185:::0;:::o;11008:154::-;8946:13;:11;:13::i;:::-;11083:11:::1;:26:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;11124:31:::1;::::0;::::1;::::0;-1:-1:-1;;11124:31:0::1;11008:154:::0;:::o;9708:101::-;8946:13;:11;:13::i;:::-;9772:30:::1;9799:1;9772:18;:30::i;:::-;9708:101::o:0;11168:155::-;8946:13;:11;:13::i;:::-;11239:9:::1;:34:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;11288:28:::1;::::0;::::1;::::0;-1:-1:-1;;11288:28:0::1;11168:155:::0;:::o;12012:810::-;12194:7;12218:13;12233:17;12254:32;:7;:30;:32::i;:::-;12217:69;;-1:-1:-1;12217:69:0;-1:-1:-1;12300:32:0;;;;;12296:520;;12348:26;12377:25;:7;:23;:25::i;:::-;12435:9;;12484:18;;12435:83;;;;;;;;3496:25:1;;;3537:18;;;3530:34;;;;3580:18;;;3573:34;;;12484:18:0;;-1:-1:-1;12416:16:0;;12435:9;;;;;:36;;3469:18:1;;12435:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12536:20;;;;12416:102;;-1:-1:-1;12536:24:0;12532:149;;12592:9;;12645:20;;;;12592:74;;;;;;;;3981:25:1;;;4022:18;;;4015:34;;;;12592:9:0;;;;;:40;;3954:18:1;;12592:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12580:86;;;;:::i;:::-;;;12532:149;12701:8;-1:-1:-1;12694:15:0;;-1:-1:-1;;;12694:15:0;12296:520;12740:65;;;;;4546:2:1;12740:65:0;;;4528:21:1;4585:2;4565:18;;;4558:30;4624:34;4604:18;;;4597:62;4695:25;4675:18;;;4668:53;4738:19;;12740:65:0;;;;;;;;12012:810;;;;;;:::o;11509:478::-;11393:16;;;;11379:10;:30;11371:95;;;;;;;4970:2:1;11371:95:0;;;4952:21:1;5009:2;4989:18;;;4982:30;5048:34;5028:18;;;5021:62;5119:22;5099:18;;;5092:50;5159:19;;11371:95:0;4768:416:1;11371:95:0;11805:51:::1;11821:10;11833:13;11848:7;11805:15;:51::i;:::-;11789:12;:67;;11768:164;;;::::0;::::1;::::0;;5391:2:1;11768:164:0::1;::::0;::::1;5373:21:1::0;5430:2;5410:18;;;5403:30;5469:34;5449:18;;;5442:62;5540:20;5520:18;;;5513:48;5578:19;;11768:164:0::1;5189:414:1::0;11768:164:0::1;11947:33;::::0;11966:13;;11947:33:::1;::::0;;;::::1;11509:478:::0;;;;;:::o;9958:215::-;8946:13;:11;:13::i;:::-;10042:22:::1;::::0;::::1;10038:91;;10087:31;::::0;::::1;::::0;;10115:1:::1;10087:31;::::0;::::1;491:74:1::0;464:18;;10087:31:0::1;328:243:1::0;10038:91:0::1;10138:28;10157:8;10138:18;:28::i;:::-;9958:215:::0;:::o;9211:162::-;9099:7;9125:6;9270:23;9125:6;7231:10;9270:23;9266:101;;9316:40;;;;;7231:10;9316:40;;;491:74:1;464:18;;9316:40:0;328:243:1;10327:187:0;10400:16;10419:6;;;10435:17;;;;;;;;;;10467:40;;10419:6;;;;;;;10467:40;;10400:16;10467:40;10390:124;10327:187;:::o;5259:181::-;5333:13;5348:20;5412:4;5401:32;;;;;;;;;;;;:::i;:::-;5380:53;;;;-1:-1:-1;5259:181:0;-1:-1:-1;;5259:181:0:o;5888:603::-;-1:-1:-1;;;;;;;;;;;;;;;;;5984:13:0;5999:20;6023:28;6046:4;6023:22;:28::i;:::-;5983:68;;-1:-1:-1;5983:68:0;-1:-1:-1;4644:1:0;6065:20;;;;6061:95;;;6108:37;;;;;6726:4:1;6714:17;;6108:37:0;;;6696:36:1;6669:18;;6108:37:0;6554:184:1;6061:95:0;6463:7;6452:32;;;;;;;;;;;;:::i;:::-;6445:39;5888:603;-1:-1:-1;;;;5888:603:0:o;14:309:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;181:9;168:23;231:42;224:5;220:54;213:5;210:65;200:93;;289:1;286;279:12;807:184;859:77;856:1;849:88;956:4;953:1;946:15;980:4;977:1;970:15;996:334;1067:2;1061:9;1123:2;1113:13;;1128:66;1109:86;1097:99;;1226:18;1211:34;;1247:22;;;1208:62;1205:88;;;1273:18;;:::i;:::-;1309:2;1302:22;996:334;;-1:-1:-1;996:334:1:o;1335:245::-;1383:4;1416:18;1408:6;1405:30;1402:56;;;1438:18;;:::i;:::-;-1:-1:-1;1495:2:1;1483:15;1500:66;1479:88;1569:4;1475:99;;1335:245::o;1585:462::-;1627:5;1680:3;1673:4;1665:6;1661:17;1657:27;1647:55;;1698:1;1695;1688:12;1647:55;1734:6;1721:20;1765:48;1781:31;1809:2;1781:31;:::i;:::-;1765:48;:::i;:::-;1838:2;1829:7;1822:19;1884:3;1877:4;1872:2;1864:6;1860:15;1856:26;1853:35;1850:55;;;1901:1;1898;1891:12;1850:55;1966:2;1959:4;1951:6;1947:17;1940:4;1931:7;1927:18;1914:55;2014:1;1989:16;;;2007:4;1985:27;1978:38;;;;1993:7;1585:462;-1:-1:-1;;;1585:462:1:o;2052:456::-;2138:6;2146;2154;2207:2;2195:9;2186:7;2182:23;2178:32;2175:52;;;2223:1;2220;2213:12;2175:52;2259:9;2246:23;2236:33;;2316:2;2305:9;2301:18;2288:32;2278:42;;2371:2;2360:9;2356:18;2343:32;2398:18;2390:6;2387:30;2384:50;;;2430:1;2427;2420:12;2384:50;2453:49;2494:7;2485:6;2474:9;2470:22;2453:49;:::i;:::-;2443:59;;;2052:456;;;;;:::o;2695:594::-;2799:6;2807;2815;2823;2831;2884:3;2872:9;2863:7;2859:23;2855:33;2852:53;;;2901:1;2898;2891:12;2852:53;2937:9;2924:23;2914:33;;2994:2;2983:9;2979:18;2966:32;2956:42;;3045:2;3034:9;3030:18;3017:32;3007:42;;3096:2;3085:9;3081:18;3068:32;3058:42;;3151:3;3140:9;3136:19;3123:33;3179:18;3171:6;3168:30;3165:50;;;3211:1;3208;3201:12;3165:50;3234:49;3275:7;3266:6;3255:9;3251:22;3234:49;:::i;:::-;3224:59;;;2695:594;;;;;;;;:::o;3618:184::-;3688:6;3741:2;3729:9;3720:7;3716:23;3712:32;3709:52;;;3757:1;3754;3747:12;3709:52;-1:-1:-1;3780:16:1;;3618:184;-1:-1:-1;3618:184:1:o;4060:279::-;4125:9;;;4146:10;;;4143:190;;;4189:77;4186:1;4179:88;4290:4;4287:1;4280:15;4318:4;4315:1;4308:15;4143:190;4060:279;;;;:::o;5608:941::-;5694:6;5702;5755:2;5743:9;5734:7;5730:23;5726:32;5723:52;;;5771:1;5768;5761:12;5723:52;5803:9;5797:16;5853:4;5846:5;5842:16;5835:5;5832:27;5822:55;;5873:1;5870;5863:12;5822:55;5896:5;5886:15;;;5920:2;5966;5955:9;5951:18;5945:25;5993:18;5985:6;5982:30;5979:50;;;6025:1;6022;6015:12;5979:50;6048:22;;6101:4;6093:13;;6089:27;-1:-1:-1;6079:55:1;;6130:1;6127;6120:12;6079:55;6159:2;6153:9;6184:48;6200:31;6228:2;6200:31;:::i;6184:48::-;6255:2;6248:5;6241:17;6295:7;6290:2;6285;6281;6277:11;6273:20;6270:33;6267:53;;;6316:1;6313;6306:12;6267:53;6338:1;6348:128;6362:2;6359:1;6356:9;6348:128;;;6449:10;;;6445:19;;6439:26;6419:13;;;6415:22;;6408:58;6373:10;;6348:128;;;-1:-1:-1;6517:1:1;6496:14;;;6492:23;;;6485:34;-1:-1:-1;5608:941:1;;6500:5;;-1:-1:-1;5608:941:1;;-1:-1:-1;;5608:941:1:o;6743:501::-;6838:6;6891:2;6879:9;6870:7;6866:23;6862:32;6859:52;;;6907:1;6904;6897:12;6859:52;6940:2;6934:9;6982:2;6974:6;6970:15;7051:6;7039:10;7036:22;7015:18;7003:10;7000:34;6997:62;6994:88;;;7062:18;;:::i;:::-;7098:2;7091:22;7137:16;;7122:32;;7208:2;7193:18;;;7187:25;7170:15;;;7163:50;;;;-1:-1:-1;7129:6:1;6743:501;-1:-1:-1;6743:501:1:o","abiDefinition":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"OptionsLib__IncorrectVersion","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"ExecutionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executorEOA","type":"address"}],"name":"ExecutorEOAUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gasOracle","type":"address"}],"name":"GasOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"interchainClient","type":"address"}],"name":"InterchainClientUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"executorEOA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasOracle","outputs":[{"internalType":"contract IGasOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"getExecutionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interchainClient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"requestExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_executorEOA","type":"address"}],"name":"setExecutorEOA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gasOracle","type":"address"}],"name":"setGasOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_interchainClient","type":"address"}],"name":"setInterchainClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutionFee(uint256,uint256,bytes)":{"notice":"Get the execution fee for executing an Interchain Transaction on a remote chain."},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"notice":"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract."}},"version":1},"developerDoc":{"errors":{"OwnableInvalidOwner(address)":[{"details":"The owner is not a valid owner account. (eg. `address(0)`)"}],"OwnableUnauthorizedAccount(address)":[{"details":"The caller account is not authorized to perform an operation."}]},"kind":"dev","methods":{"getExecutionFee(uint256,uint256,bytes)":{"params":{"dstChainId":"The chain id of the destination chain.","options":"The options to use for the execution.","txPayloadSize":"The size of the transaction payload to use for the execution."}},"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"details":"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.","params":{"dstChainId":"The chain id of the destination chain.","executionFee":"The fee paid for the execution.","options":"The options to use for the execution.","transactionId":"The id of the transaction to execute.","txPayloadSize":"The size of the transaction payload to use for the execution."}},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"ExecutionRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executorEOA\",\"type\":\"address\"}],\"name\":\"ExecutorEOAUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gasOracle\",\"type\":\"address\"}],\"name\":\"GasOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"interchainClient\",\"type\":\"address\"}],\"name\":\"InterchainClientUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasOracle\",\"outputs\":[{\"internalType\":\"contract IGasOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchainClient\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_executorEOA\",\"type\":\"address\"}],\"name\":\"setExecutorEOA\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gasOracle\",\"type\":\"address\"}],\"name\":\"setGasOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchainClient\",\"type\":\"address\"}],\"name\":\"setInterchainClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"options\":\"The options to use for the execution.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"details\":\"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.\",\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"executionFee\":\"The fee paid for the execution.\",\"options\":\"The options to use for the execution.\",\"transactionId\":\"The id of the transaction to execute.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"notice\":\"Get the execution fee for executing an Interchain Transaction on a remote chain.\"},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"notice\":\"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"ExecutionService\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{"executorEOA()":"62014bad","gasOracle()":"5d62a8dd","getExecutionFee(uint256,uint256,bytes)":"c473e7e8","interchainClient()":"c9a64e91","owner()":"8da5cb5b","renounceOwnership()":"715018a6","requestExecution(uint256,uint256,bytes32,uint256,bytes)":"e4e06522","setExecutorEOA(address)":"2d54566c","setGasOracle(address)":"a87b8152","setInterchainClient(address)":"27efcbb7","transferOwnership(address)":"f2fde38b"}},"solidity/ExecutionService.sol:ExecutionServiceEvents":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"ExecutionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executorEOA","type":"address"}],"name":"ExecutorEOAUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gasOracle","type":"address"}],"name":"GasOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"interchainClient","type":"address"}],"name":"InterchainClientUpdated","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"ExecutionRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"executorEOA\",\"type\":\"address\"}],\"name\":\"ExecutorEOAUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"gasOracle\",\"type\":\"address\"}],\"name\":\"GasOracleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"interchainClient\",\"type\":\"address\"}],\"name\":\"InterchainClientUpdated\",\"type\":\"event\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"ExecutionServiceEvents\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{}},"solidity/ExecutionService.sol:IExecutionService":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"executorEOA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"getExecutionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"requestExecution","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutionFee(uint256,uint256,bytes)":{"notice":"Get the execution fee for executing an Interchain Transaction on a remote chain."},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"notice":"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getExecutionFee(uint256,uint256,bytes)":{"params":{"dstChainId":"The chain id of the destination chain.","options":"The options to use for the execution.","txPayloadSize":"The size of the transaction payload to use for the execution."}},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"details":"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.","params":{"dstChainId":"The chain id of the destination chain.","executionFee":"The fee paid for the execution.","options":"The options to use for the execution.","transactionId":"The id of the transaction to execute.","txPayloadSize":"The size of the transaction payload to use for the execution."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"options\":\"The options to use for the execution.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"details\":\"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.\",\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"executionFee\":\"The fee paid for the execution.\",\"options\":\"The options to use for the execution.\",\"transactionId\":\"The id of the transaction to execute.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"notice\":\"Get the execution fee for executing an Interchain Transaction on a remote chain.\"},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"notice\":\"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"IExecutionService\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{"executorEOA()":"62014bad","getExecutionFee(uint256,uint256,bytes)":"c473e7e8","requestExecution(uint256,uint256,bytes32,uint256,bytes)":"e4e06522"}},"solidity/ExecutionService.sol:IGasOracle":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"convertRemoteValueToLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInRemoteUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"notice":"Convert a value from the native token of a remote chain to the local native token."},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token."},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token."}},"version":1},"developerDoc":{"kind":"dev","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"remoteChainId":"The chain id of the remote chain.","value":"The value to convert."}},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"remoteChainId\":\"The chain id of the remote chain.\",\"value\":\"The value to convert.\"}},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"notice\":\"Convert a value from the native token of a remote chain to the local native token.\"},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token.\"},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"IGasOracle\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{"convertRemoteValueToLocalUnits(uint256,uint256)":"1e7b9287","estimateTxCostInLocalUnits(uint256,uint256,uint256)":"5cbd3c48","estimateTxCostInRemoteUnits(uint256,uint256,uint256)":"fd6a7167"}},"solidity/ExecutionService.sol:OptionsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205a22485b2583acad6f8c2c47520c8dc72b4859c134f0579480fb7948883dcbcf64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205a22485b2583acad6f8c2c47520c8dc72b4859c134f0579480fb7948883dcbcf64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"4535:1958:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;4535:1958:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"4535:1958:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"OptionsLib__IncorrectVersion","type":"error"}],"userDoc":{"kind":"user","methods":{},"notice":"A library for encoding and decoding Interchain options related to interchain messages.","version":1},"developerDoc":{"kind":"dev","methods":{},"title":"OptionsLib","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"OptionsLib\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"A library for encoding and decoding Interchain options related to interchain messages.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"OptionsLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{}},"solidity/ExecutionService.sol:Ownable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.13 ^0.8.20;\n\n// contracts/events/ExecutionServiceEvents.sol\n\nabstract contract ExecutionServiceEvents {\n event ExecutionRequested(bytes32 indexed transactionId);\n event ExecutorEOAUpdated(address indexed executorEOA);\n event GasOracleUpdated(address indexed gasOracle);\n event InterchainClientUpdated(address indexed interchainClient);\n}\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n\n// contracts/ExecutionService.sol\n\ncontract ExecutionService is ExecutionServiceEvents, Ownable, IExecutionService {\n using OptionsLib for bytes;\n\n address public interchainClient;\n address public executorEOA;\n IGasOracle public gasOracle;\n\n constructor() Ownable(msg.sender) {}\n\n function setInterchainClient(address _interchainClient) external onlyOwner {\n interchainClient = _interchainClient;\n emit InterchainClientUpdated(_interchainClient);\n }\n\n function setExecutorEOA(address _executorEOA) external onlyOwner {\n executorEOA = _executorEOA;\n emit ExecutorEOAUpdated(executorEOA);\n }\n\n function setGasOracle(address _gasOracle) external onlyOwner {\n gasOracle = IGasOracle(_gasOracle);\n emit GasOracleUpdated(_gasOracle);\n }\n\n modifier onlyInterchainClient() {\n require(msg.sender == interchainClient, \"ExecutionService: caller is not the InterchainClient\");\n _;\n }\n\n // @inheritdoc\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n override\n onlyInterchainClient\n {\n require(\n executionFee \u003e= getExecutionFee(dstChainId, txPayloadSize, options),\n \"ExecutionService: execution fee is not high enough\"\n );\n emit ExecutionRequested(transactionId);\n }\n\n // @inheritdoc\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n public\n view\n override\n returns (uint256)\n {\n (uint8 version, bytes memory data) = options.decodeVersionedOptions();\n if (version == OptionsLib.OPTIONS_V1) {\n OptionsV1 memory optionsV1 = options.decodeOptionsV1();\n uint256 baseCost = gasOracle.estimateTxCostInLocalUnits(dstChainId, optionsV1.gasLimit, txPayloadSize);\n if (optionsV1.gasAirdrop \u003e 0) {\n baseCost += gasOracle.convertRemoteValueToLocalUnits(dstChainId, optionsV1.gasAirdrop);\n }\n return baseCost;\n } else {\n revert(\"Unsupported options version: version must be OPTIONS_V1\");\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. The initial owner is set to the address provided by the deployer. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.","errors":{"OwnableInvalidOwner(address)":[{"details":"The owner is not a valid owner account. (eg. `address(0)`)"}],"OwnableUnauthorizedAccount(address)":[{"details":"The caller account is not authorized to perform an operation."}]},"kind":"dev","methods":{"constructor":{"details":"Initializes the contract setting the address provided by the deployer as the initial owner."},"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. The initial owner is set to the address provided by the deployer. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.\",\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the contract setting the address provided by the deployer as the initial owner.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionService.sol\":\"Ownable\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionService.sol\":{\"keccak256\":\"0x26cb9b28bb2286cba9aea14879a3b6a20e78dd74adbb7d52fc053ee653b0d237\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac45ebf4af3b8a0a36b83bd9707ac0ade71056518220852d8b050e7f31e3b865\",\"dweb:/ipfs/QmRGs1ktp4f3rxBuYsPViLpog8dK5n5vKhKEEsR85v88vQ\"]}},\"version\":1}"},"hashes":{"owner()":"8da5cb5b","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}}} \ No newline at end of file diff --git a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.metadata.go b/sin-executor/contracts/executionservice/executionservice.metadata.go similarity index 85% rename from sin-executor/contracts/mocks/executionservicemock/executionservicemock.metadata.go rename to sin-executor/contracts/executionservice/executionservice.metadata.go index c103fdfd5e..b98ccb65bd 100644 --- a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.metadata.go +++ b/sin-executor/contracts/executionservice/executionservice.metadata.go @@ -1,5 +1,5 @@ // Code generated by synapse abigen DO NOT EDIT. -package executionservicemock +package executionservice import ( _ "embed" @@ -9,7 +9,7 @@ import ( // rawContracts are the json we use to dervive the processed contracts // -//go:embed executionservicemock.contractinfo.json +//go:embed executionservice.contractinfo.json var rawContracts []byte // Contracts are unmarshalled on start diff --git a/sin-executor/contracts/executionservice/generate.go b/sin-executor/contracts/executionservice/generate.go new file mode 100644 index 0000000000..32ee15fcd6 --- /dev/null +++ b/sin-executor/contracts/executionservice/generate.go @@ -0,0 +1,3 @@ +package executionservice + +//go:generate go run github.com/synapsecns/sanguine/tools/abigen generate --sol ../../../packages/contracts-communication/flattened/ExecutionService.sol --pkg executionservice --sol-version 0.8.20 --filename executionservice --evm-version istanbul diff --git a/sin-executor/contracts/executionservice/helpers.go b/sin-executor/contracts/executionservice/helpers.go new file mode 100644 index 0000000000..e18f0a6cdd --- /dev/null +++ b/sin-executor/contracts/executionservice/helpers.go @@ -0,0 +1,35 @@ +// Package executionservice provides a mock for the ExecutionService contract. +package executionservice + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +// ExecutionServiceRef is a reference to an interchain db. +type ExecutionServiceRef struct { + *ExecutionService + // address of the interchain client + address common.Address +} + +// Address is the contract address. +func (i *ExecutionServiceRef) Address() common.Address { + return i.address +} + +// NewExecutionServiceRef creates a new interchain client with a contract ref. +func NewExecutionServiceRef(address common.Address, backend bind.ContractBackend) (*ExecutionServiceRef, error) { + instance, err := NewExecutionService(address, backend) + if err != nil { + return nil, fmt.Errorf("could not create instance of InterchainClient: %w", err) + } + return &ExecutionServiceRef{ + ExecutionService: instance, + address: address, + }, nil +} + +var _ vm.ContractRef = &ExecutionServiceRef{} diff --git a/sin-executor/contracts/executionservice/parser.go b/sin-executor/contracts/executionservice/parser.go new file mode 100644 index 0000000000..1b6c6f0568 --- /dev/null +++ b/sin-executor/contracts/executionservice/parser.go @@ -0,0 +1,64 @@ +package executionservice + +import ( + "fmt" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" +) + +// EventType is the type of the module watcher +// +//go:generate go run golang.org/x/tools/cmd/stringer -type=EventType +type EventType uint + +const ( + // ExecutionRequestedEvent is an EventType that represents an execution requested event. + ExecutionRequestedEvent EventType = iota + 1 +) + +// Parser parses events from the module contract. +type Parser interface { + // ParseEvent parses the event from the log. + ParseEvent(log ethTypes.Log) (_ EventType, event interface{}, ok bool) +} + +type parserImpl struct { + filterer *ExecutionServiceFilterer +} + +// NewParser creates a new parser for the fastbridge contract. +func NewParser(synapseModuleAddress common.Address) (Parser, error) { + parser, err := NewExecutionServiceFilterer(synapseModuleAddress, nil) + if err != nil { + return nil, fmt.Errorf("could not create %T: %w", ExecutionServiceFilterer{}, err) + } + + return &parserImpl{filterer: parser}, nil +} + +// nolint: cyclop +func (p parserImpl) ParseEvent(log ethTypes.Log) (_ EventType, event interface{}, ok bool) { + // return an unknown event to avoid cases where user failed to check the event type + // make it high enough to make it obvious (we start iotas at +1, see uber style guide for details) + noOpEvent := EventType(len(topicMap()) + 2) + + if len(log.Topics) == 0 { + return noOpEvent, nil, false + } + nillableEventType := eventTypeFromTopic(log.Topics[0]) + if nillableEventType == nil { + return noOpEvent, nil, false + } + + eventType := *nillableEventType + + switch eventType { + case ExecutionRequestedEvent: + event, err := p.filterer.ParseExecutionRequested(log) + if err != nil { + return noOpEvent, nil, false + } + return eventType, event, true + } + return eventType, nil, false +} diff --git a/sin-executor/contracts/executionservice/topics.go b/sin-executor/contracts/executionservice/topics.go new file mode 100644 index 0000000000..0435c55dde --- /dev/null +++ b/sin-executor/contracts/executionservice/topics.go @@ -0,0 +1,49 @@ +package executionservice + +import ( + "bytes" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "strings" +) + +var ( + // ExecutionRequestedTopic is the event topic for a sent transaction. + ExecutionRequestedTopic common.Hash +) + +// static checks to make sure topics actually exist. +func init() { + var err error + + parsedABI, err := abi.JSON(strings.NewReader(ExecutionServiceMetaData.ABI)) + if err != nil { + panic(err) + } + + ExecutionRequestedTopic = parsedABI.Events["ExecutionRequested"].ID + + _, err = parsedABI.EventByID(ExecutionRequestedTopic) + if err != nil { + panic(err) + } +} + +// topicMap maps events to topics. +// this is returned as a function to assert immutability. +func topicMap() map[EventType]common.Hash { + return map[EventType]common.Hash{ + ExecutionRequestedEvent: ExecutionRequestedTopic, + } +} + +// eventTypeFromTopic gets the event type from the topic +// returns nil if the topic is not found. +func eventTypeFromTopic(ogTopic common.Hash) *EventType { + for eventType, topic := range topicMap() { + if bytes.Equal(ogTopic.Bytes(), topic.Bytes()) { + return &eventType + } + } + return nil +} diff --git a/sin-executor/contracts/interchainclient/eventtype_string.go b/sin-executor/contracts/interchainclient/eventtype_string.go index d66e64d1ab..a5c701351e 100644 --- a/sin-executor/contracts/interchainclient/eventtype_string.go +++ b/sin-executor/contracts/interchainclient/eventtype_string.go @@ -9,12 +9,11 @@ func _() { // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[InterchainTransactionSentEvent-1] - _ = x[InterchainOptionsV1Event-2] } -const _EventType_name = "InterchainTransactionSentEventInterchainOptionsV1Event" +const _EventType_name = "InterchainTransactionSentEvent" -var _EventType_index = [...]uint8{0, 30, 54} +var _EventType_index = [...]uint8{0, 30} func (i EventType) String() string { i -= 1 diff --git a/sin-executor/contracts/interchainclient/parser.go b/sin-executor/contracts/interchainclient/parser.go index aaa98ea6f5..31cc4c270d 100644 --- a/sin-executor/contracts/interchainclient/parser.go +++ b/sin-executor/contracts/interchainclient/parser.go @@ -14,8 +14,6 @@ type EventType uint const ( // InterchainTransactionSentEvent is an EventType that represents an interchain transaction sent event. InterchainTransactionSentEvent EventType = iota + 1 - // InterchainOptionsV1Event is an EventType that represents an interchain options v1 event. - InterchainOptionsV1Event ) // Parser parses events from the module contract. diff --git a/sin-executor/contracts/interchainclient/topics.go b/sin-executor/contracts/interchainclient/topics.go index 19596cb1e9..31f0aa2c26 100644 --- a/sin-executor/contracts/interchainclient/topics.go +++ b/sin-executor/contracts/interchainclient/topics.go @@ -10,8 +10,6 @@ import ( var ( // InterchainTransactionSentTopic is the event topic for a sent transaction. InterchainTransactionSentTopic common.Hash - // InterchainOptionsV1Topic is the event topic for options v1. - InterchainOptionsV1Topic common.Hash ) // static checks to make sure topics actually exist. @@ -25,8 +23,6 @@ func init() { InterchainTransactionSentTopic = parsedABI.Events["InterchainTransactionSent"].ID - InterchainOptionsV1Topic = parsedABI.Events["InterchainOptionsV1"].ID - _, err = parsedABI.EventByID(InterchainTransactionSentTopic) if err != nil { panic(err) @@ -38,7 +34,6 @@ func init() { func topicMap() map[EventType]common.Hash { return map[EventType]common.Hash{ InterchainTransactionSentEvent: InterchainTransactionSentTopic, - InterchainOptionsV1Event: InterchainOptionsV1Topic, } } diff --git a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.abigen.go b/sin-executor/contracts/mocks/executionservicemock/executionservicemock.abigen.go deleted file mode 100644 index 5e87059e8d..0000000000 --- a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.abigen.go +++ /dev/null @@ -1,538 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package executionservicemock - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// ExecutionServiceMockMetaData contains all meta data concerning the ExecutionServiceMock contract. -var ExecutionServiceMockMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "62014bad": "executorEOA()", - "c473e7e8": "getExecutionFee(uint256,uint256,bytes)", - "e4e06522": "requestExecution(uint256,uint256,bytes32,uint256,bytes)", - }, - Bin: "0x608060405234801561001057600080fd5b50610290806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806362014bad14610046578063c473e7e814610090578063e4e06522146100b5575b600080fd5b6000546100669073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100a761009e3660046101a6565b60009392505050565b604051908152602001610087565b6100ca6100c33660046101f6565b5050505050565b005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261010c57600080fd5b813567ffffffffffffffff80821115610127576101276100cc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561016d5761016d6100cc565b8160405283815286602085880101111561018657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156101bb57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156101e057600080fd5b6101ec868287016100fb565b9150509250925092565b600080600080600060a0868803121561020e57600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff81111561024157600080fd5b61024d888289016100fb565b915050929550929590935056fea2646970667358221220c15c20205132b64aecd1865fd1e7602a4f626d5e1e0fd8064e46f96b970b8ecf64736f6c63430008140033", -} - -// ExecutionServiceMockABI is the input ABI used to generate the binding from. -// Deprecated: Use ExecutionServiceMockMetaData.ABI instead. -var ExecutionServiceMockABI = ExecutionServiceMockMetaData.ABI - -// Deprecated: Use ExecutionServiceMockMetaData.Sigs instead. -// ExecutionServiceMockFuncSigs maps the 4-byte function signature to its string representation. -var ExecutionServiceMockFuncSigs = ExecutionServiceMockMetaData.Sigs - -// ExecutionServiceMockBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ExecutionServiceMockMetaData.Bin instead. -var ExecutionServiceMockBin = ExecutionServiceMockMetaData.Bin - -// DeployExecutionServiceMock deploys a new Ethereum contract, binding an instance of ExecutionServiceMock to it. -func DeployExecutionServiceMock(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ExecutionServiceMock, error) { - parsed, err := ExecutionServiceMockMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ExecutionServiceMockBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &ExecutionServiceMock{ExecutionServiceMockCaller: ExecutionServiceMockCaller{contract: contract}, ExecutionServiceMockTransactor: ExecutionServiceMockTransactor{contract: contract}, ExecutionServiceMockFilterer: ExecutionServiceMockFilterer{contract: contract}}, nil -} - -// ExecutionServiceMock is an auto generated Go binding around an Ethereum contract. -type ExecutionServiceMock struct { - ExecutionServiceMockCaller // Read-only binding to the contract - ExecutionServiceMockTransactor // Write-only binding to the contract - ExecutionServiceMockFilterer // Log filterer for contract events -} - -// ExecutionServiceMockCaller is an auto generated read-only Go binding around an Ethereum contract. -type ExecutionServiceMockCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ExecutionServiceMockTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ExecutionServiceMockTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ExecutionServiceMockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ExecutionServiceMockFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ExecutionServiceMockSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ExecutionServiceMockSession struct { - Contract *ExecutionServiceMock // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ExecutionServiceMockCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ExecutionServiceMockCallerSession struct { - Contract *ExecutionServiceMockCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ExecutionServiceMockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ExecutionServiceMockTransactorSession struct { - Contract *ExecutionServiceMockTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ExecutionServiceMockRaw is an auto generated low-level Go binding around an Ethereum contract. -type ExecutionServiceMockRaw struct { - Contract *ExecutionServiceMock // Generic contract binding to access the raw methods on -} - -// ExecutionServiceMockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ExecutionServiceMockCallerRaw struct { - Contract *ExecutionServiceMockCaller // Generic read-only contract binding to access the raw methods on -} - -// ExecutionServiceMockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ExecutionServiceMockTransactorRaw struct { - Contract *ExecutionServiceMockTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewExecutionServiceMock creates a new instance of ExecutionServiceMock, bound to a specific deployed contract. -func NewExecutionServiceMock(address common.Address, backend bind.ContractBackend) (*ExecutionServiceMock, error) { - contract, err := bindExecutionServiceMock(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &ExecutionServiceMock{ExecutionServiceMockCaller: ExecutionServiceMockCaller{contract: contract}, ExecutionServiceMockTransactor: ExecutionServiceMockTransactor{contract: contract}, ExecutionServiceMockFilterer: ExecutionServiceMockFilterer{contract: contract}}, nil -} - -// NewExecutionServiceMockCaller creates a new read-only instance of ExecutionServiceMock, bound to a specific deployed contract. -func NewExecutionServiceMockCaller(address common.Address, caller bind.ContractCaller) (*ExecutionServiceMockCaller, error) { - contract, err := bindExecutionServiceMock(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ExecutionServiceMockCaller{contract: contract}, nil -} - -// NewExecutionServiceMockTransactor creates a new write-only instance of ExecutionServiceMock, bound to a specific deployed contract. -func NewExecutionServiceMockTransactor(address common.Address, transactor bind.ContractTransactor) (*ExecutionServiceMockTransactor, error) { - contract, err := bindExecutionServiceMock(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ExecutionServiceMockTransactor{contract: contract}, nil -} - -// NewExecutionServiceMockFilterer creates a new log filterer instance of ExecutionServiceMock, bound to a specific deployed contract. -func NewExecutionServiceMockFilterer(address common.Address, filterer bind.ContractFilterer) (*ExecutionServiceMockFilterer, error) { - contract, err := bindExecutionServiceMock(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ExecutionServiceMockFilterer{contract: contract}, nil -} - -// bindExecutionServiceMock binds a generic wrapper to an already deployed contract. -func bindExecutionServiceMock(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ExecutionServiceMockMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ExecutionServiceMock *ExecutionServiceMockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ExecutionServiceMock.Contract.ExecutionServiceMockCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ExecutionServiceMock *ExecutionServiceMockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.ExecutionServiceMockTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_ExecutionServiceMock *ExecutionServiceMockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.ExecutionServiceMockTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ExecutionServiceMock *ExecutionServiceMockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ExecutionServiceMock.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ExecutionServiceMock *ExecutionServiceMockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_ExecutionServiceMock *ExecutionServiceMockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.contract.Transact(opts, method, params...) -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_ExecutionServiceMock *ExecutionServiceMockCaller) ExecutorEOA(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _ExecutionServiceMock.contract.Call(opts, &out, "executorEOA") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_ExecutionServiceMock *ExecutionServiceMockSession) ExecutorEOA() (common.Address, error) { - return _ExecutionServiceMock.Contract.ExecutorEOA(&_ExecutionServiceMock.CallOpts) -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_ExecutionServiceMock *ExecutionServiceMockCallerSession) ExecutorEOA() (common.Address, error) { - return _ExecutionServiceMock.Contract.ExecutorEOA(&_ExecutionServiceMock.CallOpts) -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_ExecutionServiceMock *ExecutionServiceMockCaller) GetExecutionFee(opts *bind.CallOpts, dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - var out []interface{} - err := _ExecutionServiceMock.contract.Call(opts, &out, "getExecutionFee", dstChainId, txPayloadSize, options) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_ExecutionServiceMock *ExecutionServiceMockSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - return _ExecutionServiceMock.Contract.GetExecutionFee(&_ExecutionServiceMock.CallOpts, dstChainId, txPayloadSize, options) -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_ExecutionServiceMock *ExecutionServiceMockCallerSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - return _ExecutionServiceMock.Contract.GetExecutionFee(&_ExecutionServiceMock.CallOpts, dstChainId, txPayloadSize, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_ExecutionServiceMock *ExecutionServiceMockTransactor) RequestExecution(opts *bind.TransactOpts, dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _ExecutionServiceMock.contract.Transact(opts, "requestExecution", dstChainId, txPayloadSize, transactionId, executionFee, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_ExecutionServiceMock *ExecutionServiceMockSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.RequestExecution(&_ExecutionServiceMock.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_ExecutionServiceMock *ExecutionServiceMockTransactorSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _ExecutionServiceMock.Contract.RequestExecution(&_ExecutionServiceMock.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) -} - -// IExecutionServiceMetaData contains all meta data concerning the IExecutionService contract. -var IExecutionServiceMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "62014bad": "executorEOA()", - "c473e7e8": "getExecutionFee(uint256,uint256,bytes)", - "e4e06522": "requestExecution(uint256,uint256,bytes32,uint256,bytes)", - }, -} - -// IExecutionServiceABI is the input ABI used to generate the binding from. -// Deprecated: Use IExecutionServiceMetaData.ABI instead. -var IExecutionServiceABI = IExecutionServiceMetaData.ABI - -// Deprecated: Use IExecutionServiceMetaData.Sigs instead. -// IExecutionServiceFuncSigs maps the 4-byte function signature to its string representation. -var IExecutionServiceFuncSigs = IExecutionServiceMetaData.Sigs - -// IExecutionService is an auto generated Go binding around an Ethereum contract. -type IExecutionService struct { - IExecutionServiceCaller // Read-only binding to the contract - IExecutionServiceTransactor // Write-only binding to the contract - IExecutionServiceFilterer // Log filterer for contract events -} - -// IExecutionServiceCaller is an auto generated read-only Go binding around an Ethereum contract. -type IExecutionServiceCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IExecutionServiceTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IExecutionServiceTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IExecutionServiceFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IExecutionServiceFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IExecutionServiceSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type IExecutionServiceSession struct { - Contract *IExecutionService // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IExecutionServiceCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type IExecutionServiceCallerSession struct { - Contract *IExecutionServiceCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// IExecutionServiceTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type IExecutionServiceTransactorSession struct { - Contract *IExecutionServiceTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IExecutionServiceRaw is an auto generated low-level Go binding around an Ethereum contract. -type IExecutionServiceRaw struct { - Contract *IExecutionService // Generic contract binding to access the raw methods on -} - -// IExecutionServiceCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IExecutionServiceCallerRaw struct { - Contract *IExecutionServiceCaller // Generic read-only contract binding to access the raw methods on -} - -// IExecutionServiceTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IExecutionServiceTransactorRaw struct { - Contract *IExecutionServiceTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewIExecutionService creates a new instance of IExecutionService, bound to a specific deployed contract. -func NewIExecutionService(address common.Address, backend bind.ContractBackend) (*IExecutionService, error) { - contract, err := bindIExecutionService(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &IExecutionService{IExecutionServiceCaller: IExecutionServiceCaller{contract: contract}, IExecutionServiceTransactor: IExecutionServiceTransactor{contract: contract}, IExecutionServiceFilterer: IExecutionServiceFilterer{contract: contract}}, nil -} - -// NewIExecutionServiceCaller creates a new read-only instance of IExecutionService, bound to a specific deployed contract. -func NewIExecutionServiceCaller(address common.Address, caller bind.ContractCaller) (*IExecutionServiceCaller, error) { - contract, err := bindIExecutionService(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IExecutionServiceCaller{contract: contract}, nil -} - -// NewIExecutionServiceTransactor creates a new write-only instance of IExecutionService, bound to a specific deployed contract. -func NewIExecutionServiceTransactor(address common.Address, transactor bind.ContractTransactor) (*IExecutionServiceTransactor, error) { - contract, err := bindIExecutionService(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IExecutionServiceTransactor{contract: contract}, nil -} - -// NewIExecutionServiceFilterer creates a new log filterer instance of IExecutionService, bound to a specific deployed contract. -func NewIExecutionServiceFilterer(address common.Address, filterer bind.ContractFilterer) (*IExecutionServiceFilterer, error) { - contract, err := bindIExecutionService(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IExecutionServiceFilterer{contract: contract}, nil -} - -// bindIExecutionService binds a generic wrapper to an already deployed contract. -func bindIExecutionService(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IExecutionServiceMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IExecutionService *IExecutionServiceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IExecutionService.Contract.IExecutionServiceCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IExecutionService *IExecutionServiceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IExecutionService.Contract.IExecutionServiceTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IExecutionService *IExecutionServiceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IExecutionService.Contract.IExecutionServiceTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IExecutionService *IExecutionServiceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IExecutionService.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IExecutionService *IExecutionServiceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IExecutionService.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IExecutionService *IExecutionServiceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IExecutionService.Contract.contract.Transact(opts, method, params...) -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_IExecutionService *IExecutionServiceCaller) ExecutorEOA(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _IExecutionService.contract.Call(opts, &out, "executorEOA") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_IExecutionService *IExecutionServiceSession) ExecutorEOA() (common.Address, error) { - return _IExecutionService.Contract.ExecutorEOA(&_IExecutionService.CallOpts) -} - -// ExecutorEOA is a free data retrieval call binding the contract method 0x62014bad. -// -// Solidity: function executorEOA() view returns(address) -func (_IExecutionService *IExecutionServiceCallerSession) ExecutorEOA() (common.Address, error) { - return _IExecutionService.Contract.ExecutorEOA(&_IExecutionService.CallOpts) -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_IExecutionService *IExecutionServiceCaller) GetExecutionFee(opts *bind.CallOpts, dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - var out []interface{} - err := _IExecutionService.contract.Call(opts, &out, "getExecutionFee", dstChainId, txPayloadSize, options) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_IExecutionService *IExecutionServiceSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - return _IExecutionService.Contract.GetExecutionFee(&_IExecutionService.CallOpts, dstChainId, txPayloadSize, options) -} - -// GetExecutionFee is a free data retrieval call binding the contract method 0xc473e7e8. -// -// Solidity: function getExecutionFee(uint256 dstChainId, uint256 txPayloadSize, bytes options) view returns(uint256) -func (_IExecutionService *IExecutionServiceCallerSession) GetExecutionFee(dstChainId *big.Int, txPayloadSize *big.Int, options []byte) (*big.Int, error) { - return _IExecutionService.Contract.GetExecutionFee(&_IExecutionService.CallOpts, dstChainId, txPayloadSize, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_IExecutionService *IExecutionServiceTransactor) RequestExecution(opts *bind.TransactOpts, dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _IExecutionService.contract.Transact(opts, "requestExecution", dstChainId, txPayloadSize, transactionId, executionFee, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_IExecutionService *IExecutionServiceSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _IExecutionService.Contract.RequestExecution(&_IExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) -} - -// RequestExecution is a paid mutator transaction binding the contract method 0xe4e06522. -// -// Solidity: function requestExecution(uint256 dstChainId, uint256 txPayloadSize, bytes32 transactionId, uint256 executionFee, bytes options) returns() -func (_IExecutionService *IExecutionServiceTransactorSession) RequestExecution(dstChainId *big.Int, txPayloadSize *big.Int, transactionId [32]byte, executionFee *big.Int, options []byte) (*types.Transaction, error) { - return _IExecutionService.Contract.RequestExecution(&_IExecutionService.TransactOpts, dstChainId, txPayloadSize, transactionId, executionFee, options) -} diff --git a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.contractinfo.json b/sin-executor/contracts/mocks/executionservicemock/executionservicemock.contractinfo.json deleted file mode 100644 index de8ee68d75..0000000000 --- a/sin-executor/contracts/mocks/executionservicemock/executionservicemock.contractinfo.json +++ /dev/null @@ -1 +0,0 @@ -{"solidity/ExecutionServiceMock.sol:ExecutionServiceMock":{"code":"0x608060405234801561001057600080fd5b50610290806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806362014bad14610046578063c473e7e814610090578063e4e06522146100b5575b600080fd5b6000546100669073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100a761009e3660046101a6565b60009392505050565b604051908152602001610087565b6100ca6100c33660046101f6565b5050505050565b005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261010c57600080fd5b813567ffffffffffffffff80821115610127576101276100cc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561016d5761016d6100cc565b8160405283815286602085880101111561018657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156101bb57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156101e057600080fd5b6101ec868287016100fb565b9150509250925092565b600080600080600060a0868803121561020e57600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff81111561024157600080fd5b61024d888289016100fb565b915050929550929590935056fea2646970667358221220c15c20205132b64aecd1865fd1e7602a4f626d5e1e0fd8064e46f96b970b8ecf64736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806362014bad14610046578063c473e7e814610090578063e4e06522146100b5575b600080fd5b6000546100669073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100a761009e3660046101a6565b60009392505050565b604051908152602001610087565b6100ca6100c33660046101f6565b5050505050565b005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261010c57600080fd5b813567ffffffffffffffff80821115610127576101276100cc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561016d5761016d6100cc565b8160405283815286602085880101111561018657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156101bb57600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156101e057600080fd5b6101ec868287016100fb565b9150509250925092565b600080600080600060a0868803121561020e57600080fd5b85359450602086013593506040860135925060608601359150608086013567ffffffffffffffff81111561024157600080fd5b61024d888289016100fb565b915050929550929590935056fea2646970667358221220c15c20205132b64aecd1865fd1e7602a4f626d5e1e0fd8064e46f96b970b8ecf64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0;\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// test/mocks/ExecutionServiceMock.sol\n\ncontract ExecutionServiceMock is IExecutionService {\n address public executorEOA;\n\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n {}\n\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256)\n {}\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"1995:485:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"1995:485:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2052:26;;;;;;;;;;;;190:42:1;178:55;;;160:74;;148:2;133:18;2052:26:0;;;;;;;;2296:182;;;;;;:::i;:::-;2463:7;2296:182;;;;;;;;;1823:25:1;;;1811:2;1796:18;2296:182:0;1677:177:1;2085:205:0;;;;;;:::i;:::-;;;;;;;;;245:184:1;297:77;294:1;287:88;394:4;391:1;384:15;418:4;415:1;408:15;434:777;476:5;529:3;522:4;514:6;510:17;506:27;496:55;;547:1;544;537:12;496:55;583:6;570:20;609:18;646:2;642;639:10;636:36;;;652:18;;:::i;:::-;786:2;780:9;848:4;840:13;;691:66;836:22;;;860:2;832:31;828:40;816:53;;;884:18;;;904:22;;;881:46;878:72;;;930:18;;:::i;:::-;970:10;966:2;959:22;1005:2;997:6;990:18;1051:3;1044:4;1039:2;1031:6;1027:15;1023:26;1020:35;1017:55;;;1068:1;1065;1058:12;1017:55;1132:2;1125:4;1117:6;1113:17;1106:4;1098:6;1094:17;1081:54;1179:1;1172:4;1167:2;1159:6;1155:15;1151:26;1144:37;1199:6;1190:15;;;;;;434:777;;;;:::o;1216:456::-;1302:6;1310;1318;1371:2;1359:9;1350:7;1346:23;1342:32;1339:52;;;1387:1;1384;1377:12;1339:52;1423:9;1410:23;1400:33;;1480:2;1469:9;1465:18;1452:32;1442:42;;1535:2;1524:9;1520:18;1507:32;1562:18;1554:6;1551:30;1548:50;;;1594:1;1591;1584:12;1548:50;1617:49;1658:7;1649:6;1638:9;1634:22;1617:49;:::i;:::-;1607:59;;;1216:456;;;;;:::o;1859:594::-;1963:6;1971;1979;1987;1995;2048:3;2036:9;2027:7;2023:23;2019:33;2016:53;;;2065:1;2062;2055:12;2016:53;2101:9;2088:23;2078:33;;2158:2;2147:9;2143:18;2130:32;2120:42;;2209:2;2198:9;2194:18;2181:32;2171:42;;2260:2;2249:9;2245:18;2232:32;2222:42;;2315:3;2304:9;2300:19;2287:33;2343:18;2335:6;2332:30;2329:50;;;2375:1;2372;2365:12;2329:50;2398:49;2439:7;2430:6;2419:9;2415:22;2398:49;:::i;:::-;2388:59;;;1859:594;;;;;;;;:::o","abiDefinition":[{"inputs":[],"name":"executorEOA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"getExecutionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"requestExecution","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutionFee(uint256,uint256,bytes)":{"notice":"Get the execution fee for executing an Interchain Transaction on a remote chain."},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"notice":"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getExecutionFee(uint256,uint256,bytes)":{"params":{"dstChainId":"The chain id of the destination chain.","options":"The options to use for the execution.","txPayloadSize":"The size of the transaction payload to use for the execution."}},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"details":"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.","params":{"dstChainId":"The chain id of the destination chain.","executionFee":"The fee paid for the execution.","options":"The options to use for the execution.","transactionId":"The id of the transaction to execute.","txPayloadSize":"The size of the transaction payload to use for the execution."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"options\":\"The options to use for the execution.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"details\":\"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.\",\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"executionFee\":\"The fee paid for the execution.\",\"options\":\"The options to use for the execution.\",\"transactionId\":\"The id of the transaction to execute.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"notice\":\"Get the execution fee for executing an Interchain Transaction on a remote chain.\"},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"notice\":\"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionServiceMock.sol\":\"ExecutionServiceMock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionServiceMock.sol\":{\"keccak256\":\"0xa5935b3eb2c60e4d0189746ffa6925c813f9ea7f13e7c58b413c224e73ceb8e1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6bf9ad704d73f4a97c1a1622ca5f85dc5f6de28e1f51bc28854d71c8ba2b787c\",\"dweb:/ipfs/QmdrU4ZnLqsBepPhFsWsUTmTE1U6YEPxhJpM26dvRAg99C\"]}},\"version\":1}"},"hashes":{"executorEOA()":"62014bad","getExecutionFee(uint256,uint256,bytes)":"c473e7e8","requestExecution(uint256,uint256,bytes32,uint256,bytes)":"e4e06522"}},"solidity/ExecutionServiceMock.sol:IExecutionService":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0;\n\n// contracts/interfaces/IExecutionService.sol\n\ninterface IExecutionService {\n function executorEOA() external view returns (address);\n /// @notice Request the execution of an Interchain Transaction on a remote chain.\n /// Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient\n /// event with the same transactionId, then execute the transaction on the remote chain:\n /// `dstInterchainClient.executeTransaction(transactionPayload)`\n /// Once the execution is confirmed on the source chain, the off-chain actor will be able\n /// to claim `executionFee` in the ExecutionFees contract.\n /// @dev Could only be called by `InterchainClient` contracts.\n /// Will revert if the execution fee is not big enough.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param transactionId The id of the transaction to execute.\n /// @param executionFee The fee paid for the execution.\n /// @param options The options to use for the execution.\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external;\n\n /// @notice Get the execution fee for executing an Interchain Transaction on a remote chain.\n /// @param dstChainId The chain id of the destination chain.\n /// @param txPayloadSize The size of the transaction payload to use for the execution.\n /// @param options The options to use for the execution.\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256);\n}\n\n// test/mocks/ExecutionServiceMock.sol\n\ncontract ExecutionServiceMock is IExecutionService {\n address public executorEOA;\n\n function requestExecution(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes32 transactionId,\n uint256 executionFee,\n bytes memory options\n )\n external\n {}\n\n function getExecutionFee(\n uint256 dstChainId,\n uint256 txPayloadSize,\n bytes memory options\n )\n external\n view\n returns (uint256)\n {}\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"executorEOA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"getExecutionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"txPayloadSize","type":"uint256"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"bytes","name":"options","type":"bytes"}],"name":"requestExecution","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutionFee(uint256,uint256,bytes)":{"notice":"Get the execution fee for executing an Interchain Transaction on a remote chain."},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"notice":"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getExecutionFee(uint256,uint256,bytes)":{"params":{"dstChainId":"The chain id of the destination chain.","options":"The options to use for the execution.","txPayloadSize":"The size of the transaction payload to use for the execution."}},"requestExecution(uint256,uint256,bytes32,uint256,bytes)":{"details":"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.","params":{"dstChainId":"The chain id of the destination chain.","executionFee":"The fee paid for the execution.","options":"The options to use for the execution.","transactionId":"The id of the transaction to execute.","txPayloadSize":"The size of the transaction payload to use for the execution."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"executorEOA\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"getExecutionFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"txPayloadSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"executionFee\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"}],\"name\":\"requestExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"options\":\"The options to use for the execution.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"details\":\"Could only be called by `InterchainClient` contracts. Will revert if the execution fee is not big enough.\",\"params\":{\"dstChainId\":\"The chain id of the destination chain.\",\"executionFee\":\"The fee paid for the execution.\",\"options\":\"The options to use for the execution.\",\"transactionId\":\"The id of the transaction to execute.\",\"txPayloadSize\":\"The size of the transaction payload to use for the execution.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutionFee(uint256,uint256,bytes)\":{\"notice\":\"Get the execution fee for executing an Interchain Transaction on a remote chain.\"},\"requestExecution(uint256,uint256,bytes32,uint256,bytes)\":{\"notice\":\"Request the execution of an Interchain Transaction on a remote chain. Note: the off-chain actor needs to fetch the transaction payload from the InterchainClient event with the same transactionId, then execute the transaction on the remote chain: `dstInterchainClient.executeTransaction(transactionPayload)` Once the execution is confirmed on the source chain, the off-chain actor will be able to claim `executionFee` in the ExecutionFees contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/ExecutionServiceMock.sol\":\"IExecutionService\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/ExecutionServiceMock.sol\":{\"keccak256\":\"0xa5935b3eb2c60e4d0189746ffa6925c813f9ea7f13e7c58b413c224e73ceb8e1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6bf9ad704d73f4a97c1a1622ca5f85dc5f6de28e1f51bc28854d71c8ba2b787c\",\"dweb:/ipfs/QmdrU4ZnLqsBepPhFsWsUTmTE1U6YEPxhJpM26dvRAg99C\"]}},\"version\":1}"},"hashes":{"executorEOA()":"62014bad","getExecutionFee(uint256,uint256,bytes)":"c473e7e8","requestExecution(uint256,uint256,bytes32,uint256,bytes)":"e4e06522"}}} \ No newline at end of file diff --git a/sin-executor/contracts/mocks/executionservicemock/generate.go b/sin-executor/contracts/mocks/executionservicemock/generate.go deleted file mode 100644 index 349ceddc42..0000000000 --- a/sin-executor/contracts/mocks/executionservicemock/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package executionservicemock - -//go:generate go run github.com/synapsecns/sanguine/tools/abigen generate --sol ../../../../packages/contracts-communication/flattened/ExecutionServiceMock.sol --pkg executionservicemock --sol-version 0.8.20 --filename executionservicemock --evm-version istanbul diff --git a/sin-executor/contracts/mocks/executionservicemock/helpers.go b/sin-executor/contracts/mocks/executionservicemock/helpers.go deleted file mode 100644 index d80a2585a0..0000000000 --- a/sin-executor/contracts/mocks/executionservicemock/helpers.go +++ /dev/null @@ -1,34 +0,0 @@ -// Package executionservicemock provides a mock for the ExecutionService contract. -package executionservicemock - -import ( - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" -) - -// ExecutionServicemockRef is a reference to a Executionservicemock. -// nolint: golint -type ExecutionServicemockRef struct { - *ExecutionServiceMock - address common.Address -} - -// Address is the contract address. -func (s *ExecutionServicemockRef) Address() common.Address { - return s.address -} - -// NewExecutionserviceMockRef creates a new Executionservicemock with a contract ref. -func NewExecutionserviceMockRef(address common.Address, backend bind.ContractBackend) (*ExecutionServicemockRef, error) { - instance, err := NewExecutionServiceMock(address, backend) - if err != nil { - return nil, err - } - return &ExecutionServicemockRef{ - ExecutionServiceMock: instance, - address: address, - }, nil -} - -var _ vm.ContractRef = &ExecutionServicemockRef{} diff --git a/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.abigen.go b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.abigen.go new file mode 100644 index 0000000000..6215435cec --- /dev/null +++ b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.abigen.go @@ -0,0 +1,558 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package gasoraclemock + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// GasOracleMockMetaData contains all meta data concerning the GasOracleMock contract. +var GasOracleMockMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "1e7b9287": "convertRemoteValueToLocalUnits(uint256,uint256)", + "5cbd3c48": "estimateTxCostInLocalUnits(uint256,uint256,uint256)", + "fd6a7167": "estimateTxCostInRemoteUnits(uint256,uint256,uint256)", + }, + Bin: "0x608060405234801561001057600080fd5b5060fc8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80631e7b92871460415780635cbd3c48146066578063fd6a7167146066575b600080fd5b6054604c366004607a565b600092915050565b60405190815260200160405180910390f35b60546071366004609b565b60009392505050565b60008060408385031215608c57600080fd5b50508035926020909101359150565b60008060006060848603121560af57600080fd5b50508135936020830135935060409092013591905056fea2646970667358221220d8e802cf67e61b25c6022989c4dcd8d2d60a5a11a7319acb8f31a0840e26db5864736f6c63430008140033", +} + +// GasOracleMockABI is the input ABI used to generate the binding from. +// Deprecated: Use GasOracleMockMetaData.ABI instead. +var GasOracleMockABI = GasOracleMockMetaData.ABI + +// Deprecated: Use GasOracleMockMetaData.Sigs instead. +// GasOracleMockFuncSigs maps the 4-byte function signature to its string representation. +var GasOracleMockFuncSigs = GasOracleMockMetaData.Sigs + +// GasOracleMockBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use GasOracleMockMetaData.Bin instead. +var GasOracleMockBin = GasOracleMockMetaData.Bin + +// DeployGasOracleMock deploys a new Ethereum contract, binding an instance of GasOracleMock to it. +func DeployGasOracleMock(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *GasOracleMock, error) { + parsed, err := GasOracleMockMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(GasOracleMockBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &GasOracleMock{GasOracleMockCaller: GasOracleMockCaller{contract: contract}, GasOracleMockTransactor: GasOracleMockTransactor{contract: contract}, GasOracleMockFilterer: GasOracleMockFilterer{contract: contract}}, nil +} + +// GasOracleMock is an auto generated Go binding around an Ethereum contract. +type GasOracleMock struct { + GasOracleMockCaller // Read-only binding to the contract + GasOracleMockTransactor // Write-only binding to the contract + GasOracleMockFilterer // Log filterer for contract events +} + +// GasOracleMockCaller is an auto generated read-only Go binding around an Ethereum contract. +type GasOracleMockCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GasOracleMockTransactor is an auto generated write-only Go binding around an Ethereum contract. +type GasOracleMockTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GasOracleMockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type GasOracleMockFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GasOracleMockSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type GasOracleMockSession struct { + Contract *GasOracleMock // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// GasOracleMockCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type GasOracleMockCallerSession struct { + Contract *GasOracleMockCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// GasOracleMockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type GasOracleMockTransactorSession struct { + Contract *GasOracleMockTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// GasOracleMockRaw is an auto generated low-level Go binding around an Ethereum contract. +type GasOracleMockRaw struct { + Contract *GasOracleMock // Generic contract binding to access the raw methods on +} + +// GasOracleMockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type GasOracleMockCallerRaw struct { + Contract *GasOracleMockCaller // Generic read-only contract binding to access the raw methods on +} + +// GasOracleMockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type GasOracleMockTransactorRaw struct { + Contract *GasOracleMockTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewGasOracleMock creates a new instance of GasOracleMock, bound to a specific deployed contract. +func NewGasOracleMock(address common.Address, backend bind.ContractBackend) (*GasOracleMock, error) { + contract, err := bindGasOracleMock(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &GasOracleMock{GasOracleMockCaller: GasOracleMockCaller{contract: contract}, GasOracleMockTransactor: GasOracleMockTransactor{contract: contract}, GasOracleMockFilterer: GasOracleMockFilterer{contract: contract}}, nil +} + +// NewGasOracleMockCaller creates a new read-only instance of GasOracleMock, bound to a specific deployed contract. +func NewGasOracleMockCaller(address common.Address, caller bind.ContractCaller) (*GasOracleMockCaller, error) { + contract, err := bindGasOracleMock(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &GasOracleMockCaller{contract: contract}, nil +} + +// NewGasOracleMockTransactor creates a new write-only instance of GasOracleMock, bound to a specific deployed contract. +func NewGasOracleMockTransactor(address common.Address, transactor bind.ContractTransactor) (*GasOracleMockTransactor, error) { + contract, err := bindGasOracleMock(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &GasOracleMockTransactor{contract: contract}, nil +} + +// NewGasOracleMockFilterer creates a new log filterer instance of GasOracleMock, bound to a specific deployed contract. +func NewGasOracleMockFilterer(address common.Address, filterer bind.ContractFilterer) (*GasOracleMockFilterer, error) { + contract, err := bindGasOracleMock(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &GasOracleMockFilterer{contract: contract}, nil +} + +// bindGasOracleMock binds a generic wrapper to an already deployed contract. +func bindGasOracleMock(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := GasOracleMockMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_GasOracleMock *GasOracleMockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _GasOracleMock.Contract.GasOracleMockCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_GasOracleMock *GasOracleMockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _GasOracleMock.Contract.GasOracleMockTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_GasOracleMock *GasOracleMockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _GasOracleMock.Contract.GasOracleMockTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_GasOracleMock *GasOracleMockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _GasOracleMock.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_GasOracleMock *GasOracleMockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _GasOracleMock.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_GasOracleMock *GasOracleMockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _GasOracleMock.Contract.contract.Transact(opts, method, params...) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_GasOracleMock *GasOracleMockCaller) ConvertRemoteValueToLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + var out []interface{} + err := _GasOracleMock.contract.Call(opts, &out, "convertRemoteValueToLocalUnits", remoteChainId, value) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_GasOracleMock *GasOracleMockSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.ConvertRemoteValueToLocalUnits(&_GasOracleMock.CallOpts, remoteChainId, value) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_GasOracleMock *GasOracleMockCallerSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.ConvertRemoteValueToLocalUnits(&_GasOracleMock.CallOpts, remoteChainId, value) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockCaller) EstimateTxCostInLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _GasOracleMock.contract.Call(opts, &out, "estimateTxCostInLocalUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.EstimateTxCostInLocalUnits(&_GasOracleMock.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockCallerSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.EstimateTxCostInLocalUnits(&_GasOracleMock.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockCaller) EstimateTxCostInRemoteUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _GasOracleMock.contract.Call(opts, &out, "estimateTxCostInRemoteUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.EstimateTxCostInRemoteUnits(&_GasOracleMock.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_GasOracleMock *GasOracleMockCallerSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _GasOracleMock.Contract.EstimateTxCostInRemoteUnits(&_GasOracleMock.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// IGasOracleMetaData contains all meta data concerning the IGasOracle contract. +var IGasOracleMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "1e7b9287": "convertRemoteValueToLocalUnits(uint256,uint256)", + "5cbd3c48": "estimateTxCostInLocalUnits(uint256,uint256,uint256)", + "fd6a7167": "estimateTxCostInRemoteUnits(uint256,uint256,uint256)", + }, +} + +// IGasOracleABI is the input ABI used to generate the binding from. +// Deprecated: Use IGasOracleMetaData.ABI instead. +var IGasOracleABI = IGasOracleMetaData.ABI + +// Deprecated: Use IGasOracleMetaData.Sigs instead. +// IGasOracleFuncSigs maps the 4-byte function signature to its string representation. +var IGasOracleFuncSigs = IGasOracleMetaData.Sigs + +// IGasOracle is an auto generated Go binding around an Ethereum contract. +type IGasOracle struct { + IGasOracleCaller // Read-only binding to the contract + IGasOracleTransactor // Write-only binding to the contract + IGasOracleFilterer // Log filterer for contract events +} + +// IGasOracleCaller is an auto generated read-only Go binding around an Ethereum contract. +type IGasOracleCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IGasOracleTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IGasOracleFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IGasOracleSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IGasOracleSession struct { + Contract *IGasOracle // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IGasOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IGasOracleCallerSession struct { + Contract *IGasOracleCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IGasOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IGasOracleTransactorSession struct { + Contract *IGasOracleTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IGasOracleRaw is an auto generated low-level Go binding around an Ethereum contract. +type IGasOracleRaw struct { + Contract *IGasOracle // Generic contract binding to access the raw methods on +} + +// IGasOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IGasOracleCallerRaw struct { + Contract *IGasOracleCaller // Generic read-only contract binding to access the raw methods on +} + +// IGasOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IGasOracleTransactorRaw struct { + Contract *IGasOracleTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIGasOracle creates a new instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracle(address common.Address, backend bind.ContractBackend) (*IGasOracle, error) { + contract, err := bindIGasOracle(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IGasOracle{IGasOracleCaller: IGasOracleCaller{contract: contract}, IGasOracleTransactor: IGasOracleTransactor{contract: contract}, IGasOracleFilterer: IGasOracleFilterer{contract: contract}}, nil +} + +// NewIGasOracleCaller creates a new read-only instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleCaller(address common.Address, caller bind.ContractCaller) (*IGasOracleCaller, error) { + contract, err := bindIGasOracle(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IGasOracleCaller{contract: contract}, nil +} + +// NewIGasOracleTransactor creates a new write-only instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*IGasOracleTransactor, error) { + contract, err := bindIGasOracle(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IGasOracleTransactor{contract: contract}, nil +} + +// NewIGasOracleFilterer creates a new log filterer instance of IGasOracle, bound to a specific deployed contract. +func NewIGasOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*IGasOracleFilterer, error) { + contract, err := bindIGasOracle(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IGasOracleFilterer{contract: contract}, nil +} + +// bindIGasOracle binds a generic wrapper to an already deployed contract. +func bindIGasOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IGasOracleMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IGasOracle *IGasOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IGasOracle.Contract.IGasOracleCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IGasOracle *IGasOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IGasOracle.Contract.IGasOracleTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IGasOracle *IGasOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IGasOracle.Contract.IGasOracleTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IGasOracle *IGasOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IGasOracle.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IGasOracle *IGasOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IGasOracle.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IGasOracle *IGasOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IGasOracle.Contract.contract.Transact(opts, method, params...) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) ConvertRemoteValueToLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "convertRemoteValueToLocalUnits", remoteChainId, value) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.ConvertRemoteValueToLocalUnits(&_IGasOracle.CallOpts, remoteChainId, value) +} + +// ConvertRemoteValueToLocalUnits is a free data retrieval call binding the contract method 0x1e7b9287. +// +// Solidity: function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) ConvertRemoteValueToLocalUnits(remoteChainId *big.Int, value *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.ConvertRemoteValueToLocalUnits(&_IGasOracle.CallOpts, remoteChainId, value) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) EstimateTxCostInLocalUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "estimateTxCostInLocalUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInLocalUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInLocalUnits is a free data retrieval call binding the contract method 0x5cbd3c48. +// +// Solidity: function estimateTxCostInLocalUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) EstimateTxCostInLocalUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInLocalUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCaller) EstimateTxCostInRemoteUnits(opts *bind.CallOpts, remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + var out []interface{} + err := _IGasOracle.contract.Call(opts, &out, "estimateTxCostInRemoteUnits", remoteChainId, gasLimit, calldataSize) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInRemoteUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} + +// EstimateTxCostInRemoteUnits is a free data retrieval call binding the contract method 0xfd6a7167. +// +// Solidity: function estimateTxCostInRemoteUnits(uint256 remoteChainId, uint256 gasLimit, uint256 calldataSize) view returns(uint256) +func (_IGasOracle *IGasOracleCallerSession) EstimateTxCostInRemoteUnits(remoteChainId *big.Int, gasLimit *big.Int, calldataSize *big.Int) (*big.Int, error) { + return _IGasOracle.Contract.EstimateTxCostInRemoteUnits(&_IGasOracle.CallOpts, remoteChainId, gasLimit, calldataSize) +} diff --git a/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.contractinfo.json b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.contractinfo.json new file mode 100644 index 0000000000..eed8268ec1 --- /dev/null +++ b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.contractinfo.json @@ -0,0 +1 @@ +{"solidity/GasOracleMock.sol:GasOracleMock":{"code":"0x608060405234801561001057600080fd5b5060fc8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80631e7b92871460415780635cbd3c48146066578063fd6a7167146066575b600080fd5b6054604c366004607a565b600092915050565b60405190815260200160405180910390f35b60546071366004609b565b60009392505050565b60008060408385031215608c57600080fd5b50508035926020909101359150565b60008060006060848603121560af57600080fd5b50508135936020830135935060409092013591905056fea2646970667358221220d8e802cf67e61b25c6022989c4dcd8d2d60a5a11a7319acb8f31a0840e26db5864736f6c63430008140033","runtime-code":"0x6080604052348015600f57600080fd5b5060043610603c5760003560e01c80631e7b92871460415780635cbd3c48146066578063fd6a7167146066575b600080fd5b6054604c366004607a565b600092915050565b60405190815260200160405180910390f35b60546071366004609b565b60009392505050565b60008060408385031215608c57600080fd5b50508035926020909101359150565b60008060006060848603121560af57600080fd5b50508135936020830135935060409092013591905056fea2646970667358221220d8e802cf67e61b25c6022989c4dcd8d2d60a5a11a7319acb8f31a0840e26db5864736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0;\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// test/mocks/GasOracleMock.sol\n\ncontract GasOracleMock is IGasOracle {\n function convertRemoteValueToLocalUnits(\n uint256 remoteChainId,\n uint256 value\n )\n external\n view\n override\n returns (uint256)\n {}\n\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n override\n returns (uint256)\n {}\n\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n override\n returns (uint256)\n {}\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"1807:653:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"1807:653:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1850:179;;;;;;:::i;:::-;2014:7;1850:179;;;;;;;;413:25:1;;;401:2;386:18;1850:179:0;;;;;;;2035:208;;;;;;:::i;:::-;2228:7;2035:208;;;;;;14:248:1;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:1;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:1:o;449:316::-;526:6;534;542;595:2;583:9;574:7;570:23;566:32;563:52;;;611:1;608;601:12;563:52;-1:-1:-1;;634:23:1;;;704:2;689:18;;676:32;;-1:-1:-1;755:2:1;740:18;;;727:32;;449:316;-1:-1:-1;449:316:1:o","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"convertRemoteValueToLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInRemoteUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"notice":"Convert a value from the native token of a remote chain to the local native token."},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token."},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token."}},"version":1},"developerDoc":{"kind":"dev","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"remoteChainId":"The chain id of the remote chain.","value":"The value to convert."}},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"remoteChainId\":\"The chain id of the remote chain.\",\"value\":\"The value to convert.\"}},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"notice\":\"Convert a value from the native token of a remote chain to the local native token.\"},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token.\"},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/GasOracleMock.sol\":\"GasOracleMock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/GasOracleMock.sol\":{\"keccak256\":\"0x0a5c5775772945f138b0e1d81d4b4f21b2263093f4a97189a1b2816723086894\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7744ed721ba01266912ca60321d1dd8e6be290623238abde804e2178e194329b\",\"dweb:/ipfs/QmbRU51Tj3JjiMgoyVav6U4u5ozHQEcg5WuGT6sGqxkZho\"]}},\"version\":1}"},"hashes":{"convertRemoteValueToLocalUnits(uint256,uint256)":"1e7b9287","estimateTxCostInLocalUnits(uint256,uint256,uint256)":"5cbd3c48","estimateTxCostInRemoteUnits(uint256,uint256,uint256)":"fd6a7167"}},"solidity/GasOracleMock.sol:IGasOracle":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0;\n\n// contracts/interfaces/IGasOracle.sol\n\ninterface IGasOracle {\n /// @notice Convert a value from the native token of a remote chain to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param value The value to convert.\n function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and convert it to the local native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n\n /// @notice Estimate the cost of execution a transaction on a remote chain,\n /// and return it as is in the remote chain's native token.\n /// @dev Will revert if no price is available for the remote chain.\n /// @param remoteChainId The chain id of the remote chain.\n /// @param gasLimit The gas limit of the transaction.\n /// @param calldataSize The size of the transaction calldata.\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n returns (uint256);\n}\n\n// test/mocks/GasOracleMock.sol\n\ncontract GasOracleMock is IGasOracle {\n function convertRemoteValueToLocalUnits(\n uint256 remoteChainId,\n uint256 value\n )\n external\n view\n override\n returns (uint256)\n {}\n\n function estimateTxCostInLocalUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n override\n returns (uint256)\n {}\n\n function estimateTxCostInRemoteUnits(\n uint256 remoteChainId,\n uint256 gasLimit,\n uint256 calldataSize\n )\n external\n view\n override\n returns (uint256)\n {}\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"convertRemoteValueToLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInLocalUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSize","type":"uint256"}],"name":"estimateTxCostInRemoteUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"notice":"Convert a value from the native token of a remote chain to the local native token."},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token."},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"notice":"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token."}},"version":1},"developerDoc":{"kind":"dev","methods":{"convertRemoteValueToLocalUnits(uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"remoteChainId":"The chain id of the remote chain.","value":"The value to convert."}},"estimateTxCostInLocalUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}},"estimateTxCostInRemoteUnits(uint256,uint256,uint256)":{"details":"Will revert if no price is available for the remote chain.","params":{"calldataSize":"The size of the transaction calldata.","gasLimit":"The gas limit of the transaction.","remoteChainId":"The chain id of the remote chain."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"convertRemoteValueToLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInLocalUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"remoteChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"calldataSize\",\"type\":\"uint256\"}],\"name\":\"estimateTxCostInRemoteUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"remoteChainId\":\"The chain id of the remote chain.\",\"value\":\"The value to convert.\"}},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"details\":\"Will revert if no price is available for the remote chain.\",\"params\":{\"calldataSize\":\"The size of the transaction calldata.\",\"gasLimit\":\"The gas limit of the transaction.\",\"remoteChainId\":\"The chain id of the remote chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"convertRemoteValueToLocalUnits(uint256,uint256)\":{\"notice\":\"Convert a value from the native token of a remote chain to the local native token.\"},\"estimateTxCostInLocalUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and convert it to the local native token.\"},\"estimateTxCostInRemoteUnits(uint256,uint256,uint256)\":{\"notice\":\"Estimate the cost of execution a transaction on a remote chain, and return it as is in the remote chain's native token.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/GasOracleMock.sol\":\"IGasOracle\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/GasOracleMock.sol\":{\"keccak256\":\"0x0a5c5775772945f138b0e1d81d4b4f21b2263093f4a97189a1b2816723086894\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7744ed721ba01266912ca60321d1dd8e6be290623238abde804e2178e194329b\",\"dweb:/ipfs/QmbRU51Tj3JjiMgoyVav6U4u5ozHQEcg5WuGT6sGqxkZho\"]}},\"version\":1}"},"hashes":{"convertRemoteValueToLocalUnits(uint256,uint256)":"1e7b9287","estimateTxCostInLocalUnits(uint256,uint256,uint256)":"5cbd3c48","estimateTxCostInRemoteUnits(uint256,uint256,uint256)":"fd6a7167"}}} \ No newline at end of file diff --git a/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.metadata.go b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.metadata.go new file mode 100644 index 0000000000..07c9e3211a --- /dev/null +++ b/sin-executor/contracts/mocks/gasoraclemock/gasoraclemock.metadata.go @@ -0,0 +1,25 @@ +// Code generated by synapse abigen DO NOT EDIT. +package gasoraclemock + +import ( + _ "embed" + "encoding/json" + "github.com/ethereum/go-ethereum/common/compiler" +) + +// rawContracts are the json we use to dervive the processed contracts +// +//go:embed gasoraclemock.contractinfo.json +var rawContracts []byte + +// Contracts are unmarshalled on start +var Contracts map[string]*compiler.Contract + +func init() { + // load contract metadata + var err error + err = json.Unmarshal(rawContracts, &Contracts) + if err != nil { + panic(err) + } +} diff --git a/sin-executor/contracts/mocks/gasoraclemock/generate.go b/sin-executor/contracts/mocks/gasoraclemock/generate.go new file mode 100644 index 0000000000..1934fd6a28 --- /dev/null +++ b/sin-executor/contracts/mocks/gasoraclemock/generate.go @@ -0,0 +1,3 @@ +package gasoraclemock + +//go:generate go run github.com/synapsecns/sanguine/tools/abigen generate --sol ../../../../packages/contracts-communication/flattened/GasOracleMock.sol --pkg gasoraclemock --sol-version 0.8.20 --filename gasoraclemock --evm-version istanbul diff --git a/sin-executor/contracts/mocks/gasoraclemock/helpers.go b/sin-executor/contracts/mocks/gasoraclemock/helpers.go new file mode 100644 index 0000000000..b5a0fe1508 --- /dev/null +++ b/sin-executor/contracts/mocks/gasoraclemock/helpers.go @@ -0,0 +1,35 @@ +// Package gasoraclemock provides a mock for the Gasoraclemock contract. +package gasoraclemock + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +// GasOracleMockMockRef is a reference to an interchain db. +type GasOracleMockMockRef struct { + *GasOracleMock + // address of the interchain client + address common.Address +} + +// Address is the contract address. +func (i *GasOracleMockMockRef) Address() common.Address { + return i.address +} + +// NewGasOracleMockRef creates a new interchain client with a contract ref. +func NewGasOracleMockRef(address common.Address, backend bind.ContractBackend) (*GasOracleMockMockRef, error) { + instance, err := NewGasOracleMock(address, backend) + if err != nil { + return nil, fmt.Errorf("could not create instance of InterchainClient: %w", err) + } + return &GasOracleMockMockRef{ + GasOracleMock: instance, + address: address, + }, nil +} + +var _ vm.ContractRef = &GasOracleMockMockRef{} diff --git a/sin-executor/contracts/mocks/interchainapp/interchainapp.abigen.go b/sin-executor/contracts/mocks/interchainapp/interchainapp.abigen.go index 7c3284d350..9bd7c05f82 100644 --- a/sin-executor/contracts/mocks/interchainapp/interchainapp.abigen.go +++ b/sin-executor/contracts/mocks/interchainapp/interchainapp.abigen.go @@ -32,7 +32,7 @@ var ( // AppConfigLibMetaData contains all meta data concerning the AppConfigLib contract. var AppConfigLibMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"AppConfigLib__IncorrectVersion\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202903a5b74bf91079aa6483b15964d61b54cfe5e67b89c3ff8dd6f8acee4ae07b64736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209f5affa708e3871fcbebed46226f189611882164b69517fcf6c6530ff05bbd4164736f6c63430008140033", } // AppConfigLibABI is the input ABI used to generate the binding from. @@ -846,7 +846,7 @@ func (_IInterchainClientV1 *IInterchainClientV1TransactorSession) WriteExecution // InterchainAppMetaData contains all meta data concerning the InterchainApp contract. var InterchainAppMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchain\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageRecieve\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainID\",\"type\":\"uint64\"}],\"name\":\"getLinkedIApp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOptimisticTimePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequiredResponses\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"}],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchain\",\"outputs\":[{\"internalType\":\"contractIInterchainClientV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"send\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainIDs\",\"type\":\"uint64[]\"},{\"internalType\":\"address[]\",\"name\":\"linkedIApps\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_requiredResponses\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_optimisticTimePeriod\",\"type\":\"uint64\"}],\"name\":\"setAppConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchain\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageRecieve\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainID\",\"type\":\"uint64\"}],\"name\":\"getLinkedIApp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOptimisticTimePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequiredResponses\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"}],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchain\",\"outputs\":[{\"internalType\":\"contractIInterchainClientV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"send\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainIDs\",\"type\":\"uint64[]\"},{\"internalType\":\"address[]\",\"name\":\"linkedIApps\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_executionService\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_requiredResponses\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_optimisticTimePeriod\",\"type\":\"uint64\"}],\"name\":\"setAppConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Sigs: map[string]string{ "b399470d": "appReceive(uint256,bytes32,uint256,bytes)", "bfc849ee": "getLinkedIApp(uint64)", @@ -858,9 +858,9 @@ var InterchainAppMetaData = &bind.MetaData{ "ab139613": "getSendingModules(bytes32,uint256)", "70838975": "interchain()", "e1ef3b3f": "send(bytes32,uint256,bytes)", - "dd34f56a": "setAppConfig(uint64[],address[],address[],address[],uint256,uint64)", + "645d575a": "setAppConfig(uint64[],address[],address[],address[],address,uint256,uint64)", }, - Bin: "0x60806040523480156200001157600080fd5b506040516200113c3803806200113c8339810160408190526200003491620001e5565b600080546001600160a01b0319166001600160a01b03851617905581516200006490600490602085019062000084565b5080516200007a90600590602084019062000084565b5050505062000262565b828054828255906000526020600020908101928215620000dc579160200282015b82811115620000dc57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620000a5565b50620000ea929150620000ee565b5090565b5b80821115620000ea5760008155600101620000ef565b80516001600160a01b03811681146200011d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014a57600080fd5b815160206001600160401b038083111562000169576200016962000122565b8260051b604051601f19603f8301168101818110848211171562000191576200019162000122565b604052938452858101830193838101925087851115620001b057600080fd5b83870191505b84821015620001da57620001ca8262000105565b83529183019190830190620001b6565b979650505050505050565b600080600060608486031215620001fb57600080fd5b620002068462000105565b60208501519093506001600160401b03808211156200022457600080fd5b620002328783880162000138565b935060408601519150808211156200024957600080fd5b50620002588682870162000138565b9150509250925092565b610eca80620002726000396000f3fe6080604052600436106100bc5760003560e01c8063b399470d11610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063b399470d146101a0578063bfc849ee146101b5578063dd34f56a1461020257600080fd5b80637c9abd3e116100a55780637c9abd3e1461013f578063a45e107a1461015e578063ab1396131461018057600080fd5b8063287bc057146100c157806370838975146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e49291906108c2565b60405180910390f35b3480156100f957600080fd5b5060005461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561014b57600080fd5b506007545b6040519081526020016100e4565b34801561016a57600080fd5b506101736102f3565b6040516100e491906108f0565b34801561018c57600080fd5b5061017361019b36600461090a565b610365565b6101b36101ae366004610975565b6103d8565b005b3480156101c157600080fd5b5061011a6101d03660046109f3565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b34801561020e57600080fd5b506101b361021d366004610ba0565b610408565b6101b3610230366004610c66565b6105af565b34801561024157600080fd5b506101736106ab565b34801561025657600080fd5b50600654610150565b604080518082019091526006548152600754602082015260609081906102849061071b565b60058054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b6060600360020180548060200260200160405190810160405280929190818152602001828054801561035b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156103ca57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161039f575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b845186511461049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8651811015610557578581815181106104bb576104bb610cb9565b6020026020010151600360000160008984815181106104dc576104dc610cb9565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061054f90610ce8565b9150506104a0565b506040805180820190915282815267ffffffffffffffff8216602091820181905260068490556007558451610592916004919087019061076e565b5082516105a690600590602086019061076e565b50505050505050565b60006105d2604051806040016040528062030d408152602001600081525061071b565b600080546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff16916398939d289134916106379189918b919060049089908c908c908401610d90565b604080518083038185885af1158015610654573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106799190610e35565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b6060600360010180548060200260200160405190810160405280929190818152602001828054801561035b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575050505050905090565b60606103d26001836040516020016107339190610e59565b60405160208183030381529060405260608282604051602001610757929190610e70565b604051602081830303815290604052905092915050565b8280548282559060005260206000209081019282156107e8579160200282015b828111156107e857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061078e565b506107f49291506107f8565b5090565b5b808211156107f457600081556001016107f9565b6000815180845260005b8181101561083357602081850181015186830182015201610817565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b838110156108b757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610885565b509495945050505050565b6040815260006108d5604083018561080d565b82810360208401526108e78185610871565b95945050505050565b6020815260006109036020830184610871565b9392505050565b6000806040838503121561091d57600080fd5b50508035926020909101359150565b60008083601f84011261093e57600080fd5b50813567ffffffffffffffff81111561095657600080fd5b60208301915083602082850101111561096e57600080fd5b9250929050565b60008060008060006080868803121561098d57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8111156109b957600080fd5b6109c58882890161092c565b969995985093965092949392505050565b803567ffffffffffffffff811681146109ee57600080fd5b919050565b600060208284031215610a0557600080fd5b610903826109d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a8457610a84610a0e565b604052919050565b600067ffffffffffffffff821115610aa657610aa6610a0e565b5060051b60200190565b600082601f830112610ac157600080fd5b81356020610ad6610ad183610a8c565b610a3d565b82815260059290921b84018101918181019086841115610af557600080fd5b8286015b84811015610b1757610b0a816109d6565b8352918301918301610af9565b509695505050505050565b600082601f830112610b3357600080fd5b81356020610b43610ad183610a8c565b82815260059290921b84018101918181019086841115610b6257600080fd5b8286015b84811015610b1757803573ffffffffffffffffffffffffffffffffffffffff81168114610b935760008081fd5b8352918301918301610b66565b60008060008060008060c08789031215610bb957600080fd5b863567ffffffffffffffff80821115610bd157600080fd5b610bdd8a838b01610ab0565b97506020890135915080821115610bf357600080fd5b610bff8a838b01610b22565b96506040890135915080821115610c1557600080fd5b610c218a838b01610b22565b95506060890135915080821115610c3757600080fd5b50610c4489828a01610b22565b93505060808701359150610c5a60a088016109d6565b90509295509295509295565b60008060008060608587031215610c7c57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610ca157600080fd5b610cad8782880161092c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610dfb578554841683526001958601959285019201610ddd565b50508581036080870152610e0f818a61080d565b935050505082810360a0840152610e27818587610d47565b9a9950505050505050505050565b60008060408385031215610e4857600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016103d2565b60ff83168152604060208201526000610e8c604083018461080d565b94935050505056fea2646970667358221220deb0d32be95187d250f63842fac6e4dcb0d75889233ae5bf48b8442be356140164736f6c63430008140033", + Bin: "0x60806040523480156200001157600080fd5b50604051620011a2380380620011a28339810160408190526200003491620001e5565b600080546001600160a01b0319166001600160a01b03851617905581516200006490600590602085019062000084565b5080516200007a90600690602084019062000084565b5050505062000262565b828054828255906000526020600020908101928215620000dc579160200282015b82811115620000dc57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620000a5565b50620000ea929150620000ee565b5090565b5b80821115620000ea5760008155600101620000ef565b80516001600160a01b03811681146200011d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014a57600080fd5b815160206001600160401b038083111562000169576200016962000122565b8260051b604051601f19603f8301168101818110848211171562000191576200019162000122565b604052938452858101830193838101925087851115620001b057600080fd5b83870191505b84821015620001da57620001ca8262000105565b83529183019190830190620001b6565b979650505050505050565b600080600060608486031215620001fb57600080fd5b620002068462000105565b60208501519093506001600160401b03808211156200022457600080fd5b620002328783880162000138565b935060408601519150808211156200024957600080fd5b50620002588682870162000138565b9150509250925092565b610f3080620002726000396000f3fe6080604052600436106100bc5760003560e01c8063ab13961311610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063ab139613146101a2578063b399470d146101c2578063bfc849ee146101d557600080fd5b806370838975116100a5578063708389751461010f5780637c9abd3e14610161578063a45e107a1461018057600080fd5b8063287bc057146100c1578063645d575a146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e492919061090e565b60405180910390f35b3480156100f957600080fd5b5061010d610108366004610af3565b6102f3565b005b34801561011b57600080fd5b5060005461013c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561016d57600080fd5b506008545b6040519081526020016100e4565b34801561018c57600080fd5b506101956104e0565b6040516100e49190610bcb565b3480156101ae57600080fd5b506101956101bd366004610be5565b610552565b61010d6101d0366004610c50565b6105c5565b3480156101e157600080fd5b5061013c6101f0366004610cb1565b67ffffffffffffffff1660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61010d610230366004610ccc565b6105f5565b34801561024157600080fd5b506101956106f7565b34801561025657600080fd5b50600754610172565b6040805180820190915260075481526008546020820152606090819061028490610767565b60068054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b8551875114610388576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8751811015610442578681815181106103a6576103a6610d1f565b6020026020010151600460000160008a84815181106103c7576103c7610d1f565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061043a90610d4e565b91505061038b565b506040805180820190915282815267ffffffffffffffff821660209182018190526007849055600855855161047d91600591908801906107ba565b5083516104919060069060208701906107ba565b5050600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff93909316929092179091555050505050565b6060600460020180548060200260200160405190810160405280929190818152602001828054801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b6000610618604051806040016040528062030d4081526020016000815250610767565b6000546003546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff918216926398939d28923492610683928a928c92169060059089908c908c90600401610df6565b604080518083038185885af11580156106a0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106c59190610e9b565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b606060046001018054806020026020016040519081016040528092919081815260200182805480156105485760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575050505050905090565b60606105bf60018360405160200161077f9190610ebf565b604051602081830303815290604052606082826040516020016107a3929190610ed6565b604051602081830303815290604052905092915050565b828054828255906000526020600020908101928215610834579160200282015b8281111561083457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906107da565b50610840929150610844565b5090565b5b808211156108405760008155600101610845565b6000815180845260005b8181101561087f57602081850181015186830182015201610863565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b8381101561090357815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016108d1565b509495945050505050565b6040815260006109216040830185610859565b828103602084015261093381856108bd565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b2576109b261093c565b604052919050565b600067ffffffffffffffff8211156109d4576109d461093c565b5060051b60200190565b803567ffffffffffffffff811681146109f657600080fd5b919050565b600082601f830112610a0c57600080fd5b81356020610a21610a1c836109ba565b61096b565b82815260059290921b84018101918181019086841115610a4057600080fd5b8286015b84811015610a6257610a55816109de565b8352918301918301610a44565b509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109f657600080fd5b600082601f830112610aa257600080fd5b81356020610ab2610a1c836109ba565b82815260059290921b84018101918181019086841115610ad157600080fd5b8286015b84811015610a6257610ae681610a6d565b8352918301918301610ad5565b600080600080600080600060e0888a031215610b0e57600080fd5b873567ffffffffffffffff80821115610b2657600080fd5b610b328b838c016109fb565b985060208a0135915080821115610b4857600080fd5b610b548b838c01610a91565b975060408a0135915080821115610b6a57600080fd5b610b768b838c01610a91565b965060608a0135915080821115610b8c57600080fd5b50610b998a828b01610a91565b945050610ba860808901610a6d565b925060a08801359150610bbd60c089016109de565b905092959891949750929550565b602081526000610bde60208301846108bd565b9392505050565b60008060408385031215610bf857600080fd5b50508035926020909101359150565b60008083601f840112610c1957600080fd5b50813567ffffffffffffffff811115610c3157600080fd5b602083019150836020828501011115610c4957600080fd5b9250929050565b600080600080600060808688031215610c6857600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115610c9457600080fd5b610ca088828901610c07565b969995985093965092949392505050565b600060208284031215610cc357600080fd5b610bde826109de565b60008060008060608587031215610ce257600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610d0757600080fd5b610d1387828801610c07565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610da6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610e61578554841683526001958601959285019201610e43565b50508581036080870152610e75818a610859565b935050505082810360a0840152610e8d818587610dad565b9a9950505050505050505050565b60008060408385031215610eae57600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016105bf565b60ff83168152604060208201526000610ef26040830184610859565b94935050505056fea2646970667358221220bfadb7a9cdcc8fe0a3a66c71b90675cf2087b9d292f5be92afcaa877f03bee4264736f6c63430008140033", } // InterchainAppABI is the input ABI used to generate the binding from. @@ -1325,25 +1325,25 @@ func (_InterchainApp *InterchainAppTransactorSession) Send(receiver [32]byte, ds return _InterchainApp.Contract.Send(&_InterchainApp.TransactOpts, receiver, dstChainId, message) } -// SetAppConfig is a paid mutator transaction binding the contract method 0xdd34f56a. +// SetAppConfig is a paid mutator transaction binding the contract method 0x645d575a. // -// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() -func (_InterchainApp *InterchainAppTransactor) SetAppConfig(opts *bind.TransactOpts, chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { - return _InterchainApp.contract.Transact(opts, "setAppConfig", chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod) +// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, address _executionService, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() +func (_InterchainApp *InterchainAppTransactor) SetAppConfig(opts *bind.TransactOpts, chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _executionService common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { + return _InterchainApp.contract.Transact(opts, "setAppConfig", chainIDs, linkedIApps, _sendingModules, _receivingModules, _executionService, _requiredResponses, _optimisticTimePeriod) } -// SetAppConfig is a paid mutator transaction binding the contract method 0xdd34f56a. +// SetAppConfig is a paid mutator transaction binding the contract method 0x645d575a. // -// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() -func (_InterchainApp *InterchainAppSession) SetAppConfig(chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { - return _InterchainApp.Contract.SetAppConfig(&_InterchainApp.TransactOpts, chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod) +// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, address _executionService, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() +func (_InterchainApp *InterchainAppSession) SetAppConfig(chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _executionService common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { + return _InterchainApp.Contract.SetAppConfig(&_InterchainApp.TransactOpts, chainIDs, linkedIApps, _sendingModules, _receivingModules, _executionService, _requiredResponses, _optimisticTimePeriod) } -// SetAppConfig is a paid mutator transaction binding the contract method 0xdd34f56a. +// SetAppConfig is a paid mutator transaction binding the contract method 0x645d575a. // -// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() -func (_InterchainApp *InterchainAppTransactorSession) SetAppConfig(chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { - return _InterchainApp.Contract.SetAppConfig(&_InterchainApp.TransactOpts, chainIDs, linkedIApps, _sendingModules, _receivingModules, _requiredResponses, _optimisticTimePeriod) +// Solidity: function setAppConfig(uint64[] chainIDs, address[] linkedIApps, address[] _sendingModules, address[] _receivingModules, address _executionService, uint256 _requiredResponses, uint64 _optimisticTimePeriod) returns() +func (_InterchainApp *InterchainAppTransactorSession) SetAppConfig(chainIDs []uint64, linkedIApps []common.Address, _sendingModules []common.Address, _receivingModules []common.Address, _executionService common.Address, _requiredResponses *big.Int, _optimisticTimePeriod uint64) (*types.Transaction, error) { + return _InterchainApp.Contract.SetAppConfig(&_InterchainApp.TransactOpts, chainIDs, linkedIApps, _sendingModules, _receivingModules, _executionService, _requiredResponses, _optimisticTimePeriod) } // InterchainAppAppMessageRecieveIterator is returned from FilterAppMessageRecieve and is used to iterate over the raw logs and unpacked data for AppMessageRecieve events raised by the InterchainApp contract. @@ -1615,7 +1615,7 @@ func (_InterchainApp *InterchainAppFilterer) ParseAppMessageSent(log types.Log) // OptionsLibMetaData contains all meta data concerning the OptionsLib contract. var OptionsLibMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b2c3de9937032edff8f1c18bb925e9494b1a02c2fd9043eafec8956a572995c964736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122092452693727ca9b81af205ba6b3ab0381c3222743ca25625f9ee98bdafee4dbe64736f6c63430008140033", } // OptionsLibABI is the input ABI used to generate the binding from. diff --git a/sin-executor/contracts/mocks/interchainapp/interchainapp.contractinfo.json b/sin-executor/contracts/mocks/interchainapp/interchainapp.contractinfo.json index 3c8636b2b2..5883e4cae7 100644 --- a/sin-executor/contracts/mocks/interchainapp/interchainapp.contractinfo.json +++ b/sin-executor/contracts/mocks/interchainapp/interchainapp.contractinfo.json @@ -1 +1 @@ -{"solidity/InterchainApp.sol:AppConfigLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202903a5b74bf91079aa6483b15964d61b54cfe5e67b89c3ff8dd6f8acee4ae07b64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202903a5b74bf91079aa6483b15964d61b54cfe5e67b89c3ff8dd6f8acee4ae07b64736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"6580:2072:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;6580:2072:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"6580:2072:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"AppConfigLib__IncorrectVersion","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"AppConfigLib__IncorrectVersion\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"AppConfigLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0xcee8324dd3c75392a8c5dc86ef57f1b2347902be227511446576f37bc440d7b1\",\"urls\":[\"bzz-raw://5cb95195c4bbe4c8203791b87b20b95c6420594d1874d58cb002229c2d215a69\",\"dweb:/ipfs/QmfGPkVPJxAyDpDPHwx4gbdPgdhViLE96QohaZMdZNT9vh\"]}},\"version\":1}"},"hashes":{}},"solidity/InterchainApp.sol:IInterchainApp":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"appReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getReceivingConfig","outputs":[{"internalType":"bytes","name":"appConfig","type":"bytes"},{"internalType":"address[]","name":"modules","type":"address[]"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"notice":"Minimal interface for the Interchain App to work with the Interchain Client.","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"appConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"modules\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Minimal interface for the Interchain App to work with the Interchain Client.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"IInterchainApp\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0xcee8324dd3c75392a8c5dc86ef57f1b2347902be227511446576f37bc440d7b1\",\"urls\":[\"bzz-raw://5cb95195c4bbe4c8203791b87b20b95c6420594d1874d58cb002229c2d215a69\",\"dweb:/ipfs/QmfGPkVPJxAyDpDPHwx4gbdPgdhViLE96QohaZMdZNT9vh\"]}},\"version\":1}"},"hashes":{"appReceive(uint256,bytes32,uint256,bytes)":"b399470d","getReceivingConfig()":"287bc057"}},"solidity/InterchainApp.sol:IInterchainClientV1":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__FeeAmountTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"InterchainClientV1__IncorrectDstChainId","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__IncorrectMsgValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"InterchainClientV1__IncorrectSrcChainId","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__NotEnoughResponses","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxAlreadyExecuted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxNotExecuted","type":"error"},{"inputs":[{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"getExecutor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"getExecutorById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"getInterchainFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"interchainExecute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSend","outputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSendEVM","outputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"isExecutable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"executionFees_","type":"address"}],"name":"setExecutionFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes32","name":"client","type":"bytes32"}],"name":"setLinkedClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"writeExecutionProof","outputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutor(bytes)":{"notice":"Returns the address of the executor for a transaction that has been sent to the local chain."},"getExecutorById(bytes32)":{"notice":"Returns the address of the executor for a transaction that has been sent to the local chain."},"getInterchainFee(uint256,address,address[],bytes,bytes)":{"notice":"Returns the fee for sending an Interchain message."},"interchainExecute(uint256,bytes)":{"notice":"Executes a transaction that has been sent via the Interchain."},"interchainSend(uint256,bytes32,address,address[],bytes,bytes)":{"notice":"Sends a message to another chain via the Interchain Communication Protocol."},"isExecutable(bytes)":{"notice":"Checks if a transaction is executable."},"setExecutionFees(address)":{"notice":"Sets the address of the ExecutionFees contract."},"setLinkedClient(uint256,bytes32)":{"notice":"Sets the linked client for a specific chain ID."},"writeExecutionProof(bytes32)":{"notice":"Writes the proof of execution for a transaction into the InterchainDB."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getInterchainFee(uint256,address,address[],bytes,bytes)":{"params":{"dstChainId":"The chain ID of the destination chain.","message":"The message being sent.","options":"Execution options for the message sent, currently gas limit + native gas drop.","srcExecutionService":"The address of the execution service to use for the message.","srcModules":"The source modules involved in the message sending."}},"interchainExecute(uint256,bytes)":{"details":"The transaction must have been previously sent and recorded. Transaction data includes the requested gas limit, but the executors could specify a different gas limit. If the specified gas limit is lower than requested, the requested gas limit will be used. Otherwise, the specified gas limit will be used. This allows to execute the transactions with requested gas limit set too low.","params":{"gasLimit":"The gas limit to use for the execution.","transaction":"The transaction data."}},"interchainSend(uint256,bytes32,address,address[],bytes,bytes)":{"details":"Charges a fee for the message, which is payable upon calling this function: - Verification fees: paid to every module that verifies the message. - Execution fee: paid to the executor that executes the message. Note: while a specific execution service is specified to request the execution of the message, any executor is able to execute the message on destination chain, earning the execution fee.","params":{"dstChainId":"The chain ID of the destination chain.","message":"The message being sent.","options":"Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.","receiver":"The address of the receiver on the destination chain.","srcExecutionService":"The address of the execution service to use for the message.","srcModules":"The source modules involved in the message sending."},"returns":{"dbNonce":"The database nonce of the written entry for the transaction.","transactionId":"The ID of the transaction that was sent."}},"isExecutable(bytes)":{"details":"Determines if a transaction meets the criteria to be executed based on: - If approved modules have written to the InterchainDB - If the threshold of approved modules have been met - If the optimistic window has passed for all modules","params":{"transaction":"The InterchainTransaction struct to be checked."},"returns":{"_0":"bool Returns true if the transaction is executable, false otherwise."}},"setExecutionFees(address)":{"details":"Only callable by the contract owner or an authorized account.","params":{"executionFees_":"The address of the ExecutionFees contract."}},"setLinkedClient(uint256,bytes32)":{"details":"Stores the address of the linked client in a mapping with the chain ID as the key.","params":{"chainId":"The chain ID for which the client is being set.","client":"The address of the client being linked."}},"writeExecutionProof(bytes32)":{"details":"Will revert if the transaction has not been executed.","params":{"transactionId":"The ID of the transaction to write the proof for."},"returns":{"dbNonce":" The database nonce of the written entry for the proof."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__FeeAmountTooLow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectDstChainId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectSrcChainId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__NotEnoughResponses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"InterchainClientV1__TxAlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"InterchainClientV1__TxNotExecuted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"getExecutor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"getExecutorById\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"getInterchainFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"interchainExecute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"interchainSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"interchainSendEVM\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"isExecutable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"executionFees_\",\"type\":\"address\"}],\"name\":\"setExecutionFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"client\",\"type\":\"bytes32\"}],\"name\":\"setLinkedClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"writeExecutionProof\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getInterchainFee(uint256,address,address[],bytes,bytes)\":{\"params\":{\"dstChainId\":\"The chain ID of the destination chain.\",\"message\":\"The message being sent.\",\"options\":\"Execution options for the message sent, currently gas limit + native gas drop.\",\"srcExecutionService\":\"The address of the execution service to use for the message.\",\"srcModules\":\"The source modules involved in the message sending.\"}},\"interchainExecute(uint256,bytes)\":{\"details\":\"The transaction must have been previously sent and recorded. Transaction data includes the requested gas limit, but the executors could specify a different gas limit. If the specified gas limit is lower than requested, the requested gas limit will be used. Otherwise, the specified gas limit will be used. This allows to execute the transactions with requested gas limit set too low.\",\"params\":{\"gasLimit\":\"The gas limit to use for the execution.\",\"transaction\":\"The transaction data.\"}},\"interchainSend(uint256,bytes32,address,address[],bytes,bytes)\":{\"details\":\"Charges a fee for the message, which is payable upon calling this function: - Verification fees: paid to every module that verifies the message. - Execution fee: paid to the executor that executes the message. Note: while a specific execution service is specified to request the execution of the message, any executor is able to execute the message on destination chain, earning the execution fee.\",\"params\":{\"dstChainId\":\"The chain ID of the destination chain.\",\"message\":\"The message being sent.\",\"options\":\"Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\",\"receiver\":\"The address of the receiver on the destination chain.\",\"srcExecutionService\":\"The address of the execution service to use for the message.\",\"srcModules\":\"The source modules involved in the message sending.\"},\"returns\":{\"dbNonce\":\"The database nonce of the written entry for the transaction.\",\"transactionId\":\"The ID of the transaction that was sent.\"}},\"isExecutable(bytes)\":{\"details\":\"Determines if a transaction meets the criteria to be executed based on: - If approved modules have written to the InterchainDB - If the threshold of approved modules have been met - If the optimistic window has passed for all modules\",\"params\":{\"transaction\":\"The InterchainTransaction struct to be checked.\"},\"returns\":{\"_0\":\"bool Returns true if the transaction is executable, false otherwise.\"}},\"setExecutionFees(address)\":{\"details\":\"Only callable by the contract owner or an authorized account.\",\"params\":{\"executionFees_\":\"The address of the ExecutionFees contract.\"}},\"setLinkedClient(uint256,bytes32)\":{\"details\":\"Stores the address of the linked client in a mapping with the chain ID as the key.\",\"params\":{\"chainId\":\"The chain ID for which the client is being set.\",\"client\":\"The address of the client being linked.\"}},\"writeExecutionProof(bytes32)\":{\"details\":\"Will revert if the transaction has not been executed.\",\"params\":{\"transactionId\":\"The ID of the transaction to write the proof for.\"},\"returns\":{\"dbNonce\":\" The database nonce of the written entry for the proof.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutor(bytes)\":{\"notice\":\"Returns the address of the executor for a transaction that has been sent to the local chain.\"},\"getExecutorById(bytes32)\":{\"notice\":\"Returns the address of the executor for a transaction that has been sent to the local chain.\"},\"getInterchainFee(uint256,address,address[],bytes,bytes)\":{\"notice\":\"Returns the fee for sending an Interchain message.\"},\"interchainExecute(uint256,bytes)\":{\"notice\":\"Executes a transaction that has been sent via the Interchain.\"},\"interchainSend(uint256,bytes32,address,address[],bytes,bytes)\":{\"notice\":\"Sends a message to another chain via the Interchain Communication Protocol.\"},\"isExecutable(bytes)\":{\"notice\":\"Checks if a transaction is executable.\"},\"setExecutionFees(address)\":{\"notice\":\"Sets the address of the ExecutionFees contract.\"},\"setLinkedClient(uint256,bytes32)\":{\"notice\":\"Sets the linked client for a specific chain ID.\"},\"writeExecutionProof(bytes32)\":{\"notice\":\"Writes the proof of execution for a transaction into the InterchainDB.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"IInterchainClientV1\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0xcee8324dd3c75392a8c5dc86ef57f1b2347902be227511446576f37bc440d7b1\",\"urls\":[\"bzz-raw://5cb95195c4bbe4c8203791b87b20b95c6420594d1874d58cb002229c2d215a69\",\"dweb:/ipfs/QmfGPkVPJxAyDpDPHwx4gbdPgdhViLE96QohaZMdZNT9vh\"]}},\"version\":1}"},"hashes":{"getExecutor(bytes)":"f92a79ff","getExecutorById(bytes32)":"f1a61fac","getInterchainFee(uint256,address,address[],bytes,bytes)":"3c383e7b","interchainExecute(uint256,bytes)":"80efe777","interchainSend(uint256,bytes32,address,address[],bytes,bytes)":"98939d28","interchainSendEVM(uint256,address,address,address[],bytes,bytes)":"827f940d","isExecutable(bytes)":"31afa7de","setExecutionFees(address)":"3dc68b87","setLinkedClient(uint256,bytes32)":"f34234c8","writeExecutionProof(bytes32)":"90e81077"}},"solidity/InterchainApp.sol:InterchainApp":{"code":"0x60806040523480156200001157600080fd5b506040516200113c3803806200113c8339810160408190526200003491620001e5565b600080546001600160a01b0319166001600160a01b03851617905581516200006490600490602085019062000084565b5080516200007a90600590602084019062000084565b5050505062000262565b828054828255906000526020600020908101928215620000dc579160200282015b82811115620000dc57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620000a5565b50620000ea929150620000ee565b5090565b5b80821115620000ea5760008155600101620000ef565b80516001600160a01b03811681146200011d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014a57600080fd5b815160206001600160401b038083111562000169576200016962000122565b8260051b604051601f19603f8301168101818110848211171562000191576200019162000122565b604052938452858101830193838101925087851115620001b057600080fd5b83870191505b84821015620001da57620001ca8262000105565b83529183019190830190620001b6565b979650505050505050565b600080600060608486031215620001fb57600080fd5b620002068462000105565b60208501519093506001600160401b03808211156200022457600080fd5b620002328783880162000138565b935060408601519150808211156200024957600080fd5b50620002588682870162000138565b9150509250925092565b610eca80620002726000396000f3fe6080604052600436106100bc5760003560e01c8063b399470d11610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063b399470d146101a0578063bfc849ee146101b5578063dd34f56a1461020257600080fd5b80637c9abd3e116100a55780637c9abd3e1461013f578063a45e107a1461015e578063ab1396131461018057600080fd5b8063287bc057146100c157806370838975146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e49291906108c2565b60405180910390f35b3480156100f957600080fd5b5060005461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561014b57600080fd5b506007545b6040519081526020016100e4565b34801561016a57600080fd5b506101736102f3565b6040516100e491906108f0565b34801561018c57600080fd5b5061017361019b36600461090a565b610365565b6101b36101ae366004610975565b6103d8565b005b3480156101c157600080fd5b5061011a6101d03660046109f3565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b34801561020e57600080fd5b506101b361021d366004610ba0565b610408565b6101b3610230366004610c66565b6105af565b34801561024157600080fd5b506101736106ab565b34801561025657600080fd5b50600654610150565b604080518082019091526006548152600754602082015260609081906102849061071b565b60058054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b6060600360020180548060200260200160405190810160405280929190818152602001828054801561035b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156103ca57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161039f575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b845186511461049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8651811015610557578581815181106104bb576104bb610cb9565b6020026020010151600360000160008984815181106104dc576104dc610cb9565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061054f90610ce8565b9150506104a0565b506040805180820190915282815267ffffffffffffffff8216602091820181905260068490556007558451610592916004919087019061076e565b5082516105a690600590602086019061076e565b50505050505050565b60006105d2604051806040016040528062030d408152602001600081525061071b565b600080546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff16916398939d289134916106379189918b919060049089908c908c908401610d90565b604080518083038185885af1158015610654573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106799190610e35565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b6060600360010180548060200260200160405190810160405280929190818152602001828054801561035b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575050505050905090565b60606103d26001836040516020016107339190610e59565b60405160208183030381529060405260608282604051602001610757929190610e70565b604051602081830303815290604052905092915050565b8280548282559060005260206000209081019282156107e8579160200282015b828111156107e857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061078e565b506107f49291506107f8565b5090565b5b808211156107f457600081556001016107f9565b6000815180845260005b8181101561083357602081850181015186830182015201610817565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b838110156108b757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610885565b509495945050505050565b6040815260006108d5604083018561080d565b82810360208401526108e78185610871565b95945050505050565b6020815260006109036020830184610871565b9392505050565b6000806040838503121561091d57600080fd5b50508035926020909101359150565b60008083601f84011261093e57600080fd5b50813567ffffffffffffffff81111561095657600080fd5b60208301915083602082850101111561096e57600080fd5b9250929050565b60008060008060006080868803121561098d57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8111156109b957600080fd5b6109c58882890161092c565b969995985093965092949392505050565b803567ffffffffffffffff811681146109ee57600080fd5b919050565b600060208284031215610a0557600080fd5b610903826109d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a8457610a84610a0e565b604052919050565b600067ffffffffffffffff821115610aa657610aa6610a0e565b5060051b60200190565b600082601f830112610ac157600080fd5b81356020610ad6610ad183610a8c565b610a3d565b82815260059290921b84018101918181019086841115610af557600080fd5b8286015b84811015610b1757610b0a816109d6565b8352918301918301610af9565b509695505050505050565b600082601f830112610b3357600080fd5b81356020610b43610ad183610a8c565b82815260059290921b84018101918181019086841115610b6257600080fd5b8286015b84811015610b1757803573ffffffffffffffffffffffffffffffffffffffff81168114610b935760008081fd5b8352918301918301610b66565b60008060008060008060c08789031215610bb957600080fd5b863567ffffffffffffffff80821115610bd157600080fd5b610bdd8a838b01610ab0565b97506020890135915080821115610bf357600080fd5b610bff8a838b01610b22565b96506040890135915080821115610c1557600080fd5b610c218a838b01610b22565b95506060890135915080821115610c3757600080fd5b50610c4489828a01610b22565b93505060808701359150610c5a60a088016109d6565b90509295509295509295565b60008060008060608587031215610c7c57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610ca157600080fd5b610cad8782880161092c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610dfb578554841683526001958601959285019201610ddd565b50508581036080870152610e0f818a61080d565b935050505082810360a0840152610e27818587610d47565b9a9950505050505050505050565b60008060408385031215610e4857600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016103d2565b60ff83168152604060208201526000610e8c604083018461080d565b94935050505056fea2646970667358221220deb0d32be95187d250f63842fac6e4dcb0d75889233ae5bf48b8442be356140164736f6c63430008140033","runtime-code":"0x6080604052600436106100bc5760003560e01c8063b399470d11610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063b399470d146101a0578063bfc849ee146101b5578063dd34f56a1461020257600080fd5b80637c9abd3e116100a55780637c9abd3e1461013f578063a45e107a1461015e578063ab1396131461018057600080fd5b8063287bc057146100c157806370838975146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e49291906108c2565b60405180910390f35b3480156100f957600080fd5b5060005461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561014b57600080fd5b506007545b6040519081526020016100e4565b34801561016a57600080fd5b506101736102f3565b6040516100e491906108f0565b34801561018c57600080fd5b5061017361019b36600461090a565b610365565b6101b36101ae366004610975565b6103d8565b005b3480156101c157600080fd5b5061011a6101d03660046109f3565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b34801561020e57600080fd5b506101b361021d366004610ba0565b610408565b6101b3610230366004610c66565b6105af565b34801561024157600080fd5b506101736106ab565b34801561025657600080fd5b50600654610150565b604080518082019091526006548152600754602082015260609081906102849061071b565b60058054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b6060600360020180548060200260200160405190810160405280929190818152602001828054801561035b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156103ca57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161039f575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b845186511461049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8651811015610557578581815181106104bb576104bb610cb9565b6020026020010151600360000160008984815181106104dc576104dc610cb9565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061054f90610ce8565b9150506104a0565b506040805180820190915282815267ffffffffffffffff8216602091820181905260068490556007558451610592916004919087019061076e565b5082516105a690600590602086019061076e565b50505050505050565b60006105d2604051806040016040528062030d408152602001600081525061071b565b600080546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff16916398939d289134916106379189918b919060049089908c908c908401610d90565b604080518083038185885af1158015610654573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106799190610e35565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b6060600360010180548060200260200160405190810160405280929190818152602001828054801561035b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610330575050505050905090565b60606103d26001836040516020016107339190610e59565b60405160208183030381529060405260608282604051602001610757929190610e70565b604051602081830303815290604052905092915050565b8280548282559060005260206000209081019282156107e8579160200282015b828111156107e857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061078e565b506107f49291506107f8565b5090565b5b808211156107f457600081556001016107f9565b6000815180845260005b8181101561083357602081850181015186830182015201610817565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b838110156108b757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610885565b509495945050505050565b6040815260006108d5604083018561080d565b82810360208401526108e78185610871565b95945050505050565b6020815260006109036020830184610871565b9392505050565b6000806040838503121561091d57600080fd5b50508035926020909101359150565b60008083601f84011261093e57600080fd5b50813567ffffffffffffffff81111561095657600080fd5b60208301915083602082850101111561096e57600080fd5b9250929050565b60008060008060006080868803121561098d57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8111156109b957600080fd5b6109c58882890161092c565b969995985093965092949392505050565b803567ffffffffffffffff811681146109ee57600080fd5b919050565b600060208284031215610a0557600080fd5b610903826109d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a8457610a84610a0e565b604052919050565b600067ffffffffffffffff821115610aa657610aa6610a0e565b5060051b60200190565b600082601f830112610ac157600080fd5b81356020610ad6610ad183610a8c565b610a3d565b82815260059290921b84018101918181019086841115610af557600080fd5b8286015b84811015610b1757610b0a816109d6565b8352918301918301610af9565b509695505050505050565b600082601f830112610b3357600080fd5b81356020610b43610ad183610a8c565b82815260059290921b84018101918181019086841115610b6257600080fd5b8286015b84811015610b1757803573ffffffffffffffffffffffffffffffffffffffff81168114610b935760008081fd5b8352918301918301610b66565b60008060008060008060c08789031215610bb957600080fd5b863567ffffffffffffffff80821115610bd157600080fd5b610bdd8a838b01610ab0565b97506020890135915080821115610bf357600080fd5b610bff8a838b01610b22565b96506040890135915080821115610c1557600080fd5b610c218a838b01610b22565b95506060890135915080821115610c3757600080fd5b50610c4489828a01610b22565b93505060808701359150610c5a60a088016109d6565b90509295509295509295565b60008060008060608587031215610c7c57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610ca157600080fd5b610cad8782880161092c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610dfb578554841683526001958601959285019201610ddd565b50508581036080870152610e0f818a61080d565b935050505082810360a0840152610e27818587610d47565b9a9950505050505050505050565b60008060408385031215610e4857600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016103d2565b60ff83168152604060208201526000610e8c604083018461080d565b94935050505056fea2646970667358221220deb0d32be95187d250f63842fac6e4dcb0d75889233ae5bf48b8442be356140164736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"11163:3833:0:-:0;;;13926:283;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14039:10;:45;;-1:-1:-1;;;;;;14039:45:0;-1:-1:-1;;;;;14039:45:0;;;;;14094:47;;;;:29;;:47;;;;;:::i;:::-;-1:-1:-1;14151:51:0;;;;:31;;:51;;;;;:::i;:::-;;13926:283;;;11163:3833;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;11163:3833:0;-1:-1:-1;;;;;11163:3833:0;;;;;;;;;;;-1:-1:-1;11163:3833:0;;;;;;;-1:-1:-1;11163:3833:0;;;-1:-1:-1;11163:3833:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:177:1;93:13;;-1:-1:-1;;;;;135:31:1;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:127::-;257:10;252:3;248:20;245:1;238:31;288:4;285:1;278:15;312:4;309:1;302:15;328:923;393:5;446:3;439:4;431:6;427:17;423:27;413:55;;464:1;461;454:12;413:55;487:13;;519:4;-1:-1:-1;;;;;572:10:1;;;569:36;;;585:18;;:::i;:::-;631:2;628:1;624:10;663:2;657:9;726:2;722:7;717:2;713;709:11;705:25;697:6;693:38;781:6;769:10;766:22;761:2;749:10;746:18;743:46;740:72;;;792:18;;:::i;:::-;828:2;821:22;878:18;;;954:15;;;950:24;;;912:15;;;;-1:-1:-1;986:15:1;;;983:35;;;1014:1;1011;1004:12;983:35;1050:2;1042:6;1038:15;1027:26;;1062:159;1078:6;1073:3;1070:15;1062:159;;;1144:34;1174:3;1144:34;:::i;:::-;1132:47;;1199:12;;;;1095;;;;1062:159;;;1239:6;328:923;-1:-1:-1;;;;;;;328:923:1:o;1256:699::-;1394:6;1402;1410;1463:2;1451:9;1442:7;1438:23;1434:32;1431:52;;;1479:1;1476;1469:12;1431:52;1502:40;1532:9;1502:40;:::i;:::-;1586:2;1571:18;;1565:25;1492:50;;-1:-1:-1;;;;;;1639:14:1;;;1636:34;;;1666:1;1663;1656:12;1636:34;1689:72;1753:7;1744:6;1733:9;1729:22;1689:72;:::i;:::-;1679:82;;1807:2;1796:9;1792:18;1786:25;1770:41;;1836:2;1826:8;1823:16;1820:36;;;1852:1;1849;1842:12;1820:36;;1875:74;1941:7;1930:8;1919:9;1915:24;1875:74;:::i;:::-;1865:84;;;1256:699;;;;;:::o;:::-;11163:3833:0;;;;;;","srcMapRuntime":"11163:3833:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13715:205;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;11376:37;;;;;;;;;;-1:-1:-1;11376:37:0;;;;;;;;;;;1618:42:1;1606:55;;;1588:74;;1576:2;1561:18;11376:37:0;1415:253:1;13422:137:0;;;;;;;;;;-1:-1:-1;13506:46:0;;13422:137;;;1819:25:1;;;1807:2;1792:18;13422:137:0;1673:177:1;13148:127:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;13565:144::-;;;;;;;;;;-1:-1:-1;13565:144:0;;;;;:::i;:::-;;:::i;14839:155::-;;;;;;:::i;:::-;;:::i;:::-;;12818:130;;;;;;;;;;-1:-1:-1;12818:130:0;;;;;:::i;:::-;12906:35;;12880:7;12906:35;;;:14;:35;;;;;;;;;12818:130;11923:840;;;;;;;;;;-1:-1:-1;11923:840:0;;;;;:::i;:::-;;:::i;14275:507::-;;;;;;:::i;:::-;;:::i;13019:123::-;;;;;;;;;;;;;:::i;13281:135::-;;;;;;;;;;-1:-1:-1;13362:29:0;:47;13281:135;;13715:205;13818:61;;;;;;;;;13849:29;13818:61;;;;;;;;;13768:12;;;;13818:61;;:30;:61::i;:::-;13881:31;13810:103;;;;;;;;;;;;;;;;;;;;13881:31;;13810:103;;13881:31;13810:103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13715:205;;:::o;13148:127::-;13202:16;13237:14;:31;;13230:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13148:127;:::o;13565:144::-;13653:16;13688:14;13681:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13565:144;;;;;:::o;14839:155::-;14968:19;;;;;;;14839:155;;;;;:::o;11923:840::-;12295:11;:18;12276:8;:15;:37;12268:84;;;;;;;8144:2:1;12268:84:0;;;8126:21:1;8183:2;8163:18;;;8156:30;8222:34;8202:18;;;8195:62;8293:4;8273:18;;;8266:32;8315:19;;12268:84:0;;;;;;;;12368:9;12363:127;12387:8;:15;12383:1;:19;12363:127;;;12465:11;12477:1;12465:14;;;;;;;;:::i;:::-;;;;;;;12423;:26;;:39;12450:8;12459:1;12450:11;;;;;;;;:::i;:::-;;;;;;;12423:39;;;;;;;;;;;;;;;;:56;;;;;;;;;;;;;;;;;;12404:3;;;;;:::i;:::-;;;;12363:127;;;-1:-1:-1;12544:93:0;;;;;;;;;;;;;;;;;;;;;;12500:29;:137;;;;;12648:47;;;;:29;;:47;;;;;:::i;:::-;-1:-1:-1;12705:51:0;;;;:31;;:51;;;;;:::i;:::-;;11923:840;;;;;;:::o;14275:507::-;14378:20;14401:39;:21;;;;;;;;14411:7;14401:21;;;;14420:1;14401:21;;;:37;:39::i;:::-;14596:10;;;:148;;;;;14378:62;;-1:-1:-1;14596:10:0;;;:25;;14629:9;;14596:148;;14653:10;;14665:8;;14596:10;14687:29;;14378:62;;14727:7;;;;14596:148;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;14759:16:0;;;;;;;14368:414;14275:507;;;;:::o;13019:123::-;13071:16;13106:14;:29;;13099:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13019:123;:::o;7676:180::-;7756:12;7787:62;6696:1;7838:9;7827:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;6979:12;7021:7;7030:9;7010:30;;;;;;;;;:::i;:::-;;;;;;;;;;;;;7003:37;;6883:164;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:481:1;55:3;93:5;87:12;120:6;115:3;108:19;145:1;155:162;169:6;166:1;163:13;155:162;;;231:4;287:13;;;283:22;;277:29;259:11;;;255:20;;248:59;184:12;155:162;;;159:3;362:1;355:4;346:6;341:3;337:16;333:27;326:38;484:4;414:66;409:2;401:6;397:15;393:88;388:3;384:98;380:109;373:116;;;14:481;;;;:::o;500:484::-;553:3;591:5;585:12;618:6;613:3;606:19;644:4;673:2;668:3;664:12;657:19;;710:2;703:5;699:14;731:1;741:218;755:6;752:1;749:13;741:218;;;820:13;;835:42;816:62;804:75;;899:12;;;;934:15;;;;777:1;770:9;741:218;;;-1:-1:-1;975:3:1;;500:484;-1:-1:-1;;;;;500:484:1:o;989:421::-;1214:2;1203:9;1196:21;1177:4;1240:44;1280:2;1269:9;1265:18;1257:6;1240:44;:::i;:::-;1332:9;1324:6;1320:22;1315:2;1304:9;1300:18;1293:50;1360:44;1397:6;1389;1360:44;:::i;:::-;1352:52;989:421;-1:-1:-1;;;;;989:421:1:o;1855:261::-;2034:2;2023:9;2016:21;1997:4;2054:56;2106:2;2095:9;2091:18;2083:6;2054:56;:::i;:::-;2046:64;1855:261;-1:-1:-1;;;1855:261:1:o;2121:248::-;2189:6;2197;2250:2;2238:9;2229:7;2225:23;2221:32;2218:52;;;2266:1;2263;2256:12;2218:52;-1:-1:-1;;2289:23:1;;;2359:2;2344:18;;;2331:32;;-1:-1:-1;2121:248:1:o;2374:347::-;2425:8;2435:6;2489:3;2482:4;2474:6;2470:17;2466:27;2456:55;;2507:1;2504;2497:12;2456:55;-1:-1:-1;2530:20:1;;2573:18;2562:30;;2559:50;;;2605:1;2602;2595:12;2559:50;2642:4;2634:6;2630:17;2618:29;;2694:3;2687:4;2678:6;2670;2666:19;2662:30;2659:39;2656:59;;;2711:1;2708;2701:12;2656:59;2374:347;;;;;:::o;2726:614::-;2823:6;2831;2839;2847;2855;2908:3;2896:9;2887:7;2883:23;2879:33;2876:53;;;2925:1;2922;2915:12;2876:53;2961:9;2948:23;2938:33;;3018:2;3007:9;3003:18;2990:32;2980:42;;3069:2;3058:9;3054:18;3041:32;3031:42;;3124:2;3113:9;3109:18;3096:32;3151:18;3143:6;3140:30;3137:50;;;3183:1;3180;3173:12;3137:50;3222:58;3272:7;3263:6;3252:9;3248:22;3222:58;:::i;:::-;2726:614;;;;-1:-1:-1;2726:614:1;;-1:-1:-1;3299:8:1;;3196:84;2726:614;-1:-1:-1;;;2726:614:1:o;3345:171::-;3412:20;;3472:18;3461:30;;3451:41;;3441:69;;3506:1;3503;3496:12;3441:69;3345:171;;;:::o;3521:184::-;3579:6;3632:2;3620:9;3611:7;3607:23;3603:32;3600:52;;;3648:1;3645;3638:12;3600:52;3671:28;3689:9;3671:28;:::i;3941:184::-;3993:77;3990:1;3983:88;4090:4;4087:1;4080:15;4114:4;4111:1;4104:15;4130:334;4201:2;4195:9;4257:2;4247:13;;4262:66;4243:86;4231:99;;4360:18;4345:34;;4381:22;;;4342:62;4339:88;;;4407:18;;:::i;:::-;4443:2;4436:22;4130:334;;-1:-1:-1;4130:334:1:o;4469:182::-;4528:4;4561:18;4553:6;4550:30;4547:56;;;4583:18;;:::i;:::-;-1:-1:-1;4628:1:1;4624:14;4640:4;4620:25;;4469:182::o;4656:665::-;4709:5;4762:3;4755:4;4747:6;4743:17;4739:27;4729:55;;4780:1;4777;4770:12;4729:55;4816:6;4803:20;4842:4;4866:59;4882:42;4921:2;4882:42;:::i;:::-;4866:59;:::i;:::-;4959:15;;;5045:1;5041:10;;;;5029:23;;5025:32;;;4990:12;;;;5069:15;;;5066:35;;;5097:1;5094;5087:12;5066:35;5133:2;5125:6;5121:15;5145:147;5161:6;5156:3;5153:15;5145:147;;;5227:22;5245:3;5227:22;:::i;:::-;5215:35;;5270:12;;;;5178;;5145:147;;;-1:-1:-1;5310:5:1;4656:665;-1:-1:-1;;;;;;4656:665:1:o;5326:868::-;5380:5;5433:3;5426:4;5418:6;5414:17;5410:27;5400:55;;5451:1;5448;5441:12;5400:55;5487:6;5474:20;5513:4;5537:59;5553:42;5592:2;5553:42;:::i;5537:59::-;5630:15;;;5716:1;5712:10;;;;5700:23;;5696:32;;;5661:12;;;;5740:15;;;5737:35;;;5768:1;5765;5758:12;5737:35;5804:2;5796:6;5792:15;5816:349;5832:6;5827:3;5824:15;5816:349;;;5912:3;5899:17;5960:42;5953:5;5949:54;5942:5;5939:65;5929:163;;6046:1;6075:2;6071;6064:14;5929:163;6105:18;;6143:12;;;;5849;;5816:349;;6199:1188;6401:6;6409;6417;6425;6433;6441;6494:3;6482:9;6473:7;6469:23;6465:33;6462:53;;;6511:1;6508;6501:12;6462:53;6551:9;6538:23;6580:18;6621:2;6613:6;6610:14;6607:34;;;6637:1;6634;6627:12;6607:34;6660:60;6712:7;6703:6;6692:9;6688:22;6660:60;:::i;:::-;6650:70;;6773:2;6762:9;6758:18;6745:32;6729:48;;6802:2;6792:8;6789:16;6786:36;;;6818:1;6815;6808:12;6786:36;6841:63;6896:7;6885:8;6874:9;6870:24;6841:63;:::i;:::-;6831:73;;6957:2;6946:9;6942:18;6929:32;6913:48;;6986:2;6976:8;6973:16;6970:36;;;7002:1;6999;6992:12;6970:36;7025:63;7080:7;7069:8;7058:9;7054:24;7025:63;:::i;:::-;7015:73;;7141:2;7130:9;7126:18;7113:32;7097:48;;7170:2;7160:8;7157:16;7154:36;;;7186:1;7183;7176:12;7154:36;;7209:63;7264:7;7253:8;7242:9;7238:24;7209:63;:::i;:::-;7199:73;;;7319:3;7308:9;7304:19;7291:33;7281:43;;7343:38;7376:3;7365:9;7361:19;7343:38;:::i;:::-;7333:48;;6199:1188;;;;;;;;:::o;7392:545::-;7480:6;7488;7496;7504;7557:2;7545:9;7536:7;7532:23;7528:32;7525:52;;;7573:1;7570;7563:12;7525:52;7609:9;7596:23;7586:33;;7666:2;7655:9;7651:18;7638:32;7628:42;;7721:2;7710:9;7706:18;7693:32;7748:18;7740:6;7737:30;7734:50;;;7780:1;7777;7770:12;7734:50;7819:58;7869:7;7860:6;7849:9;7845:22;7819:58;:::i;:::-;7392:545;;;;-1:-1:-1;7896:8:1;-1:-1:-1;;;;7392:545:1:o;8345:184::-;8397:77;8394:1;8387:88;8494:4;8491:1;8484:15;8518:4;8515:1;8508:15;8534:349;8573:3;8604:66;8597:5;8594:77;8591:257;;8704:77;8701:1;8694:88;8805:4;8802:1;8795:15;8833:4;8830:1;8823:15;8591:257;-1:-1:-1;8875:1:1;8864:13;;8534:349::o;8888:325::-;8976:6;8971:3;8964:19;9028:6;9021:5;9014:4;9009:3;9005:14;8992:43;;9080:1;9073:4;9064:6;9059:3;9055:16;9051:27;9044:38;8946:3;9202:4;9132:66;9127:2;9119:6;9115:15;9111:88;9106:3;9102:98;9098:109;9091:116;;8888:325;;;;:::o;9218:1267::-;9543:4;9591:3;9580:9;9576:19;9622:6;9611:9;9604:25;9648:2;9686:6;9681:2;9670:9;9666:18;9659:34;9712:42;9802:2;9794:6;9790:15;9785:2;9774:9;9770:18;9763:43;9842:3;9837:2;9826:9;9822:18;9815:31;9866:6;9901;9895:13;9932:6;9924;9917:22;9970:3;9959:9;9955:19;9948:26;;9993:6;9990:1;9983:17;10036:2;10033:1;10023:16;10009:30;;10057:1;10067:177;10081:6;10078:1;10075:13;10067:177;;;10146:13;;10142:22;;10130:35;;10232:1;10220:14;;;;10185:12;;;;10096:9;10067:177;;;10071:3;;10290:9;10285:3;10281:19;10275:3;10264:9;10260:19;10253:48;10324:29;10349:3;10341:6;10324:29;:::i;:::-;10310:43;;;;;10402:9;10394:6;10390:22;10384:3;10373:9;10369:19;10362:51;10430:49;10472:6;10464;10456;10430:49;:::i;:::-;10422:57;9218:1267;-1:-1:-1;;;;;;;;;;9218:1267:1:o;10490:245::-;10569:6;10577;10630:2;10618:9;10609:7;10605:23;10601:32;10598:52;;;10646:1;10643;10636:12;10598:52;-1:-1:-1;;10669:16:1;;10725:2;10710:18;;;10704:25;10669:16;;10704:25;;-1:-1:-1;10490:245:1:o;10897:256::-;10817:12;;10805:25;;10879:4;10868:16;;;10862:23;10846:14;;;10839:47;11087:2;11072:18;;11099:48;10740:152;11415:295;11598:4;11590:6;11586:17;11575:9;11568:36;11640:2;11635;11624:9;11620:18;11613:30;11549:4;11660:44;11700:2;11689:9;11685:18;11677:6;11660:44;:::i;:::-;11652:52;11415:295;-1:-1:-1;;;;11415:295:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_interchain","type":"address"},{"internalType":"address[]","name":"_sendingModules","type":"address[]"},{"internalType":"address[]","name":"_receivingModules","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"AppMessageRecieve","type":"event"},{"anonymous":false,"inputs":[],"name":"AppMessageSent","type":"event"},{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"appReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainID","type":"uint64"}],"name":"getLinkedIApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOptimisticTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReceivingConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReceivingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRequiredResponses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint256","name":"dstChainId","type":"uint256"}],"name":"getSendingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSendingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interchain","outputs":[{"internalType":"contract IInterchainClientV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"chainIDs","type":"uint64[]"},{"internalType":"address[]","name":"linkedIApps","type":"address[]"},{"internalType":"address[]","name":"_sendingModules","type":"address[]"},{"internalType":"address[]","name":"_receivingModules","type":"address[]"},{"internalType":"uint256","name":"_requiredResponses","type":"uint256"},{"internalType":"uint64","name":"_optimisticTimePeriod","type":"uint64"}],"name":"setAppConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchain\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageRecieve\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainID\",\"type\":\"uint64\"}],\"name\":\"getLinkedIApp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOptimisticTimePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequiredResponses\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"}],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchain\",\"outputs\":[{\"internalType\":\"contract IInterchainClientV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"send\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainIDs\",\"type\":\"uint64[]\"},{\"internalType\":\"address[]\",\"name\":\"linkedIApps\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_requiredResponses\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_optimisticTimePeriod\",\"type\":\"uint64\"}],\"name\":\"setAppConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"InterchainApp\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0xcee8324dd3c75392a8c5dc86ef57f1b2347902be227511446576f37bc440d7b1\",\"urls\":[\"bzz-raw://5cb95195c4bbe4c8203791b87b20b95c6420594d1874d58cb002229c2d215a69\",\"dweb:/ipfs/QmfGPkVPJxAyDpDPHwx4gbdPgdhViLE96QohaZMdZNT9vh\"]}},\"version\":1}"},"hashes":{"appReceive(uint256,bytes32,uint256,bytes)":"b399470d","getLinkedIApp(uint64)":"bfc849ee","getOptimisticTimePeriod()":"7c9abd3e","getReceivingConfig()":"287bc057","getReceivingModules()":"a45e107a","getRequiredResponses()":"f31b19a9","getSendingModules()":"ea13398f","getSendingModules(bytes32,uint256)":"ab139613","interchain()":"70838975","send(bytes32,uint256,bytes)":"e1ef3b3f","setAppConfig(uint64[],address[],address[],address[],uint256,uint64)":"dd34f56a"}},"solidity/InterchainApp.sol:OptionsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b2c3de9937032edff8f1c18bb925e9494b1a02c2fd9043eafec8956a572995c964736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b2c3de9937032edff8f1c18bb925e9494b1a02c2fd9043eafec8956a572995c964736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, address(0), localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"9171:1958:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;9171:1958:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"9171:1958:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"OptionsLib__IncorrectVersion","type":"error"}],"userDoc":{"kind":"user","methods":{},"notice":"A library for encoding and decoding Interchain options related to interchain messages.","version":1},"developerDoc":{"kind":"dev","methods":{},"title":"OptionsLib","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"OptionsLib\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"A library for encoding and decoding Interchain options related to interchain messages.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"OptionsLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0xcee8324dd3c75392a8c5dc86ef57f1b2347902be227511446576f37bc440d7b1\",\"urls\":[\"bzz-raw://5cb95195c4bbe4c8203791b87b20b95c6420594d1874d58cb002229c2d215a69\",\"dweb:/ipfs/QmfGPkVPJxAyDpDPHwx4gbdPgdhViLE96QohaZMdZNT9vh\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file +{"solidity/InterchainApp.sol:AppConfigLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209f5affa708e3871fcbebed46226f189611882164b69517fcf6c6530ff05bbd4164736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209f5affa708e3871fcbebed46226f189611882164b69517fcf6c6530ff05bbd4164736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n address private executionService;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n address _executionService,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n executionService = _executionService;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"6580:2072:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;6580:2072:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"6580:2072:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"AppConfigLib__IncorrectVersion","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"AppConfigLib__IncorrectVersion\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"AppConfigLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0x97256ebb052f6f28fecf0beec3b1dfa66674bc1f309fa5ee1d848c8510a9efce\",\"urls\":[\"bzz-raw://4449ebe8a883f01fc9475e12203c0ba46d8546f96ac1296fa4eefe6a2b236127\",\"dweb:/ipfs/QmPW2zd3zqaAsMed1LSjVLafcE6zXNNiTwqEkHfbnRC69p\"]}},\"version\":1}"},"hashes":{}},"solidity/InterchainApp.sol:IInterchainApp":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n address private executionService;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n address _executionService,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n executionService = _executionService;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"appReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getReceivingConfig","outputs":[{"internalType":"bytes","name":"appConfig","type":"bytes"},{"internalType":"address[]","name":"modules","type":"address[]"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"notice":"Minimal interface for the Interchain App to work with the Interchain Client.","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"appConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"modules\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Minimal interface for the Interchain App to work with the Interchain Client.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"IInterchainApp\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0x97256ebb052f6f28fecf0beec3b1dfa66674bc1f309fa5ee1d848c8510a9efce\",\"urls\":[\"bzz-raw://4449ebe8a883f01fc9475e12203c0ba46d8546f96ac1296fa4eefe6a2b236127\",\"dweb:/ipfs/QmPW2zd3zqaAsMed1LSjVLafcE6zXNNiTwqEkHfbnRC69p\"]}},\"version\":1}"},"hashes":{"appReceive(uint256,bytes32,uint256,bytes)":"b399470d","getReceivingConfig()":"287bc057"}},"solidity/InterchainApp.sol:IInterchainClientV1":{"code":"0x","runtime-code":"0x","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n address private executionService;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n address _executionService,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n executionService = _executionService;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__FeeAmountTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"InterchainClientV1__IncorrectDstChainId","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__IncorrectMsgValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"InterchainClientV1__IncorrectSrcChainId","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InterchainClientV1__NotEnoughResponses","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxAlreadyExecuted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"InterchainClientV1__TxNotExecuted","type":"error"},{"inputs":[{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"getExecutor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"getExecutorById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"getInterchainFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"interchainExecute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSend","outputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcExecutionService","type":"address"},{"internalType":"address[]","name":"srcModules","type":"address[]"},{"internalType":"bytes","name":"options","type":"bytes"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"interchainSendEVM","outputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"transaction","type":"bytes"}],"name":"isExecutable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"executionFees_","type":"address"}],"name":"setExecutionFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes32","name":"client","type":"bytes32"}],"name":"setLinkedClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"writeExecutionProof","outputs":[{"internalType":"uint256","name":"dbNonce","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getExecutor(bytes)":{"notice":"Returns the address of the executor for a transaction that has been sent to the local chain."},"getExecutorById(bytes32)":{"notice":"Returns the address of the executor for a transaction that has been sent to the local chain."},"getInterchainFee(uint256,address,address[],bytes,bytes)":{"notice":"Returns the fee for sending an Interchain message."},"interchainExecute(uint256,bytes)":{"notice":"Executes a transaction that has been sent via the Interchain."},"interchainSend(uint256,bytes32,address,address[],bytes,bytes)":{"notice":"Sends a message to another chain via the Interchain Communication Protocol."},"isExecutable(bytes)":{"notice":"Checks if a transaction is executable."},"setExecutionFees(address)":{"notice":"Sets the address of the ExecutionFees contract."},"setLinkedClient(uint256,bytes32)":{"notice":"Sets the linked client for a specific chain ID."},"writeExecutionProof(bytes32)":{"notice":"Writes the proof of execution for a transaction into the InterchainDB."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getInterchainFee(uint256,address,address[],bytes,bytes)":{"params":{"dstChainId":"The chain ID of the destination chain.","message":"The message being sent.","options":"Execution options for the message sent, currently gas limit + native gas drop.","srcExecutionService":"The address of the execution service to use for the message.","srcModules":"The source modules involved in the message sending."}},"interchainExecute(uint256,bytes)":{"details":"The transaction must have been previously sent and recorded. Transaction data includes the requested gas limit, but the executors could specify a different gas limit. If the specified gas limit is lower than requested, the requested gas limit will be used. Otherwise, the specified gas limit will be used. This allows to execute the transactions with requested gas limit set too low.","params":{"gasLimit":"The gas limit to use for the execution.","transaction":"The transaction data."}},"interchainSend(uint256,bytes32,address,address[],bytes,bytes)":{"details":"Charges a fee for the message, which is payable upon calling this function: - Verification fees: paid to every module that verifies the message. - Execution fee: paid to the executor that executes the message. Note: while a specific execution service is specified to request the execution of the message, any executor is able to execute the message on destination chain, earning the execution fee.","params":{"dstChainId":"The chain ID of the destination chain.","message":"The message being sent.","options":"Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.","receiver":"The address of the receiver on the destination chain.","srcExecutionService":"The address of the execution service to use for the message.","srcModules":"The source modules involved in the message sending."},"returns":{"dbNonce":"The database nonce of the written entry for the transaction.","transactionId":"The ID of the transaction that was sent."}},"isExecutable(bytes)":{"details":"Determines if a transaction meets the criteria to be executed based on: - If approved modules have written to the InterchainDB - If the threshold of approved modules have been met - If the optimistic window has passed for all modules","params":{"transaction":"The InterchainTransaction struct to be checked."},"returns":{"_0":"bool Returns true if the transaction is executable, false otherwise."}},"setExecutionFees(address)":{"details":"Only callable by the contract owner or an authorized account.","params":{"executionFees_":"The address of the ExecutionFees contract."}},"setLinkedClient(uint256,bytes32)":{"details":"Stores the address of the linked client in a mapping with the chain ID as the key.","params":{"chainId":"The chain ID for which the client is being set.","client":"The address of the client being linked."}},"writeExecutionProof(bytes32)":{"details":"Will revert if the transaction has not been executed.","params":{"transactionId":"The ID of the transaction to write the proof for."},"returns":{"dbNonce":" The database nonce of the written entry for the proof."}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__FeeAmountTooLow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectDstChainId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__IncorrectSrcChainId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"InterchainClientV1__NotEnoughResponses\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"InterchainClientV1__TxAlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"InterchainClientV1__TxNotExecuted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"getExecutor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"getExecutorById\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"getInterchainFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"interchainExecute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"interchainSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"srcExecutionService\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"srcModules\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"options\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"interchainSendEVM\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transaction\",\"type\":\"bytes\"}],\"name\":\"isExecutable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"executionFees_\",\"type\":\"address\"}],\"name\":\"setExecutionFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"client\",\"type\":\"bytes32\"}],\"name\":\"setLinkedClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"writeExecutionProof\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getInterchainFee(uint256,address,address[],bytes,bytes)\":{\"params\":{\"dstChainId\":\"The chain ID of the destination chain.\",\"message\":\"The message being sent.\",\"options\":\"Execution options for the message sent, currently gas limit + native gas drop.\",\"srcExecutionService\":\"The address of the execution service to use for the message.\",\"srcModules\":\"The source modules involved in the message sending.\"}},\"interchainExecute(uint256,bytes)\":{\"details\":\"The transaction must have been previously sent and recorded. Transaction data includes the requested gas limit, but the executors could specify a different gas limit. If the specified gas limit is lower than requested, the requested gas limit will be used. Otherwise, the specified gas limit will be used. This allows to execute the transactions with requested gas limit set too low.\",\"params\":{\"gasLimit\":\"The gas limit to use for the execution.\",\"transaction\":\"The transaction data.\"}},\"interchainSend(uint256,bytes32,address,address[],bytes,bytes)\":{\"details\":\"Charges a fee for the message, which is payable upon calling this function: - Verification fees: paid to every module that verifies the message. - Execution fee: paid to the executor that executes the message. Note: while a specific execution service is specified to request the execution of the message, any executor is able to execute the message on destination chain, earning the execution fee.\",\"params\":{\"dstChainId\":\"The chain ID of the destination chain.\",\"message\":\"The message being sent.\",\"options\":\"Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\",\"receiver\":\"The address of the receiver on the destination chain.\",\"srcExecutionService\":\"The address of the execution service to use for the message.\",\"srcModules\":\"The source modules involved in the message sending.\"},\"returns\":{\"dbNonce\":\"The database nonce of the written entry for the transaction.\",\"transactionId\":\"The ID of the transaction that was sent.\"}},\"isExecutable(bytes)\":{\"details\":\"Determines if a transaction meets the criteria to be executed based on: - If approved modules have written to the InterchainDB - If the threshold of approved modules have been met - If the optimistic window has passed for all modules\",\"params\":{\"transaction\":\"The InterchainTransaction struct to be checked.\"},\"returns\":{\"_0\":\"bool Returns true if the transaction is executable, false otherwise.\"}},\"setExecutionFees(address)\":{\"details\":\"Only callable by the contract owner or an authorized account.\",\"params\":{\"executionFees_\":\"The address of the ExecutionFees contract.\"}},\"setLinkedClient(uint256,bytes32)\":{\"details\":\"Stores the address of the linked client in a mapping with the chain ID as the key.\",\"params\":{\"chainId\":\"The chain ID for which the client is being set.\",\"client\":\"The address of the client being linked.\"}},\"writeExecutionProof(bytes32)\":{\"details\":\"Will revert if the transaction has not been executed.\",\"params\":{\"transactionId\":\"The ID of the transaction to write the proof for.\"},\"returns\":{\"dbNonce\":\" The database nonce of the written entry for the proof.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getExecutor(bytes)\":{\"notice\":\"Returns the address of the executor for a transaction that has been sent to the local chain.\"},\"getExecutorById(bytes32)\":{\"notice\":\"Returns the address of the executor for a transaction that has been sent to the local chain.\"},\"getInterchainFee(uint256,address,address[],bytes,bytes)\":{\"notice\":\"Returns the fee for sending an Interchain message.\"},\"interchainExecute(uint256,bytes)\":{\"notice\":\"Executes a transaction that has been sent via the Interchain.\"},\"interchainSend(uint256,bytes32,address,address[],bytes,bytes)\":{\"notice\":\"Sends a message to another chain via the Interchain Communication Protocol.\"},\"isExecutable(bytes)\":{\"notice\":\"Checks if a transaction is executable.\"},\"setExecutionFees(address)\":{\"notice\":\"Sets the address of the ExecutionFees contract.\"},\"setLinkedClient(uint256,bytes32)\":{\"notice\":\"Sets the linked client for a specific chain ID.\"},\"writeExecutionProof(bytes32)\":{\"notice\":\"Writes the proof of execution for a transaction into the InterchainDB.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"IInterchainClientV1\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0x97256ebb052f6f28fecf0beec3b1dfa66674bc1f309fa5ee1d848c8510a9efce\",\"urls\":[\"bzz-raw://4449ebe8a883f01fc9475e12203c0ba46d8546f96ac1296fa4eefe6a2b236127\",\"dweb:/ipfs/QmPW2zd3zqaAsMed1LSjVLafcE6zXNNiTwqEkHfbnRC69p\"]}},\"version\":1}"},"hashes":{"getExecutor(bytes)":"f92a79ff","getExecutorById(bytes32)":"f1a61fac","getInterchainFee(uint256,address,address[],bytes,bytes)":"3c383e7b","interchainExecute(uint256,bytes)":"80efe777","interchainSend(uint256,bytes32,address,address[],bytes,bytes)":"98939d28","interchainSendEVM(uint256,address,address,address[],bytes,bytes)":"827f940d","isExecutable(bytes)":"31afa7de","setExecutionFees(address)":"3dc68b87","setLinkedClient(uint256,bytes32)":"f34234c8","writeExecutionProof(bytes32)":"90e81077"}},"solidity/InterchainApp.sol:InterchainApp":{"code":"0x60806040523480156200001157600080fd5b50604051620011a2380380620011a28339810160408190526200003491620001e5565b600080546001600160a01b0319166001600160a01b03851617905581516200006490600590602085019062000084565b5080516200007a90600690602084019062000084565b5050505062000262565b828054828255906000526020600020908101928215620000dc579160200282015b82811115620000dc57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620000a5565b50620000ea929150620000ee565b5090565b5b80821115620000ea5760008155600101620000ef565b80516001600160a01b03811681146200011d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014a57600080fd5b815160206001600160401b038083111562000169576200016962000122565b8260051b604051601f19603f8301168101818110848211171562000191576200019162000122565b604052938452858101830193838101925087851115620001b057600080fd5b83870191505b84821015620001da57620001ca8262000105565b83529183019190830190620001b6565b979650505050505050565b600080600060608486031215620001fb57600080fd5b620002068462000105565b60208501519093506001600160401b03808211156200022457600080fd5b620002328783880162000138565b935060408601519150808211156200024957600080fd5b50620002588682870162000138565b9150509250925092565b610f3080620002726000396000f3fe6080604052600436106100bc5760003560e01c8063ab13961311610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063ab139613146101a2578063b399470d146101c2578063bfc849ee146101d557600080fd5b806370838975116100a5578063708389751461010f5780637c9abd3e14610161578063a45e107a1461018057600080fd5b8063287bc057146100c1578063645d575a146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e492919061090e565b60405180910390f35b3480156100f957600080fd5b5061010d610108366004610af3565b6102f3565b005b34801561011b57600080fd5b5060005461013c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561016d57600080fd5b506008545b6040519081526020016100e4565b34801561018c57600080fd5b506101956104e0565b6040516100e49190610bcb565b3480156101ae57600080fd5b506101956101bd366004610be5565b610552565b61010d6101d0366004610c50565b6105c5565b3480156101e157600080fd5b5061013c6101f0366004610cb1565b67ffffffffffffffff1660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61010d610230366004610ccc565b6105f5565b34801561024157600080fd5b506101956106f7565b34801561025657600080fd5b50600754610172565b6040805180820190915260075481526008546020820152606090819061028490610767565b60068054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b8551875114610388576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8751811015610442578681815181106103a6576103a6610d1f565b6020026020010151600460000160008a84815181106103c7576103c7610d1f565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061043a90610d4e565b91505061038b565b506040805180820190915282815267ffffffffffffffff821660209182018190526007849055600855855161047d91600591908801906107ba565b5083516104919060069060208701906107ba565b5050600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff93909316929092179091555050505050565b6060600460020180548060200260200160405190810160405280929190818152602001828054801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b6000610618604051806040016040528062030d4081526020016000815250610767565b6000546003546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff918216926398939d28923492610683928a928c92169060059089908c908c90600401610df6565b604080518083038185885af11580156106a0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106c59190610e9b565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b606060046001018054806020026020016040519081016040528092919081815260200182805480156105485760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575050505050905090565b60606105bf60018360405160200161077f9190610ebf565b604051602081830303815290604052606082826040516020016107a3929190610ed6565b604051602081830303815290604052905092915050565b828054828255906000526020600020908101928215610834579160200282015b8281111561083457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906107da565b50610840929150610844565b5090565b5b808211156108405760008155600101610845565b6000815180845260005b8181101561087f57602081850181015186830182015201610863565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b8381101561090357815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016108d1565b509495945050505050565b6040815260006109216040830185610859565b828103602084015261093381856108bd565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b2576109b261093c565b604052919050565b600067ffffffffffffffff8211156109d4576109d461093c565b5060051b60200190565b803567ffffffffffffffff811681146109f657600080fd5b919050565b600082601f830112610a0c57600080fd5b81356020610a21610a1c836109ba565b61096b565b82815260059290921b84018101918181019086841115610a4057600080fd5b8286015b84811015610a6257610a55816109de565b8352918301918301610a44565b509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109f657600080fd5b600082601f830112610aa257600080fd5b81356020610ab2610a1c836109ba565b82815260059290921b84018101918181019086841115610ad157600080fd5b8286015b84811015610a6257610ae681610a6d565b8352918301918301610ad5565b600080600080600080600060e0888a031215610b0e57600080fd5b873567ffffffffffffffff80821115610b2657600080fd5b610b328b838c016109fb565b985060208a0135915080821115610b4857600080fd5b610b548b838c01610a91565b975060408a0135915080821115610b6a57600080fd5b610b768b838c01610a91565b965060608a0135915080821115610b8c57600080fd5b50610b998a828b01610a91565b945050610ba860808901610a6d565b925060a08801359150610bbd60c089016109de565b905092959891949750929550565b602081526000610bde60208301846108bd565b9392505050565b60008060408385031215610bf857600080fd5b50508035926020909101359150565b60008083601f840112610c1957600080fd5b50813567ffffffffffffffff811115610c3157600080fd5b602083019150836020828501011115610c4957600080fd5b9250929050565b600080600080600060808688031215610c6857600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115610c9457600080fd5b610ca088828901610c07565b969995985093965092949392505050565b600060208284031215610cc357600080fd5b610bde826109de565b60008060008060608587031215610ce257600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610d0757600080fd5b610d1387828801610c07565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610da6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610e61578554841683526001958601959285019201610e43565b50508581036080870152610e75818a610859565b935050505082810360a0840152610e8d818587610dad565b9a9950505050505050505050565b60008060408385031215610eae57600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016105bf565b60ff83168152604060208201526000610ef26040830184610859565b94935050505056fea2646970667358221220bfadb7a9cdcc8fe0a3a66c71b90675cf2087b9d292f5be92afcaa877f03bee4264736f6c63430008140033","runtime-code":"0x6080604052600436106100bc5760003560e01c8063ab13961311610074578063e1ef3b3f1161004e578063e1ef3b3f14610222578063ea13398f14610235578063f31b19a91461024a57600080fd5b8063ab139613146101a2578063b399470d146101c2578063bfc849ee146101d557600080fd5b806370838975116100a5578063708389751461010f5780637c9abd3e14610161578063a45e107a1461018057600080fd5b8063287bc057146100c1578063645d575a146100ed575b600080fd5b3480156100cd57600080fd5b506100d661025f565b6040516100e492919061090e565b60405180910390f35b3480156100f957600080fd5b5061010d610108366004610af3565b6102f3565b005b34801561011b57600080fd5b5060005461013c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e4565b34801561016d57600080fd5b506008545b6040519081526020016100e4565b34801561018c57600080fd5b506101956104e0565b6040516100e49190610bcb565b3480156101ae57600080fd5b506101956101bd366004610be5565b610552565b61010d6101d0366004610c50565b6105c5565b3480156101e157600080fd5b5061013c6101f0366004610cb1565b67ffffffffffffffff1660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61010d610230366004610ccc565b6105f5565b34801561024157600080fd5b506101956106f7565b34801561025657600080fd5b50600754610172565b6040805180820190915260075481526008546020820152606090819061028490610767565b60068054604080516020808402820181019092528281529183918301828280156102e457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102b9575b50505050509050915091509091565b8551875114610388576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f436861696e49447320616e64204941707073206c656e677468206d69736d617460448201527f6368000000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b60005b8751811015610442578681815181106103a6576103a6610d1f565b6020026020010151600460000160008a84815181106103c7576103c7610d1f565b602002602001015167ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808061043a90610d4e565b91505061038b565b506040805180820190915282815267ffffffffffffffff821660209182018190526007849055600855855161047d91600591908801906107ba565b5083516104919060069060208701906107ba565b5050600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff93909316929092179091555050505050565b6060600460020180548060200260200160405190810160405280929190818152602001828054801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b5050505050905090565b606060018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b505050505090505b92915050565b6040517f847042eccd302ccad5013142e14e1f299a4527dba6be2e3b3e41e7e4b4b0ac8b90600090a15050505050565b6000610618604051806040016040528062030d4081526020016000815250610767565b6000546003546040517f98939d2800000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff918216926398939d28923492610683928a928c92169060059089908c908c90600401610df6565b604080518083038185885af11580156106a0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106c59190610e9b565b50506040517f943237a3fcaf9fd505830acf03c74d7f672b1b7501aa0f1a79eb0170c553bd4f90600090a15050505050565b606060046001018054806020026020016040519081016040528092919081815260200182805480156105485760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575050505050905090565b60606105bf60018360405160200161077f9190610ebf565b604051602081830303815290604052606082826040516020016107a3929190610ed6565b604051602081830303815290604052905092915050565b828054828255906000526020600020908101928215610834579160200282015b8281111561083457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906107da565b50610840929150610844565b5090565b5b808211156108405760008155600101610845565b6000815180845260005b8181101561087f57602081850181015186830182015201610863565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600081518084526020808501945080840160005b8381101561090357815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016108d1565b509495945050505050565b6040815260006109216040830185610859565b828103602084015261093381856108bd565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156109b2576109b261093c565b604052919050565b600067ffffffffffffffff8211156109d4576109d461093c565b5060051b60200190565b803567ffffffffffffffff811681146109f657600080fd5b919050565b600082601f830112610a0c57600080fd5b81356020610a21610a1c836109ba565b61096b565b82815260059290921b84018101918181019086841115610a4057600080fd5b8286015b84811015610a6257610a55816109de565b8352918301918301610a44565b509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109f657600080fd5b600082601f830112610aa257600080fd5b81356020610ab2610a1c836109ba565b82815260059290921b84018101918181019086841115610ad157600080fd5b8286015b84811015610a6257610ae681610a6d565b8352918301918301610ad5565b600080600080600080600060e0888a031215610b0e57600080fd5b873567ffffffffffffffff80821115610b2657600080fd5b610b328b838c016109fb565b985060208a0135915080821115610b4857600080fd5b610b548b838c01610a91565b975060408a0135915080821115610b6a57600080fd5b610b768b838c01610a91565b965060608a0135915080821115610b8c57600080fd5b50610b998a828b01610a91565b945050610ba860808901610a6d565b925060a08801359150610bbd60c089016109de565b905092959891949750929550565b602081526000610bde60208301846108bd565b9392505050565b60008060408385031215610bf857600080fd5b50508035926020909101359150565b60008083601f840112610c1957600080fd5b50813567ffffffffffffffff811115610c3157600080fd5b602083019150836020828501011115610c4957600080fd5b9250929050565b600080600080600060808688031215610c6857600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115610c9457600080fd5b610ca088828901610c07565b969995985093965092949392505050565b600060208284031215610cc357600080fd5b610bde826109de565b60008060008060608587031215610ce257600080fd5b8435935060208501359250604085013567ffffffffffffffff811115610d0757600080fd5b610d1387828801610c07565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610da6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600060c082018983526020898185015273ffffffffffffffffffffffffffffffffffffffff808a16604086015260c0606086015282895480855260e0870191508a60005283600020945060005b81811015610e61578554841683526001958601959285019201610e43565b50508581036080870152610e75818a610859565b935050505082810360a0840152610e8d818587610dad565b9a9950505050505050505050565b60008060408385031215610eae57600080fd5b505080516020909101519092909150565b8151815260208083015190820152604081016105bf565b60ff83168152604060208201526000610ef26040830184610859565b94935050505056fea2646970667358221220bfadb7a9cdcc8fe0a3a66c71b90675cf2087b9d292f5be92afcaa877f03bee4264736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n address private executionService;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n address _executionService,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n executionService = _executionService;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"11163:3958:0:-:0;;;14045:283;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14158:10;:45;;-1:-1:-1;;;;;;14158:45:0;-1:-1:-1;;;;;14158:45:0;;;;;14213:47;;;;:29;;:47;;;;;:::i;:::-;-1:-1:-1;14270:51:0;;;;:31;;:51;;;;;:::i;:::-;;14045:283;;;11163:3958;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;11163:3958:0;-1:-1:-1;;;;;11163:3958:0;;;;;;;;;;;-1:-1:-1;11163:3958:0;;;;;;;-1:-1:-1;11163:3958:0;;;-1:-1:-1;11163:3958:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:177:1;93:13;;-1:-1:-1;;;;;135:31:1;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:127::-;257:10;252:3;248:20;245:1;238:31;288:4;285:1;278:15;312:4;309:1;302:15;328:923;393:5;446:3;439:4;431:6;427:17;423:27;413:55;;464:1;461;454:12;413:55;487:13;;519:4;-1:-1:-1;;;;;572:10:1;;;569:36;;;585:18;;:::i;:::-;631:2;628:1;624:10;663:2;657:9;726:2;722:7;717:2;713;709:11;705:25;697:6;693:38;781:6;769:10;766:22;761:2;749:10;746:18;743:46;740:72;;;792:18;;:::i;:::-;828:2;821:22;878:18;;;954:15;;;950:24;;;912:15;;;;-1:-1:-1;986:15:1;;;983:35;;;1014:1;1011;1004:12;983:35;1050:2;1042:6;1038:15;1027:26;;1062:159;1078:6;1073:3;1070:15;1062:159;;;1144:34;1174:3;1144:34;:::i;:::-;1132:47;;1199:12;;;;1095;;;;1062:159;;;1239:6;328:923;-1:-1:-1;;;;;;;328:923:1:o;1256:699::-;1394:6;1402;1410;1463:2;1451:9;1442:7;1438:23;1434:32;1431:52;;;1479:1;1476;1469:12;1431:52;1502:40;1532:9;1502:40;:::i;:::-;1586:2;1571:18;;1565:25;1492:50;;-1:-1:-1;;;;;;1639:14:1;;;1636:34;;;1666:1;1663;1656:12;1636:34;1689:72;1753:7;1744:6;1733:9;1729:22;1689:72;:::i;:::-;1679:82;;1807:2;1796:9;1792:18;1786:25;1770:41;;1836:2;1826:8;1823:16;1820:36;;;1852:1;1849;1842:12;1820:36;;1875:74;1941:7;1930:8;1919:9;1915:24;1875:74;:::i;:::-;1865:84;;;1256:699;;;;;:::o;:::-;11163:3958:0;;;;;;","srcMapRuntime":"11163:3958:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13834:205;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;11961:921;;;;;;;;;;-1:-1:-1;11961:921:0;;;;;:::i;:::-;;:::i;:::-;;11376:37;;;;;;;;;;-1:-1:-1;11376:37:0;;;;;;;;;;;5320:42:1;5308:55;;;5290:74;;5278:2;5263:18;11376:37:0;5117:253:1;13541:137:0;;;;;;;;;;-1:-1:-1;13625:46:0;;13541:137;;;5521:25:1;;;5509:2;5494:18;13541:137:0;5375:177:1;13267:127:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;13684:144::-;;;;;;;;;;-1:-1:-1;13684:144:0;;;;;:::i;:::-;;:::i;14964:155::-;;;;;;:::i;:::-;;:::i;12937:130::-;;;;;;;;;;-1:-1:-1;12937:130:0;;;;;:::i;:::-;13025:35;;12999:7;13025:35;;;:14;:35;;;;;;;;;12937:130;14394:513;;;;;;:::i;:::-;;:::i;13138:123::-;;;;;;;;;;;;;:::i;13400:135::-;;;;;;;;;;-1:-1:-1;13481:29:0;:47;13400:135;;13834:205;13937:61;;;;;;;;;13968:29;13937:61;;;;;;;;;13887:12;;;;13937:61;;:30;:61::i;:::-;14000:31;13929:103;;;;;;;;;;;;;;;;;;;;14000:31;;13929:103;;14000:31;13929:103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13834:205;;:::o;11961:921::-;12368:11;:18;12349:8;:15;:37;12341:84;;;;;;;8219:2:1;12341:84:0;;;8201:21:1;8258:2;8238:18;;;8231:30;8297:34;8277:18;;;8270:62;8368:4;8348:18;;;8341:32;8390:19;;12341:84:0;;;;;;;;12441:9;12436:127;12460:8;:15;12456:1;:19;12436:127;;;12538:11;12550:1;12538:14;;;;;;;;:::i;:::-;;;;;;;12496;:26;;:39;12523:8;12532:1;12523:11;;;;;;;;:::i;:::-;;;;;;;12496:39;;;;;;;;;;;;;;;;:56;;;;;;;;;;;;;;;;;;12477:3;;;;;:::i;:::-;;;;12436:127;;;-1:-1:-1;12617:93:0;;;;;;;;;;;;;;;;;;;;;;12573:29;:137;;;;;12721:47;;;;:29;;:47;;;;;:::i;:::-;-1:-1:-1;12778:51:0;;;;:31;;:51;;;;;:::i;:::-;-1:-1:-1;;12839:16:0;:36;;;;;;;;;;;;;;;;-1:-1:-1;;;;;11961:921:0:o;13267:127::-;13321:16;13356:14;:31;;13349:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13267:127;:::o;13684:144::-;13772:16;13807:14;13800:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13684:144;;;;;:::o;14964:155::-;15093:19;;;;;;;14964:155;;;;;:::o;14394:513::-;14497:20;14520:39;:21;;;;;;;;14530:7;14520:21;;;;14539:1;14520:21;;;:37;:39::i;:::-;14715:10;;14794:16;;14715:154;;;;;14497:62;;-1:-1:-1;14715:10:0;;;;;:25;;14748:9;;14715:154;;14772:10;;14784:8;;14794:16;;14812:29;;14497:62;;14852:7;;;;14812:14;14715:154;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;14884:16:0;;;;;;;14487:420;14394:513;;;;:::o;13138:123::-;13190:16;13225:14;:29;;13218:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13138:123;:::o;7676:180::-;7756:12;7787:62;6696:1;7838:9;7827:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;6979:12;7021:7;7030:9;7010:30;;;;;;;;;:::i;:::-;;;;;;;;;;;;;7003:37;;6883:164;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:481:1;55:3;93:5;87:12;120:6;115:3;108:19;145:1;155:162;169:6;166:1;163:13;155:162;;;231:4;287:13;;;283:22;;277:29;259:11;;;255:20;;248:59;184:12;155:162;;;159:3;362:1;355:4;346:6;341:3;337:16;333:27;326:38;484:4;414:66;409:2;401:6;397:15;393:88;388:3;384:98;380:109;373:116;;;14:481;;;;:::o;500:484::-;553:3;591:5;585:12;618:6;613:3;606:19;644:4;673:2;668:3;664:12;657:19;;710:2;703:5;699:14;731:1;741:218;755:6;752:1;749:13;741:218;;;820:13;;835:42;816:62;804:75;;899:12;;;;934:15;;;;777:1;770:9;741:218;;;-1:-1:-1;975:3:1;;500:484;-1:-1:-1;;;;;500:484:1:o;989:421::-;1214:2;1203:9;1196:21;1177:4;1240:44;1280:2;1269:9;1265:18;1257:6;1240:44;:::i;:::-;1332:9;1324:6;1320:22;1315:2;1304:9;1300:18;1293:50;1360:44;1397:6;1389;1360:44;:::i;:::-;1352:52;989:421;-1:-1:-1;;;;;989:421:1:o;1415:184::-;1467:77;1464:1;1457:88;1564:4;1561:1;1554:15;1588:4;1585:1;1578:15;1604:334;1675:2;1669:9;1731:2;1721:13;;1736:66;1717:86;1705:99;;1834:18;1819:34;;1855:22;;;1816:62;1813:88;;;1881:18;;:::i;:::-;1917:2;1910:22;1604:334;;-1:-1:-1;1604:334:1:o;1943:182::-;2002:4;2035:18;2027:6;2024:30;2021:56;;;2057:18;;:::i;:::-;-1:-1:-1;2102:1:1;2098:14;2114:4;2094:25;;1943:182::o;2130:171::-;2197:20;;2257:18;2246:30;;2236:41;;2226:69;;2291:1;2288;2281:12;2226:69;2130:171;;;:::o;2306:665::-;2359:5;2412:3;2405:4;2397:6;2393:17;2389:27;2379:55;;2430:1;2427;2420:12;2379:55;2466:6;2453:20;2492:4;2516:59;2532:42;2571:2;2532:42;:::i;:::-;2516:59;:::i;:::-;2609:15;;;2695:1;2691:10;;;;2679:23;;2675:32;;;2640:12;;;;2719:15;;;2716:35;;;2747:1;2744;2737:12;2716:35;2783:2;2775:6;2771:15;2795:147;2811:6;2806:3;2803:15;2795:147;;;2877:22;2895:3;2877:22;:::i;:::-;2865:35;;2920:12;;;;2828;;2795:147;;;-1:-1:-1;2960:5:1;2306:665;-1:-1:-1;;;;;;2306:665:1:o;2976:196::-;3044:20;;3104:42;3093:54;;3083:65;;3073:93;;3162:1;3159;3152:12;3177:667;3231:5;3284:3;3277:4;3269:6;3265:17;3261:27;3251:55;;3302:1;3299;3292:12;3251:55;3338:6;3325:20;3364:4;3388:59;3404:42;3443:2;3404:42;:::i;3388:59::-;3481:15;;;3567:1;3563:10;;;;3551:23;;3547:32;;;3512:12;;;;3591:15;;;3588:35;;;3619:1;3616;3609:12;3588:35;3655:2;3647:6;3643:15;3667:148;3683:6;3678:3;3675:15;3667:148;;;3749:23;3768:3;3749:23;:::i;:::-;3737:36;;3793:12;;;;3700;;3667:148;;3849:1263;4060:6;4068;4076;4084;4092;4100;4108;4161:3;4149:9;4140:7;4136:23;4132:33;4129:53;;;4178:1;4175;4168:12;4129:53;4218:9;4205:23;4247:18;4288:2;4280:6;4277:14;4274:34;;;4304:1;4301;4294:12;4274:34;4327:60;4379:7;4370:6;4359:9;4355:22;4327:60;:::i;:::-;4317:70;;4440:2;4429:9;4425:18;4412:32;4396:48;;4469:2;4459:8;4456:16;4453:36;;;4485:1;4482;4475:12;4453:36;4508:63;4563:7;4552:8;4541:9;4537:24;4508:63;:::i;:::-;4498:73;;4624:2;4613:9;4609:18;4596:32;4580:48;;4653:2;4643:8;4640:16;4637:36;;;4669:1;4666;4659:12;4637:36;4692:63;4747:7;4736:8;4725:9;4721:24;4692:63;:::i;:::-;4682:73;;4808:2;4797:9;4793:18;4780:32;4764:48;;4837:2;4827:8;4824:16;4821:36;;;4853:1;4850;4843:12;4821:36;;4876:63;4931:7;4920:8;4909:9;4905:24;4876:63;:::i;:::-;4866:73;;;4958:39;4992:3;4981:9;4977:19;4958:39;:::i;:::-;4948:49;;5044:3;5033:9;5029:19;5016:33;5006:43;;5068:38;5101:3;5090:9;5086:19;5068:38;:::i;:::-;5058:48;;3849:1263;;;;;;;;;;:::o;5557:261::-;5736:2;5725:9;5718:21;5699:4;5756:56;5808:2;5797:9;5793:18;5785:6;5756:56;:::i;:::-;5748:64;5557:261;-1:-1:-1;;;5557:261:1:o;5823:248::-;5891:6;5899;5952:2;5940:9;5931:7;5927:23;5923:32;5920:52;;;5968:1;5965;5958:12;5920:52;-1:-1:-1;;5991:23:1;;;6061:2;6046:18;;;6033:32;;-1:-1:-1;5823:248:1:o;6076:347::-;6127:8;6137:6;6191:3;6184:4;6176:6;6172:17;6168:27;6158:55;;6209:1;6206;6199:12;6158:55;-1:-1:-1;6232:20:1;;6275:18;6264:30;;6261:50;;;6307:1;6304;6297:12;6261:50;6344:4;6336:6;6332:17;6320:29;;6396:3;6389:4;6380:6;6372;6368:19;6364:30;6361:39;6358:59;;;6413:1;6410;6403:12;6358:59;6076:347;;;;;:::o;6428:614::-;6525:6;6533;6541;6549;6557;6610:3;6598:9;6589:7;6585:23;6581:33;6578:53;;;6627:1;6624;6617:12;6578:53;6663:9;6650:23;6640:33;;6720:2;6709:9;6705:18;6692:32;6682:42;;6771:2;6760:9;6756:18;6743:32;6733:42;;6826:2;6815:9;6811:18;6798:32;6853:18;6845:6;6842:30;6839:50;;;6885:1;6882;6875:12;6839:50;6924:58;6974:7;6965:6;6954:9;6950:22;6924:58;:::i;:::-;6428:614;;;;-1:-1:-1;6428:614:1;;-1:-1:-1;7001:8:1;;6898:84;6428:614;-1:-1:-1;;;6428:614:1:o;7047:184::-;7105:6;7158:2;7146:9;7137:7;7133:23;7129:32;7126:52;;;7174:1;7171;7164:12;7126:52;7197:28;7215:9;7197:28;:::i;7467:545::-;7555:6;7563;7571;7579;7632:2;7620:9;7611:7;7607:23;7603:32;7600:52;;;7648:1;7645;7638:12;7600:52;7684:9;7671:23;7661:33;;7741:2;7730:9;7726:18;7713:32;7703:42;;7796:2;7785:9;7781:18;7768:32;7823:18;7815:6;7812:30;7809:50;;;7855:1;7852;7845:12;7809:50;7894:58;7944:7;7935:6;7924:9;7920:22;7894:58;:::i;:::-;7467:545;;;;-1:-1:-1;7971:8:1;-1:-1:-1;;;;7467:545:1:o;8420:184::-;8472:77;8469:1;8462:88;8569:4;8566:1;8559:15;8593:4;8590:1;8583:15;8609:349;8648:3;8679:66;8672:5;8669:77;8666:257;;8779:77;8776:1;8769:88;8880:4;8877:1;8870:15;8908:4;8905:1;8898:15;8666:257;-1:-1:-1;8950:1:1;8939:13;;8609:349::o;8963:325::-;9051:6;9046:3;9039:19;9103:6;9096:5;9089:4;9084:3;9080:14;9067:43;;9155:1;9148:4;9139:6;9134:3;9130:16;9126:27;9119:38;9021:3;9277:4;9207:66;9202:2;9194:6;9190:15;9186:88;9181:3;9177:98;9173:109;9166:116;;8963:325;;;;:::o;9293:1267::-;9618:4;9666:3;9655:9;9651:19;9697:6;9686:9;9679:25;9723:2;9761:6;9756:2;9745:9;9741:18;9734:34;9787:42;9877:2;9869:6;9865:15;9860:2;9849:9;9845:18;9838:43;9917:3;9912:2;9901:9;9897:18;9890:31;9941:6;9976;9970:13;10007:6;9999;9992:22;10045:3;10034:9;10030:19;10023:26;;10068:6;10065:1;10058:17;10111:2;10108:1;10098:16;10084:30;;10132:1;10142:177;10156:6;10153:1;10150:13;10142:177;;;10221:13;;10217:22;;10205:35;;10307:1;10295:14;;;;10260:12;;;;10171:9;10142:177;;;10146:3;;10365:9;10360:3;10356:19;10350:3;10339:9;10335:19;10328:48;10399:29;10424:3;10416:6;10399:29;:::i;:::-;10385:43;;;;;10477:9;10469:6;10465:22;10459:3;10448:9;10444:19;10437:51;10505:49;10547:6;10539;10531;10505:49;:::i;:::-;10497:57;9293:1267;-1:-1:-1;;;;;;;;;;9293:1267:1:o;10565:245::-;10644:6;10652;10705:2;10693:9;10684:7;10680:23;10676:32;10673:52;;;10721:1;10718;10711:12;10673:52;-1:-1:-1;;10744:16:1;;10800:2;10785:18;;;10779:25;10744:16;;10779:25;;-1:-1:-1;10565:245:1:o;10972:256::-;10892:12;;10880:25;;10954:4;10943:16;;;10937:23;10921:14;;;10914:47;11162:2;11147:18;;11174:48;10815:152;11490:295;11673:4;11665:6;11661:17;11650:9;11643:36;11715:2;11710;11699:9;11695:18;11688:30;11624:4;11735:44;11775:2;11764:9;11760:18;11752:6;11735:44;:::i;:::-;11727:52;11490:295;-1:-1:-1;;;;11490:295:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_interchain","type":"address"},{"internalType":"address[]","name":"_sendingModules","type":"address[]"},{"internalType":"address[]","name":"_receivingModules","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"AppMessageRecieve","type":"event"},{"anonymous":false,"inputs":[],"name":"AppMessageSent","type":"event"},{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"dbNonce","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"appReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainID","type":"uint64"}],"name":"getLinkedIApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOptimisticTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReceivingConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReceivingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRequiredResponses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint256","name":"dstChainId","type":"uint256"}],"name":"getSendingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSendingModules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interchain","outputs":[{"internalType":"contract IInterchainClientV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"chainIDs","type":"uint64[]"},{"internalType":"address[]","name":"linkedIApps","type":"address[]"},{"internalType":"address[]","name":"_sendingModules","type":"address[]"},{"internalType":"address[]","name":"_receivingModules","type":"address[]"},{"internalType":"address","name":"_executionService","type":"address"},{"internalType":"uint256","name":"_requiredResponses","type":"uint256"},{"internalType":"uint64","name":"_optimisticTimePeriod","type":"uint64"}],"name":"setAppConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_interchain\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageRecieve\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"AppMessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"srcChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dbNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"appReceive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainID\",\"type\":\"uint64\"}],\"name\":\"getLinkedIApp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOptimisticTimePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReceivingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequiredResponses\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"}],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSendingModules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interchain\",\"outputs\":[{\"internalType\":\"contract IInterchainClientV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"dstChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"send\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainIDs\",\"type\":\"uint64[]\"},{\"internalType\":\"address[]\",\"name\":\"linkedIApps\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_sendingModules\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_receivingModules\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"_executionService\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_requiredResponses\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_optimisticTimePeriod\",\"type\":\"uint64\"}],\"name\":\"setAppConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"InterchainApp\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0x97256ebb052f6f28fecf0beec3b1dfa66674bc1f309fa5ee1d848c8510a9efce\",\"urls\":[\"bzz-raw://4449ebe8a883f01fc9475e12203c0ba46d8546f96ac1296fa4eefe6a2b236127\",\"dweb:/ipfs/QmPW2zd3zqaAsMed1LSjVLafcE6zXNNiTwqEkHfbnRC69p\"]}},\"version\":1}"},"hashes":{"appReceive(uint256,bytes32,uint256,bytes)":"b399470d","getLinkedIApp(uint64)":"bfc849ee","getOptimisticTimePeriod()":"7c9abd3e","getReceivingConfig()":"287bc057","getReceivingModules()":"a45e107a","getRequiredResponses()":"f31b19a9","getSendingModules()":"ea13398f","getSendingModules(bytes32,uint256)":"ab139613","interchain()":"70838975","send(bytes32,uint256,bytes)":"e1ef3b3f","setAppConfig(uint64[],address[],address[],address[],address,uint256,uint64)":"645d575a"}},"solidity/InterchainApp.sol:OptionsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122092452693727ca9b81af205ba6b3ab0381c3222743ca25625f9ee98bdafee4dbe64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122092452693727ca9b81af205ba6b3ab0381c3222743ca25625f9ee98bdafee4dbe64736f6c63430008140033","info":{"source":"pragma solidity =0.8.20 ^0.8.0 ^0.8.13;\n\n// contracts/interfaces/IInterchainApp.sol\n\n/// @notice Minimal interface for the Interchain App to work with the Interchain Client.\ninterface IInterchainApp {\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable;\n\n function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules);\n}\n\n// contracts/interfaces/IInterchainClientV1.sol\n\ninterface IInterchainClientV1 {\n error InterchainClientV1__FeeAmountTooLow(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectDstChainId(uint256 chainId);\n error InterchainClientV1__IncorrectMsgValue(uint256 actual, uint256 required);\n error InterchainClientV1__IncorrectSrcChainId(uint256 chainId);\n error InterchainClientV1__NotEnoughResponses(uint256 actual, uint256 required);\n error InterchainClientV1__TxAlreadyExecuted(bytes32 transactionId);\n error InterchainClientV1__TxNotExecuted(bytes32 transactionId);\n\n /**\n * @notice Sets the address of the ExecutionFees contract.\n * @dev Only callable by the contract owner or an authorized account.\n * @param executionFees_ The address of the ExecutionFees contract.\n */\n function setExecutionFees(address executionFees_) external;\n\n /**\n * @notice Sets the linked client for a specific chain ID.\n * @dev Stores the address of the linked client in a mapping with the chain ID as the key.\n * @param chainId The chain ID for which the client is being set.\n * @param client The address of the client being linked.\n */\n function setLinkedClient(uint256 chainId, bytes32 client) external;\n\n /**\n * @notice Sends a message to another chain via the Interchain Communication Protocol.\n * @dev Charges a fee for the message, which is payable upon calling this function:\n * - Verification fees: paid to every module that verifies the message.\n * - Execution fee: paid to the executor that executes the message.\n * Note: while a specific execution service is specified to request the execution of the message,\n * any executor is able to execute the message on destination chain, earning the execution fee.\n * @param dstChainId The chain ID of the destination chain.\n * @param receiver The address of the receiver on the destination chain.\n * @param srcExecutionService The address of the execution service to use for the message.\n * @param srcModules The source modules involved in the message sending.\n * @param options Execution options for the message sent, encoded as bytes, currently gas limit + native gas drop.\n * @param message The message being sent.\n * @return transactionId The ID of the transaction that was sent.\n * @return dbNonce The database nonce of the written entry for the transaction.\n */\n function interchainSend(\n uint256 dstChainId,\n bytes32 receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n function interchainSendEVM(\n uint256 dstChainId,\n address receiver,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n payable\n returns (bytes32 transactionId, uint256 dbNonce);\n\n /**\n * @notice Executes a transaction that has been sent via the Interchain.\n * @dev The transaction must have been previously sent and recorded.\n * Transaction data includes the requested gas limit, but the executors could specify a different gas limit.\n * If the specified gas limit is lower than requested, the requested gas limit will be used.\n * Otherwise, the specified gas limit will be used.\n * This allows to execute the transactions with requested gas limit set too low.\n * @param gasLimit The gas limit to use for the execution.\n * @param transaction The transaction data.\n */\n function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable;\n\n /// @notice Writes the proof of execution for a transaction into the InterchainDB.\n /// @dev Will revert if the transaction has not been executed.\n /// @param transactionId The ID of the transaction to write the proof for.\n /// @return dbNonce The database nonce of the written entry for the proof.\n function writeExecutionProof(bytes32 transactionId) external returns (uint256 dbNonce);\n\n /**\n * @notice Checks if a transaction is executable.\n * @dev Determines if a transaction meets the criteria to be executed based on:\n * - If approved modules have written to the InterchainDB\n * - If the threshold of approved modules have been met\n * - If the optimistic window has passed for all modules\n * @param transaction The InterchainTransaction struct to be checked.\n * @return bool Returns true if the transaction is executable, false otherwise.\n */\n function isExecutable(bytes calldata transaction) external view returns (bool);\n\n /// @notice Returns the fee for sending an Interchain message.\n /// @param dstChainId The chain ID of the destination chain.\n /// @param srcExecutionService The address of the execution service to use for the message.\n /// @param srcModules The source modules involved in the message sending.\n /// @param options Execution options for the message sent, currently gas limit + native gas drop.\n /// @param message The message being sent.\n function getInterchainFee(\n uint256 dstChainId,\n address srcExecutionService,\n address[] calldata srcModules,\n bytes calldata options,\n bytes calldata message\n )\n external\n view\n returns (uint256);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutor(bytes calldata transaction) external view returns (address);\n\n /// @notice Returns the address of the executor for a transaction that has been sent to the local chain.\n function getExecutorById(bytes32 transactionId) external view returns (address);\n}\n\n// contracts/libs/AppConfig.sol\n\nstruct AppConfigV1 {\n uint256 requiredResponses;\n uint256 optimisticPeriod;\n}\n\nusing AppConfigLib for AppConfigV1 global;\n\nlibrary AppConfigLib {\n error AppConfigLib__IncorrectVersion(uint8 version);\n\n uint8 constant APP_CONFIG_V1 = 1;\n\n /// @notice Encodes versioned app config into a bytes format.\n /// @param version The version of the app config.\n /// @param appConfig The app config to encode.\n function encodeVersionedAppConfig(uint8 version, bytes memory appConfig) internal pure returns (bytes memory) {\n return abi.encode(version, appConfig);\n }\n\n /// @notice Decodes versioned app config from a bytes format back into a version and app config.\n /// @param data The versioned app config data in bytes format.\n /// @return version The version of the app config.\n /// @return appConfig The app config as bytes.\n function decodeVersionedAppConfig(bytes memory data)\n internal\n pure\n returns (uint8 version, bytes memory appConfig)\n {\n (version, appConfig) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 app config into a bytes format.\n /// @param appConfig The AppConfigV1 to encode.\n function encodeAppConfigV1(AppConfigV1 memory appConfig) internal pure returns (bytes memory) {\n return encodeVersionedAppConfig(APP_CONFIG_V1, abi.encode(appConfig));\n }\n\n /// @notice Decodes app config (V1 or higher) from a bytes format back into an AppConfigV1 struct.\n /// @param data The app config data in bytes format.\n function decodeAppConfigV1(bytes memory data) internal pure returns (AppConfigV1 memory) {\n (uint8 version, bytes memory appConfig) = decodeVersionedAppConfig(data);\n if (version \u003c APP_CONFIG_V1) {\n revert AppConfigLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(appConfig, (AppConfigV1));\n }\n}\n\n// contracts/libs/Options.sol\n\n/// @notice Struct to hold V1 of options data.\n/// @dev Next versions have to use the fields from the previous version and add new fields at the end.\n/// @param gasLimit The gas limit for the transaction.\n/// @param gasAirdrop The amount of gas to airdrop.\nstruct OptionsV1 {\n uint256 gasLimit;\n uint256 gasAirdrop;\n}\n\nusing OptionsLib for OptionsV1 global;\n\n/// @title OptionsLib\n/// @notice A library for encoding and decoding Interchain options related to interchain messages.\nlibrary OptionsLib {\n error OptionsLib__IncorrectVersion(uint8 version);\n\n uint8 constant OPTIONS_V1 = 1;\n\n /// @notice Encodes versioned options into a bytes format.\n /// @param version The version of the options.\n /// @param options The options to encode.\n function encodeVersionedOptions(uint8 version, bytes memory options) internal pure returns (bytes memory) {\n return abi.encode(version, options);\n }\n\n /// @notice Decodes versioned options from a bytes format back into a version and options.\n /// @param data The versioned options data in bytes format.\n /// @return version The version of the options.\n /// @return options The options as bytes.\n function decodeVersionedOptions(bytes memory data) internal pure returns (uint8 version, bytes memory options) {\n (version, options) = abi.decode(data, (uint8, bytes));\n }\n\n /// @notice Encodes V1 options into a bytes format.\n /// @param options The OptionsV1 to encode.\n function encodeOptionsV1(OptionsV1 memory options) internal pure returns (bytes memory) {\n return encodeVersionedOptions(OPTIONS_V1, abi.encode(options));\n }\n\n /// @notice Decodes options (V1 or higher) from a bytes format back into an OptionsV1 struct.\n /// @param data The options data in bytes format.\n function decodeOptionsV1(bytes memory data) internal pure returns (OptionsV1 memory) {\n (uint8 version, bytes memory options) = decodeVersionedOptions(data);\n if (version \u003c OPTIONS_V1) {\n revert OptionsLib__IncorrectVersion(version);\n }\n // Structs of the same version will always be decoded correctly.\n // Following versions will be decoded correctly if they have the same fields as the previous version,\n // and new fields at the end: abi.decode ignores the extra bytes in the decoded payload.\n return abi.decode(options, (OptionsV1));\n }\n}\n\n// contracts/InterchainApp.sol\n\ncontract InterchainApp is IInterchainApp {\n using AppConfigLib for bytes;\n // What properties should Interchain be pulling from InterchainApp?\n // 1. Which modules to use, and how many are required?\n\n IInterchainClientV1 public interchain;\n\n address[] private sendingModules;\n address[] private receivingModules;\n address private executionService;\n\n struct AppConfig {\n // ChainID -\u003e Linked IApps\n mapping(uint64 =\u003e address) linkedIApps;\n // Sends message to be verified through all modules\n address[] sendingModules;\n // Accepts messages from these destination chain modules\n address[] receivingModules;\n AppConfigV1 bytesAppConfig;\n }\n\n AppConfig private localAppConfig;\n\n // Set the application configuration\n function setAppConfig(\n uint64[] memory chainIDs,\n address[] memory linkedIApps,\n address[] memory _sendingModules,\n address[] memory _receivingModules,\n address _executionService,\n uint256 _requiredResponses,\n uint64 _optimisticTimePeriod\n )\n public\n {\n // TODO: Add access control or ownership checks\n require(chainIDs.length == linkedIApps.length, \"ChainIDs and IApps length mismatch\");\n\n for (uint256 i = 0; i \u003c chainIDs.length; i++) {\n localAppConfig.linkedIApps[chainIDs[i]] = linkedIApps[i];\n }\n\n localAppConfig.bytesAppConfig =\n AppConfigV1({requiredResponses: _requiredResponses, optimisticPeriod: _optimisticTimePeriod});\n\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n executionService = _executionService;\n }\n\n // Getters for the application configuration\n function getLinkedIApp(uint64 chainID) external view returns (address) {\n return localAppConfig.linkedIApps[chainID];\n }\n\n // TODO: Is a receiving module the same as a sending module?\n function getSendingModules() external view returns (address[] memory) {\n return localAppConfig.sendingModules;\n }\n\n function getReceivingModules() external view returns (address[] memory) {\n return localAppConfig.receivingModules;\n }\n\n function getRequiredResponses() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.requiredResponses;\n }\n\n function getOptimisticTimePeriod() external view returns (uint256) {\n return localAppConfig.bytesAppConfig.optimisticPeriod;\n }\n\n function getSendingModules(bytes32 receiver, uint256 dstChainId) external view returns (address[] memory) {\n return sendingModules;\n }\n\n function getReceivingConfig() external view returns (bytes memory, address[] memory) {\n return (AppConfigLib.encodeAppConfigV1(localAppConfig.bytesAppConfig), localAppConfig.receivingModules);\n }\n\n constructor(address _interchain, address[] memory _sendingModules, address[] memory _receivingModules) {\n interchain = IInterchainClientV1(_interchain);\n localAppConfig.sendingModules = _sendingModules;\n localAppConfig.receivingModules = _receivingModules;\n }\n\n event AppMessageRecieve();\n event AppMessageSent();\n\n function send(bytes32 receiver, uint256 dstChainId, bytes calldata message) external payable {\n bytes memory options = OptionsV1(200_000, 0).encodeOptionsV1();\n // TODO: Currently, we forward all gas to Interchain, this may not be expected behavior, and the real abstract contract shouldn't do this\n interchain.interchainSend{value: msg.value}(\n dstChainId, receiver, executionService, localAppConfig.sendingModules, options, message\n );\n emit AppMessageSent();\n }\n\n // TODO: Auth checks based on incoming message\n function appReceive(uint256 srcChainId, bytes32 sender, uint256 dbNonce, bytes calldata message) external payable {\n emit AppMessageRecieve();\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"9171:1958:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;9171:1958:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"9171:1958:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"uint8","name":"version","type":"uint8"}],"name":"OptionsLib__IncorrectVersion","type":"error"}],"userDoc":{"kind":"user","methods":{},"notice":"A library for encoding and decoding Interchain options related to interchain messages.","version":1},"developerDoc":{"kind":"dev","methods":{},"title":"OptionsLib","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"OptionsLib__IncorrectVersion\",\"type\":\"error\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"OptionsLib\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"A library for encoding and decoding Interchain options related to interchain messages.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/InterchainApp.sol\":\"OptionsLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/InterchainApp.sol\":{\"keccak256\":\"0x97256ebb052f6f28fecf0beec3b1dfa66674bc1f309fa5ee1d848c8510a9efce\",\"urls\":[\"bzz-raw://4449ebe8a883f01fc9475e12203c0ba46d8546f96ac1296fa4eefe6a2b236127\",\"dweb:/ipfs/QmPW2zd3zqaAsMed1LSjVLafcE6zXNNiTwqEkHfbnRC69p\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file diff --git a/sin-executor/executor/executor.go b/sin-executor/executor/executor.go index 4df5c8e884..c8f323277b 100644 --- a/sin-executor/executor/executor.go +++ b/sin-executor/executor/executor.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/synapsecns/sanguine/core" + "github.com/synapsecns/sanguine/sin-executor/contracts/executionservice" "math/big" "time" @@ -59,20 +60,21 @@ func NewExecutor(ctx context.Context, handler metrics.Handler, cfg config.Config executor.chainListeners = make(map[int]listener.ContractListener) executor.clientContracts = make(map[int]*interchainclient.InterchainClientRef) - for chainID, address := range cfg.Chains { - synapseModule := common.HexToAddress(address) + for chainID, chainCfg := range cfg.Chains { + executionService := common.HexToAddress(chainCfg.ExecutionService) + interchainClient := common.HexToAddress(chainCfg.Client) chainClient, err := executor.client.GetChainClient(ctx, chainID) if err != nil { return nil, fmt.Errorf("could not get chain client: %w", err) } - chainListener, err := listener.NewChainListener(chainClient, executor.db, synapseModule, handler) + chainListener, err := listener.NewChainListener(chainClient, executor.db, executionService, handler) if err != nil { return nil, fmt.Errorf("could not get chain listener: %w", err) } executor.chainListeners[chainID] = chainListener - executor.clientContracts[chainID], err = interchainclient.NewInterchainClientRef(synapseModule, chainClient) + executor.clientContracts[chainID], err = interchainclient.NewInterchainClientRef(interchainClient, chainClient) if err != nil { return nil, fmt.Errorf("could not get synapse module ref: %w", err) } @@ -181,10 +183,7 @@ func (e *Executor) executeTransaction(ctx context.Context, request db.Transactio status, _ := e.submitter.GetSubmissionStatus(ctx, request.DstChainID, nonce) if status.TxHash().String() != (common.Hash{}).String() { - fmt.Println("STATUS") - fmt.Println(status) - fmt.Println("hash") - fmt.Println(status.TxHash().String()) + fmt.Printf("cast run %s --rpc-url %s/rpc/2\n", status.TxHash().String(), e.cfg.OmnirpcURL) } } }() @@ -203,6 +202,10 @@ func (e *Executor) checkReady(ctx context.Context, request db.TransactionSent) e return fmt.Errorf("could not get contract for chain %d", request.DstChainID.Int64()) } + // TODO: REMOVE ME + // err := e.db.UpdateInterchainTransactionStatus(ctx, request.TransactionID, db.Ready) + // TODO: REMOVE ME + isExecutable, err := contract.IsExecutable(&bind.CallOpts{Context: ctx}, request.EncodedTX) if err != nil { return fmt.Errorf("could not check if executable: %w", err) @@ -224,7 +227,7 @@ func (e *Executor) startChainIndexers(ctx context.Context) error { // TODO: good chance we wanna prepare these chain listeners up front and then listen later. for chainID := range e.cfg.Chains { - chainID := chainID // capture func literal + chainID := chainID // capture func litera g.Go(func() error { err := e.runChainIndexer(ctx, chainID) @@ -250,14 +253,23 @@ const defaultDBInterval = 3 func (e *Executor) runChainIndexer(parentCtx context.Context, chainID int) (err error) { chainListener := e.chainListeners[chainID] - parser, err := interchainclient.NewParser(chainListener.Address()) + clientParser, err := interchainclient.NewParser(chainListener.Address()) if err != nil { return fmt.Errorf("could not parse: %w", err) } + executionServiceParser, err := executionservice.NewParser(chainListener.Address()) + if err != nil { + return fmt.Errorf("could not parse: %w", err) + } + + chainClient, err := e.client.GetChainClient(parentCtx, chainID) + if err != nil { + return fmt.Errorf("could not get chain client: %w", err) + } + err = chainListener.Listen(parentCtx, func(parentCtx context.Context, log types.Log) (err error) { - et, parsedEvent, ok := parser.ParseEvent(log) - // handle unknown event + oget, _, ok := executionServiceParser.ParseEvent(log) if !ok { if len(log.Topics) != 0 { e.metrics.ExperimentalLogger().Warnf(parentCtx, "unknown event %s", log.Topics[0]) @@ -265,7 +277,7 @@ func (e *Executor) runChainIndexer(parentCtx context.Context, chainID int) (err return nil } - ctx, span := e.metrics.Tracer().Start(parentCtx, fmt.Sprintf("handleLog-%s", et), trace.WithAttributes( + ctx, span := e.metrics.Tracer().Start(parentCtx, fmt.Sprintf("handleLog-%s", oget), trace.WithAttributes( attribute.String(metrics.TxHash, log.TxHash.String()), attribute.Int(metrics.Origin, chainID), attribute.String(metrics.Contract, log.Address.String()), @@ -277,34 +289,51 @@ func (e *Executor) runChainIndexer(parentCtx context.Context, chainID int) (err metrics.EndSpanWithErr(span, err) }() - switch event := parsedEvent.(type) { - case *interchainclient.InterchainClientV1InterchainTransactionSent: - encodedTX, err := e.clientContracts[chainID].EncodeTransaction(&bind.CallOpts{Context: ctx}, interchainclient.InterchainTransaction{ - SrcChainId: big.NewInt(int64(chainID)), - SrcSender: event.SrcSender, - DstChainId: core.CopyBigInt(event.DstChainId), - DstReceiver: event.DstReceiver, - DbNonce: event.DbNonce, - Options: event.Options, - Message: event.Message, - }) - - decodedOptions, err := e.clientContracts[chainID].DecodeOptions(&bind.CallOpts{Context: ctx}, event.Options) - if err != nil { - return fmt.Errorf("could not decode options: %w", err) + receipt, err := chainClient.TransactionReceipt(ctx, log.TxHash) + if err != nil { + return fmt.Errorf("could not get transaction receipt: %w", err) + } + + for _, receiptLog := range receipt.Logs { + _, parsedEvent, ok := clientParser.ParseEvent(*receiptLog) + // handle unknown event + if !ok { + continue + } + + switch event := parsedEvent.(type) { + case *interchainclient.InterchainClientV1InterchainTransactionSent: + encodedTX, err := e.clientContracts[chainID].EncodeTransaction(&bind.CallOpts{Context: ctx}, interchainclient.InterchainTransaction{ + SrcChainId: big.NewInt(int64(chainID)), + SrcSender: event.SrcSender, + DstChainId: core.CopyBigInt(event.DstChainId), + DstReceiver: event.DstReceiver, + DbNonce: event.DbNonce, + Options: event.Options, + Message: event.Message, + }) + if err != nil { + return fmt.Errorf("could not encode transaction: %w", err) + } + + decodedOptions, err := e.clientContracts[chainID].DecodeOptions(&bind.CallOpts{Context: ctx}, event.Options) + if err != nil { + return fmt.Errorf("could not decode options: %w", err) + } + + err = e.db.StoreInterchainTransaction(ctx, big.NewInt(int64(chainID)), event, &decodedOptions, encodedTX) + if err != nil { + return fmt.Errorf("could not store interchain transaction: %w", err) + } } - err = e.db.StoreInterchainTransaction(ctx, big.NewInt(int64(chainID)), event, &decodedOptions, encodedTX) + // stop the world. if err != nil { - return fmt.Errorf("could not store interchain transaction: %w", err) + return fmt.Errorf("could not handle event: %w", err) } - } - // stop the world. - if err != nil { - return fmt.Errorf("could not handle event: %w", err) + return nil } - return nil }) diff --git a/sin-executor/executor/executor_test.go b/sin-executor/executor/executor_test.go index 13e4982b5a..2265635a48 100644 --- a/sin-executor/executor/executor_test.go +++ b/sin-executor/executor/executor_test.go @@ -2,6 +2,9 @@ package executor_test import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/optionslibexport" "math/big" "time" @@ -14,9 +17,24 @@ func (i *InterchainSuite) TestE2E() { auth := i.originChain.GetTxContext(i.GetTestContext(), nil) receiver := i.addressToBytes32(i.deployManager.Get(i.GetTestContext(), i.destChain, testutil.InterchainApp).Address()) + message := []byte("hello") + + _, optionsLib := i.deployManager.GetOptionsLib(i.GetTestContext(), i.originChain) + // must match values in the contract + encodedOptions, err := optionsLib.EncodeOptions(&bind.CallOpts{Context: i.GetTestContext()}, optionslibexport.OptionsV1{ + GasLimit: big.NewInt(200000), + GasAirdrop: big.NewInt(0), + }) + i.Require().NoError(err) + + _, originClient := i.deployManager.GetInterchainClient(i.GetTestContext(), i.originChain) + interchainFee, err := originClient.GetInterchainFee(&bind.CallOpts{Context: i.GetTestContext()}, + i.destChain.GetBigChainID(), i.deployManager.Get(i.GetTestContext(), i.originChain, testutil.ExecutionService).Address(), []common.Address{i.deployManager.Get(i.GetTestContext(), i.originChain, testutil.InterchainModuleMock).Address()}, encodedOptions, message) + i.Require().NoError(err) _, appMock := i.deployManager.GetInterchainAppMock(i.GetTestContext(), i.originChain) - tx, err := appMock.Send(auth.TransactOpts, receiver, i.destChain.GetBigChainID(), []byte("hello")) + auth.TransactOpts.Value = interchainFee + tx, err := appMock.Send(auth.TransactOpts, receiver, i.destChain.GetBigChainID(), message) i.Require().NoError(err) i.Require().NoError(err) i.originChain.WaitForConfirmation(i.GetTestContext(), tx) @@ -37,7 +55,6 @@ func (i *InterchainSuite) TestE2E() { if err != nil { continue } - _, destDB := i.deployManager.GetInterchainDB(i.GetTestContext(), i.destChain) destContext := i.destChain.GetTxContext(i.GetTestContext(), nil) @@ -63,6 +80,5 @@ func (i *InterchainSuite) TestE2E() { i.destChain.GetFundedAccount(i.GetTestContext(), big.NewInt(1)) } }() - time.Sleep(time.Minute * 1) } diff --git a/sin-executor/executor/suite_test.go b/sin-executor/executor/suite_test.go index 60097e6a15..b33d717ed6 100644 --- a/sin-executor/executor/suite_test.go +++ b/sin-executor/executor/suite_test.go @@ -68,10 +68,24 @@ func (i *InterchainSuite) SetupTest() { }() wg.Wait() - i.omnirpcURL = testhelper.NewOmnirpcServer(i.GetTestContext(), i.T(), i.originChain, i.destChain) + wg = sync.WaitGroup{} + wg.Add(3) + go func() { + i.omnirpcURL = testhelper.NewOmnirpcServer(i.GetTestContext(), i.T(), i.originChain, i.destChain) + wg.Done() + }() + + go func() { + i.setClientConfigs(i.originChain, i.originModule, originInfo, destInfo, i.destChain) + wg.Done() + }() + + go func() { + i.setClientConfigs(i.destChain, i.destModule, destInfo, originInfo, i.originChain) + wg.Done() + }() + wg.Wait() - i.setClientConfigs(i.originChain, i.originModule, originInfo, destInfo, i.destChain) - i.setClientConfigs(i.destChain, i.destModule, destInfo, originInfo, i.originChain) i.makeExecutor() } @@ -93,9 +107,11 @@ func (i *InterchainSuite) setClientConfigs(backend backends.SimulatedTestBackend receivingModules, err := appMock.GetReceivingModules(&bind.CallOpts{Context: i.GetTestContext()}) i.Require().NoError(err) + + _, executionService := i.deployManager.GetExecutionService(i.GetTestContext(), backend) // same thing - tx, err = appMock.SetAppConfig(auth.TransactOpts, chainIDS, linkedApps, sendingModules, receivingModules, big.NewInt(1), 0) + tx, err = appMock.SetAppConfig(auth.TransactOpts, chainIDS, linkedApps, sendingModules, receivingModules, executionService.Address(), big.NewInt(1), 0) i.Require().NoError(err) backend.WaitForConfirmation(i.GetTestContext(), tx) } @@ -115,10 +131,19 @@ func (i *InterchainSuite) makeExecutor() { i.originChain.FundAccount(i.GetTestContext(), testWallet.Address(), *new(big.Int).SetUint64(params.Ether)) i.destChain.FundAccount(i.GetTestContext(), testWallet.Address(), *new(big.Int).SetUint64(params.Ether)) + originOwner, execServiceOrigin := i.deployManager.GetExecutionService(i.GetTestContext(), i.originChain) + destOwner, execServiceDest := i.deployManager.GetExecutionService(i.GetTestContext(), i.destChain) + cfg := config.Config{ - Chains: map[int]string{ - 1: i.originModule.Address().String(), - 2: i.destModule.Address().String(), + Chains: map[int]config.ChainConfig{ + 1: { + ExecutionService: execServiceOrigin.Address().String(), + Client: i.originModule.Address().String(), + }, + 2: { + ExecutionService: execServiceDest.Address().String(), + Client: i.destModule.Address().String(), + }, }, OmnirpcURL: i.omnirpcURL, Database: config.DatabaseConfig{ @@ -134,6 +159,17 @@ func (i *InterchainSuite) makeExecutor() { i.executor, err = executor.NewExecutor(i.GetTestContext(), i.metrics, cfg) i.Require().NoError(err) + originOpts := i.originChain.GetTxContext(i.GetTestContext(), originOwner.OwnerPtr()) + destOpts := i.destChain.GetTxContext(i.GetTestContext(), destOwner.OwnerPtr()) + + tx, err := execServiceOrigin.SetExecutorEOA(originOpts.TransactOpts, testWallet.Address()) + i.Require().NoError(err) + i.originChain.WaitForConfirmation(i.GetTestContext(), tx) + + tx, err = execServiceDest.SetExecutorEOA(destOpts.TransactOpts, testWallet.Address()) + i.Require().NoError(err) + i.destChain.WaitForConfirmation(i.GetTestContext(), tx) + go func() { err = i.executor.Start(i.GetTestContext()) if !errors.Is(err, context.Canceled) { diff --git a/sin-executor/testutil/contracttype.go b/sin-executor/testutil/contracttype.go index 21c94bd464..dd9497ea5e 100644 --- a/sin-executor/testutil/contracttype.go +++ b/sin-executor/testutil/contracttype.go @@ -4,10 +4,11 @@ import ( "github.com/ethereum/go-ethereum/common/compiler" "github.com/synapsecns/sanguine/ethergo/backends/base" "github.com/synapsecns/sanguine/ethergo/contracts" + "github.com/synapsecns/sanguine/sin-executor/contracts/executionservice" "github.com/synapsecns/sanguine/sin-executor/contracts/interchainclient" "github.com/synapsecns/sanguine/sin-executor/contracts/interchaindb" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/executionfeesmock" - "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/executionservicemock" + "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/gasoraclemock" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/interchainapp" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/interchainmodulemock" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/optionslibexport" @@ -58,10 +59,12 @@ const ( InterchainApp // InterchainApp // OptionsLib is the options library. OptionsLib // OptionsLib - // ExecutionServiceMock is the execution service mock. - ExecutionServiceMock // ExecutionServiceMock + // ExecutionService is the execution service mock. + ExecutionService // ExecutionService // ExecutionFeesMock is the execution fees mock. ExecutionFeesMock // ExecutionFeesMock + // GasOracleMock is the gas oracle mock. + GasOracleMock // GasOracleMock ) // ID gets the contract type as an id. @@ -98,10 +101,12 @@ func (c contractTypeImpl) ContractInfo() *compiler.Contract { return interchainapp.Contracts["solidity/InterchainApp.sol:InterchainApp"] case OptionsLib: return optionslibexport.Contracts["solidity/OptionsLibExport.sol:OptionsLibMocks"] - case ExecutionServiceMock: - return executionservicemock.Contracts["solidity/ExecutionServiceMock.sol:ExecutionServiceMock"] + case ExecutionService: + return executionservice.Contracts["solidity/ExecutionService.sol:ExecutionService"] case ExecutionFeesMock: return executionfeesmock.Contracts["solidity/ExecutionfeesMock.sol:ExecutionFeesMock"] + case GasOracleMock: + return gasoraclemock.Contracts["solidity/GasOracleMock.sol:GasOracleMock"] } return nil } diff --git a/sin-executor/testutil/contracttypeimpl_string.go b/sin-executor/testutil/contracttypeimpl_string.go index 61511d955e..8845e4c573 100644 --- a/sin-executor/testutil/contracttypeimpl_string.go +++ b/sin-executor/testutil/contracttypeimpl_string.go @@ -13,13 +13,14 @@ func _() { _ = x[InterchainModuleMock-3] _ = x[InterchainApp-4] _ = x[OptionsLib-5] - _ = x[ExecutionServiceMock-6] + _ = x[ExecutionService-6] _ = x[ExecutionFeesMock-7] + _ = x[GasOracleMock-8] } -const _contractTypeImpl_name = "SynapseModuleSynapseModuleInterchainModuleMockInterchainAppOptionsLibExecutionServiceMockExecutionFeesMock" +const _contractTypeImpl_name = "SynapseModuleSynapseModuleInterchainModuleMockInterchainAppOptionsLibExecutionServiceExecutionFeesMockGasOracleMock" -var _contractTypeImpl_index = [...]uint8{0, 13, 26, 46, 59, 69, 89, 106} +var _contractTypeImpl_index = [...]uint8{0, 13, 26, 46, 59, 69, 85, 102, 115} func (i contractTypeImpl) String() string { i -= 1 diff --git a/sin-executor/testutil/deployers.go b/sin-executor/testutil/deployers.go index fc2c7d49d1..95d06e01b4 100644 --- a/sin-executor/testutil/deployers.go +++ b/sin-executor/testutil/deployers.go @@ -9,10 +9,11 @@ import ( "github.com/synapsecns/sanguine/ethergo/contracts" "github.com/synapsecns/sanguine/ethergo/deployer" "github.com/synapsecns/sanguine/ethergo/manager" + "github.com/synapsecns/sanguine/sin-executor/contracts/executionservice" "github.com/synapsecns/sanguine/sin-executor/contracts/interchainclient" "github.com/synapsecns/sanguine/sin-executor/contracts/interchaindb" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/executionfeesmock" - "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/executionservicemock" + "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/gasoraclemock" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/interchainapp" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/interchainmodulemock" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/optionslibexport" @@ -28,7 +29,7 @@ type DeployManager struct { func NewDeployManager(t *testing.T) *DeployManager { t.Helper() - return &DeployManager{manager.NewDeployerManager(t, interchainClientDeployer, interchainDBDeployer, interchainModuleMockDeployer, interchainAppMockDeployer, optionsLibMock, executionServiceMock, executionFeesMock)} + return &DeployManager{manager.NewDeployerManager(t, interchainClientDeployer, interchainDBDeployer, interchainModuleMockDeployer, interchainAppMockDeployer, optionsLibMock, executionService, executionFeesMock, gasOracleMock)} } var ( @@ -101,15 +102,39 @@ var ( return optionslibexport.NewOptionsLibExportRef(address, backend) }, []contracts.ContractType{}) - executionServiceMock = deployer.NewFunctionalDeployer(ExecutionServiceMock, func(ctx context.Context, helpers deployer.IFunctionalDeployer, transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { - return executionservicemock.DeployExecutionServiceMock(transactOps, backend) + executionService = deployer.NewFunctionalDeployer(ExecutionService, func(ctx context.Context, helpers deployer.IFunctionalDeployer, transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { + address, deployTx, iface, err := executionservice.DeployExecutionService(transactOps, backend) + if err != nil { + return common.Address{}, nil, nil, fmt.Errorf("could not deploy execution service: %w", err) + } + helpers.Backend().WaitForConfirmation(ctx, deployTx) + + tx, err := iface.SetGasOracle(transactOps, helpers.Registry().Get(ctx, GasOracleMock).Address()) + if err != nil { + return common.Address{}, nil, nil, fmt.Errorf("could not set gas oracle: %w", err) + } + helpers.Backend().WaitForConfirmation(ctx, tx) + + tx, err = iface.SetInterchainClient(transactOps, helpers.Registry().Get(ctx, InterchainClient).Address()) + if err != nil { + return common.Address{}, nil, nil, fmt.Errorf("could not set interchain client: %w", err) + } + helpers.Backend().WaitForConfirmation(ctx, tx) + + return address, tx, iface, nil }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { - return executionservicemock.NewExecutionserviceMockRef(address, backend) - }, []contracts.ContractType{}) + return executionservice.NewExecutionServiceRef(address, backend) + }, []contracts.ContractType{GasOracleMock, InterchainClient}) executionFeesMock = deployer.NewFunctionalDeployer(ExecutionFeesMock, func(ctx context.Context, helpers deployer.IFunctionalDeployer, transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { return executionfeesmock.DeployExecutionFeesMock(transactOps, backend) }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { return executionfeesmock.NewExecutionfeesMockRef(address, backend) }, []contracts.ContractType{}) + + gasOracleMock = deployer.NewFunctionalDeployer(GasOracleMock, func(ctx context.Context, helpers deployer.IFunctionalDeployer, transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error) { + return gasoraclemock.DeployGasOracleMock(transactOps, backend) + }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) { + return gasoraclemock.NewGasOracleMockRef(address, backend) + }, []contracts.ContractType{}) ) diff --git a/sin-executor/testutil/typecast.go b/sin-executor/testutil/typecast.go index 14968348c8..d4b50fbe86 100644 --- a/sin-executor/testutil/typecast.go +++ b/sin-executor/testutil/typecast.go @@ -5,6 +5,7 @@ import ( "github.com/synapsecns/sanguine/ethergo/backends" "github.com/synapsecns/sanguine/ethergo/contracts" "github.com/synapsecns/sanguine/ethergo/manager" + "github.com/synapsecns/sanguine/sin-executor/contracts/executionservice" "github.com/synapsecns/sanguine/sin-executor/contracts/interchainclient" "github.com/synapsecns/sanguine/sin-executor/contracts/interchaindb" "github.com/synapsecns/sanguine/sin-executor/contracts/mocks/interchainapp" @@ -46,3 +47,9 @@ func (d *DeployManager) GetInterchainAppMock(ctx context.Context, backend backen return manager.GetContract[*interchainapp.InterchainAppMockRef](ctx, d.T(), d, backend, InterchainApp) } + +func (d *DeployManager) GetExecutionService(ctx context.Context, backend backends.SimulatedTestBackend) (contract contracts.DeployedContract, handle *executionservice.ExecutionServiceRef) { + d.T().Helper() + + return manager.GetContract[*executionservice.ExecutionServiceRef](ctx, d.T(), d, backend, ExecutionService) +}