From 864be6d2e0973911be9054fa6df143d489637b0a Mon Sep 17 00:00:00 2001 From: srdtrk <59252793+srdtrk@users.noreply.github.com> Date: Wed, 29 Jan 2025 20:32:01 +0800 Subject: [PATCH] imp: merge IBCStore into ICS26Router (#246) --- README.md | 14 +- abi/IBCStore.json | 464 --------------- abi/ICS26Router.json | 54 +- abigen/ibcstore/contract.go | 561 ------------------ abigen/ics26router/contract.go | 54 +- abigen/ics26router/store.go | 4 + contracts/ICS20Transfer.sol | 4 +- contracts/ICS26Router.sol | 88 +-- contracts/errors/IICS24HostErrors.sol | 8 - contracts/errors/IICS26RouterErrors.sol | 3 - contracts/interfaces/IIBCStore.sol | 28 - contracts/interfaces/IICS26Router.sol | 5 - contracts/utils/IBCStore.sol | 88 --- contracts/utils/IBCStoreUpgradeable.sol | 111 ++++ .../e2esuite/light_clients.go | 4 +- e2e/interchaintestv8/ethereum/utils.go | 4 +- e2e/interchaintestv8/ibc_eureka_test.go | 131 ++-- e2e/interchaintestv8/multichain_test.go | 8 +- e2e/interchaintestv8/testvalues/values.go | 4 +- justfile | 2 - packages/solidity/src/ibc_store.rs | 18 - packages/solidity/src/lib.rs | 1 - scripts/E2ETestDeploy.s.sol | 1 - test/solidity-ibc/BenchmarkTest.t.sol | 10 +- test/solidity-ibc/IntegrationTest.t.sol | 176 +----- test/solidity-ibc/mocks/ErroneousIBCStore.sol | 39 -- 26 files changed, 319 insertions(+), 1565 deletions(-) delete mode 100644 abi/IBCStore.json delete mode 100644 abigen/ibcstore/contract.go create mode 100644 abigen/ics26router/store.go delete mode 100644 contracts/utils/IBCStore.sol create mode 100644 contracts/utils/IBCStoreUpgradeable.sol delete mode 100644 packages/solidity/src/ibc_store.rs delete mode 100644 test/solidity-ibc/mocks/ErroneousIBCStore.sol diff --git a/README.md b/README.md index 657d1e59f..659edaede 100644 --- a/README.md +++ b/README.md @@ -161,11 +161,11 @@ The following benchmarks are for a single packet transfer without aggregation. | **Contract** | **Method** | **Description** | **Gas (groth16)** | **Gas (plonk)** | |:---:|:---:|:---:|:---:|:---:| -| `ICS26Router.sol` | `sendPacket` | Initiating an IBC transfer with an `ERC20`. | ~174,000 | ~174,000 | -| `ICS26Router.sol` | `recvPacket` | Receiving _back_ an `ERC20` token. | ~528,043 | ~611,904 | -| `ICS26Router.sol` | `recvPacket` | Receiving a _new_ Cosmos token for the first time. (Deploying an `ERC20` contract) | ~1,378,483 | ~1,462,056 | -| `ICS26Router.sol` | `ackPacket` | Acknowledging an ICS20 packet. | ~404,755 | ~488,517 | -| `ICS26Router.sol` | `timeoutPacket` | Timing out an ICS20 packet | ~462,234 | ~545,938 | +| `ICS26Router.sol` | `sendPacket` | Initiating an IBC transfer with an `ERC20`. | ~160,500 | ~160,500 | +| `ICS26Router.sol` | `recvPacket` | Receiving _back_ an `ERC20` token. | ~514,011 | ~597,875 | +| `ICS26Router.sol` | `recvPacket` | Receiving a _new_ Cosmos token for the first time. (Deploying an `ERC20` contract) | ~1,364,451 | ~1,448,027 | +| `ICS26Router.sol` | `ackPacket` | Acknowledging an ICS20 packet. | ~395,232 | ~478,997 | +| `ICS26Router.sol` | `timeoutPacket` | Timing out an ICS20 packet | ~452,661 | ~536,368 | ### Aggregated Packet Benchmarks @@ -174,8 +174,8 @@ Since there is no meaningful difference in gas costs between plonk and groth16 i | **ICS26Router Method** | **Description** | **Avg Gas (25 packets)** | **Avg Gas (50 packets)** | |:---:|:---:|:---:|:---:| -| `multicall/recvPacket` | Receiving _back_ an `ERC20` token. | ~193,438 | ~187,042 | -| `multicall/ackPacket` | Acknowledging an ICS20 packet. | ~99,469 | ~93,679 | +| `multicall/recvPacket` | Receiving _back_ an `ERC20` token. | ~185,583 | ~179,324 | +| `multicall/ackPacket` | Acknowledging an ICS20 packet. | ~96,148 | ~90,485 | Note: These gas benchmarks are with Groth16. diff --git a/abi/IBCStore.json b/abi/IBCStore.json deleted file mode 100644 index 282c85b4f..000000000 --- a/abi/IBCStore.json +++ /dev/null @@ -1,464 +0,0 @@ -[ - { - "type": "constructor", - "inputs": [ - { - "name": "owner_", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "commitPacket", - "inputs": [ - { - "name": "packet", - "type": "tuple", - "internalType": "struct IICS26RouterMsgs.Packet", - "components": [ - { - "name": "sequence", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "sourceClient", - "type": "string", - "internalType": "string" - }, - { - "name": "destClient", - "type": "string", - "internalType": "string" - }, - { - "name": "timeoutTimestamp", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "payloads", - "type": "tuple[]", - "internalType": "struct IICS26RouterMsgs.Payload[]", - "components": [ - { - "name": "sourcePort", - "type": "string", - "internalType": "string" - }, - { - "name": "destPort", - "type": "string", - "internalType": "string" - }, - { - "name": "version", - "type": "string", - "internalType": "string" - }, - { - "name": "encoding", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "commitPacketAcknowledgement", - "inputs": [ - { - "name": "packet", - "type": "tuple", - "internalType": "struct IICS26RouterMsgs.Packet", - "components": [ - { - "name": "sequence", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "sourceClient", - "type": "string", - "internalType": "string" - }, - { - "name": "destClient", - "type": "string", - "internalType": "string" - }, - { - "name": "timeoutTimestamp", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "payloads", - "type": "tuple[]", - "internalType": "struct IICS26RouterMsgs.Payload[]", - "components": [ - { - "name": "sourcePort", - "type": "string", - "internalType": "string" - }, - { - "name": "destPort", - "type": "string", - "internalType": "string" - }, - { - "name": "version", - "type": "string", - "internalType": "string" - }, - { - "name": "encoding", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - } - ] - }, - { - "name": "acks", - "type": "bytes[]", - "internalType": "bytes[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "deletePacketCommitment", - "inputs": [ - { - "name": "packet", - "type": "tuple", - "internalType": "struct IICS26RouterMsgs.Packet", - "components": [ - { - "name": "sequence", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "sourceClient", - "type": "string", - "internalType": "string" - }, - { - "name": "destClient", - "type": "string", - "internalType": "string" - }, - { - "name": "timeoutTimestamp", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "payloads", - "type": "tuple[]", - "internalType": "struct IICS26RouterMsgs.Payload[]", - "components": [ - { - "name": "sourcePort", - "type": "string", - "internalType": "string" - }, - { - "name": "destPort", - "type": "string", - "internalType": "string" - }, - { - "name": "version", - "type": "string", - "internalType": "string" - }, - { - "name": "encoding", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - } - ] - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "getCommitment", - "inputs": [ - { - "name": "hashedPath", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "nextSequenceSend", - "inputs": [ - { - "name": "clientId", - "type": "string", - "internalType": "string" - } - ], - "outputs": [ - { - "name": "", - "type": "uint32", - "internalType": "uint32" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "renounceOwnership", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "setPacketReceipt", - "inputs": [ - { - "name": "packet", - "type": "tuple", - "internalType": "struct IICS26RouterMsgs.Packet", - "components": [ - { - "name": "sequence", - "type": "uint32", - "internalType": "uint32" - }, - { - "name": "sourceClient", - "type": "string", - "internalType": "string" - }, - { - "name": "destClient", - "type": "string", - "internalType": "string" - }, - { - "name": "timeoutTimestamp", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "payloads", - "type": "tuple[]", - "internalType": "struct IICS26RouterMsgs.Payload[]", - "components": [ - { - "name": "sourcePort", - "type": "string", - "internalType": "string" - }, - { - "name": "destPort", - "type": "string", - "internalType": "string" - }, - { - "name": "version", - "type": "string", - "internalType": "string" - }, - { - "name": "encoding", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "transferOwnership", - "inputs": [ - { - "name": "newOwner", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [ - { - "name": "previousOwner", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "IBCMultiPayloadPacketNotSupported", - "inputs": [] - }, - { - "type": "error", - "name": "IBCPacketAcknowledgementAlreadyExists", - "inputs": [ - { - "name": "path", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "IBCPacketCommitmentAlreadyExists", - "inputs": [ - { - "name": "path", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "IBCPacketCommitmentNotFound", - "inputs": [ - { - "name": "path", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "IBCPacketReceiptAlreadyExists", - "inputs": [ - { - "name": "path", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "InvalidMerklePrefix", - "inputs": [ - { - "name": "prefix", - "type": "bytes[]", - "internalType": "bytes[]" - } - ] - }, - { - "type": "error", - "name": "OwnableInvalidOwner", - "inputs": [ - { - "name": "owner", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "OwnableUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - } - ] - } -] diff --git a/abi/ICS26Router.json b/abi/ICS26Router.json index 1fa437eb7..162f36863 100644 --- a/abi/ICS26Router.json +++ b/abi/ICS26Router.json @@ -17,19 +17,6 @@ ], "stateMutability": "view" }, - { - "type": "function", - "name": "IBC_STORE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "contract IIBCStore" - } - ], - "stateMutability": "view" - }, { "type": "function", "name": "ackPacket", @@ -209,6 +196,25 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getCommitment", + "inputs": [ + { + "name": "hashedPath", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getCounterparty", @@ -1381,6 +1387,28 @@ "name": "IBCMultiPayloadPacketNotSupported", "inputs": [] }, + { + "type": "error", + "name": "IBCPacketAcknowledgementAlreadyExists", + "inputs": [ + { + "name": "path", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "type": "error", + "name": "IBCPacketCommitmentAlreadyExists", + "inputs": [ + { + "name": "path", + "type": "bytes", + "internalType": "bytes" + } + ] + }, { "type": "error", "name": "IBCPacketCommitmentMismatch", diff --git a/abigen/ibcstore/contract.go b/abigen/ibcstore/contract.go deleted file mode 100644 index f27d3fffc..000000000 --- a/abigen/ibcstore/contract.go +++ /dev/null @@ -1,561 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package ibcstore - -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 -) - -// IICS26RouterMsgsPacket is an auto generated low-level Go binding around an user-defined struct. -type IICS26RouterMsgsPacket struct { - Sequence uint32 - SourceClient string - DestClient string - TimeoutTimestamp uint64 - Payloads []IICS26RouterMsgsPayload -} - -// IICS26RouterMsgsPayload is an auto generated low-level Go binding around an user-defined struct. -type IICS26RouterMsgsPayload struct { - SourcePort string - DestPort string - Version string - Encoding string - Value []byte -} - -// ContractMetaData contains all meta data concerning the Contract contract. -var ContractMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"owner_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPacketAcknowledgement\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acks\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"deletePacketCommitment\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getCommitment\",\"inputs\":[{\"name\":\"hashedPath\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextSequenceSend\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setPacketReceipt\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"IBCMultiPayloadPacketNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCPacketAcknowledgementAlreadyExists\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"IBCPacketCommitmentAlreadyExists\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"IBCPacketCommitmentNotFound\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"IBCPacketReceiptAlreadyExists\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidMerklePrefix\",\"inputs\":[{\"name\":\"prefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", -} - -// ContractABI is the input ABI used to generate the binding from. -// Deprecated: Use ContractMetaData.ABI instead. -var ContractABI = ContractMetaData.ABI - -// Contract is an auto generated Go binding around an Ethereum contract. -type Contract struct { - ContractCaller // Read-only binding to the contract - ContractTransactor // Write-only binding to the contract - ContractFilterer // Log filterer for contract events -} - -// ContractCaller is an auto generated read-only Go binding around an Ethereum contract. -type ContractCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContractTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ContractTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ContractFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContractSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ContractSession struct { - Contract *Contract // 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 -} - -// ContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ContractCallerSession struct { - Contract *ContractCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ContractTransactorSession struct { - Contract *ContractTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ContractRaw is an auto generated low-level Go binding around an Ethereum contract. -type ContractRaw struct { - Contract *Contract // Generic contract binding to access the raw methods on -} - -// ContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ContractCallerRaw struct { - Contract *ContractCaller // Generic read-only contract binding to access the raw methods on -} - -// ContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ContractTransactorRaw struct { - Contract *ContractTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewContract creates a new instance of Contract, bound to a specific deployed contract. -func NewContract(address common.Address, backend bind.ContractBackend) (*Contract, error) { - contract, err := bindContract(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil -} - -// NewContractCaller creates a new read-only instance of Contract, bound to a specific deployed contract. -func NewContractCaller(address common.Address, caller bind.ContractCaller) (*ContractCaller, error) { - contract, err := bindContract(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ContractCaller{contract: contract}, nil -} - -// NewContractTransactor creates a new write-only instance of Contract, bound to a specific deployed contract. -func NewContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ContractTransactor, error) { - contract, err := bindContract(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ContractTransactor{contract: contract}, nil -} - -// NewContractFilterer creates a new log filterer instance of Contract, bound to a specific deployed contract. -func NewContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ContractFilterer, error) { - contract, err := bindContract(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ContractFilterer{contract: contract}, nil -} - -// bindContract binds a generic wrapper to an already deployed contract. -func bindContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ContractMetaData.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 (_Contract *ContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Contract.Contract.ContractCaller.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 (_Contract *ContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Contract.Contract.ContractTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Contract *ContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Contract.Contract.ContractTransactor.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 (_Contract *ContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Contract.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 (_Contract *ContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Contract.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Contract *ContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Contract.Contract.contract.Transact(opts, method, params...) -} - -// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. -// -// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) -func (_Contract *ContractCaller) GetCommitment(opts *bind.CallOpts, hashedPath [32]byte) ([32]byte, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "getCommitment", hashedPath) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. -// -// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) -func (_Contract *ContractSession) GetCommitment(hashedPath [32]byte) ([32]byte, error) { - return _Contract.Contract.GetCommitment(&_Contract.CallOpts, hashedPath) -} - -// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. -// -// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) -func (_Contract *ContractCallerSession) GetCommitment(hashedPath [32]byte) ([32]byte, error) { - return _Contract.Contract.GetCommitment(&_Contract.CallOpts, hashedPath) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Contract *ContractCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Contract.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 (_Contract *ContractSession) Owner() (common.Address, error) { - return _Contract.Contract.Owner(&_Contract.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Contract *ContractCallerSession) Owner() (common.Address, error) { - return _Contract.Contract.Owner(&_Contract.CallOpts) -} - -// CommitPacket is a paid mutator transaction binding the contract method 0xccac5fbd. -// -// Solidity: function commitPacket((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractTransactor) CommitPacket(opts *bind.TransactOpts, packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "commitPacket", packet) -} - -// CommitPacket is a paid mutator transaction binding the contract method 0xccac5fbd. -// -// Solidity: function commitPacket((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractSession) CommitPacket(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.CommitPacket(&_Contract.TransactOpts, packet) -} - -// CommitPacket is a paid mutator transaction binding the contract method 0xccac5fbd. -// -// Solidity: function commitPacket((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractTransactorSession) CommitPacket(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.CommitPacket(&_Contract.TransactOpts, packet) -} - -// CommitPacketAcknowledgement is a paid mutator transaction binding the contract method 0xc8e84932. -// -// Solidity: function commitPacketAcknowledgement((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet, bytes[] acks) returns() -func (_Contract *ContractTransactor) CommitPacketAcknowledgement(opts *bind.TransactOpts, packet IICS26RouterMsgsPacket, acks [][]byte) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "commitPacketAcknowledgement", packet, acks) -} - -// CommitPacketAcknowledgement is a paid mutator transaction binding the contract method 0xc8e84932. -// -// Solidity: function commitPacketAcknowledgement((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet, bytes[] acks) returns() -func (_Contract *ContractSession) CommitPacketAcknowledgement(packet IICS26RouterMsgsPacket, acks [][]byte) (*types.Transaction, error) { - return _Contract.Contract.CommitPacketAcknowledgement(&_Contract.TransactOpts, packet, acks) -} - -// CommitPacketAcknowledgement is a paid mutator transaction binding the contract method 0xc8e84932. -// -// Solidity: function commitPacketAcknowledgement((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet, bytes[] acks) returns() -func (_Contract *ContractTransactorSession) CommitPacketAcknowledgement(packet IICS26RouterMsgsPacket, acks [][]byte) (*types.Transaction, error) { - return _Contract.Contract.CommitPacketAcknowledgement(&_Contract.TransactOpts, packet, acks) -} - -// DeletePacketCommitment is a paid mutator transaction binding the contract method 0x20b870a9. -// -// Solidity: function deletePacketCommitment((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns(bytes32) -func (_Contract *ContractTransactor) DeletePacketCommitment(opts *bind.TransactOpts, packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "deletePacketCommitment", packet) -} - -// DeletePacketCommitment is a paid mutator transaction binding the contract method 0x20b870a9. -// -// Solidity: function deletePacketCommitment((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns(bytes32) -func (_Contract *ContractSession) DeletePacketCommitment(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.DeletePacketCommitment(&_Contract.TransactOpts, packet) -} - -// DeletePacketCommitment is a paid mutator transaction binding the contract method 0x20b870a9. -// -// Solidity: function deletePacketCommitment((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns(bytes32) -func (_Contract *ContractTransactorSession) DeletePacketCommitment(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.DeletePacketCommitment(&_Contract.TransactOpts, packet) -} - -// NextSequenceSend is a paid mutator transaction binding the contract method 0x676bd316. -// -// Solidity: function nextSequenceSend(string clientId) returns(uint32) -func (_Contract *ContractTransactor) NextSequenceSend(opts *bind.TransactOpts, clientId string) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "nextSequenceSend", clientId) -} - -// NextSequenceSend is a paid mutator transaction binding the contract method 0x676bd316. -// -// Solidity: function nextSequenceSend(string clientId) returns(uint32) -func (_Contract *ContractSession) NextSequenceSend(clientId string) (*types.Transaction, error) { - return _Contract.Contract.NextSequenceSend(&_Contract.TransactOpts, clientId) -} - -// NextSequenceSend is a paid mutator transaction binding the contract method 0x676bd316. -// -// Solidity: function nextSequenceSend(string clientId) returns(uint32) -func (_Contract *ContractTransactorSession) NextSequenceSend(clientId string) (*types.Transaction, error) { - return _Contract.Contract.NextSequenceSend(&_Contract.TransactOpts, clientId) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Contract *ContractTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Contract *ContractSession) RenounceOwnership() (*types.Transaction, error) { - return _Contract.Contract.RenounceOwnership(&_Contract.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Contract *ContractTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _Contract.Contract.RenounceOwnership(&_Contract.TransactOpts) -} - -// SetPacketReceipt is a paid mutator transaction binding the contract method 0x8fc969f0. -// -// Solidity: function setPacketReceipt((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractTransactor) SetPacketReceipt(opts *bind.TransactOpts, packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "setPacketReceipt", packet) -} - -// SetPacketReceipt is a paid mutator transaction binding the contract method 0x8fc969f0. -// -// Solidity: function setPacketReceipt((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractSession) SetPacketReceipt(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.SetPacketReceipt(&_Contract.TransactOpts, packet) -} - -// SetPacketReceipt is a paid mutator transaction binding the contract method 0x8fc969f0. -// -// Solidity: function setPacketReceipt((uint32,string,string,uint64,(string,string,string,string,bytes)[]) packet) returns() -func (_Contract *ContractTransactorSession) SetPacketReceipt(packet IICS26RouterMsgsPacket) (*types.Transaction, error) { - return _Contract.Contract.SetPacketReceipt(&_Contract.TransactOpts, packet) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Contract *ContractTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _Contract.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Contract *ContractSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Contract.Contract.TransferOwnership(&_Contract.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Contract *ContractTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Contract.Contract.TransferOwnership(&_Contract.TransactOpts, newOwner) -} - -// ContractOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Contract contract. -type ContractOwnershipTransferredIterator struct { - Event *ContractOwnershipTransferred // 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 *ContractOwnershipTransferredIterator) 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(ContractOwnershipTransferred) - 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(ContractOwnershipTransferred) - 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 *ContractOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ContractOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ContractOwnershipTransferred represents a OwnershipTransferred event raised by the Contract contract. -type ContractOwnershipTransferred 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 (_Contract *ContractFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ContractOwnershipTransferredIterator, 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 := _Contract.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &ContractOwnershipTransferredIterator{contract: _Contract.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 (_Contract *ContractFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ContractOwnershipTransferred, 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 := _Contract.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(ContractOwnershipTransferred) - if err := _Contract.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 (_Contract *ContractFilterer) ParseOwnershipTransferred(log types.Log) (*ContractOwnershipTransferred, error) { - event := new(ContractOwnershipTransferred) - if err := _Contract.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/abigen/ics26router/contract.go b/abigen/ics26router/contract.go index 0f741c449..e4db5eb65 100644 --- a/abigen/ics26router/contract.go +++ b/abigen/ics26router/contract.go @@ -90,7 +90,7 @@ type IICS26RouterMsgsPayload struct { // ContractMetaData contains all meta data concerning the Contract contract. var ContractMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"IBC_STORE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIIBCStore\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ackPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgAckPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofAcked\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addClient\",\"inputs\":[{\"name\":\"clientType\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterpartyInfo\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]},{\"name\":\"client\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addIBCApp\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"app\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractILightClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCounterparty\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getIBCApp\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIIBCApp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"portCustomizer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrateClient\",\"inputs\":[{\"name\":\"subjectClientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"substituteClientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"multicall\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[{\"name\":\"results\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"recvPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgRecvPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"proofCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgSendPacket\",\"components\":[{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitMisbehaviour\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"misbehaviourMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"timeoutPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgTimeoutPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"proofTimeout\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"updateMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumILightClientMsgs.UpdateResult\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"upgradeMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AckPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IBCAppAdded\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"app\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ICS02ClientAdded\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"counterpartyInfo\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Noop\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RecvPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SendPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TimeoutPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"WriteAcknowledgement\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgements\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCAppNotFound\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCAsyncAcknowledgementNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCClientNotFound\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCCounterpartyClientNotFound\",\"inputs\":[{\"name\":\"counterpartyClientId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidClientType\",\"inputs\":[{\"name\":\"clientType\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidCounterparty\",\"inputs\":[{\"name\":\"expected\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"actual\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidPortIdentifier\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidTimeoutDuration\",\"inputs\":[{\"name\":\"maxTimeoutDuration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualTimeoutDuration\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidTimeoutTimestamp\",\"inputs\":[{\"name\":\"timeoutTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"comparedTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IBCMultiPayloadPacketNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCPacketCommitmentMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"IBCPortAlreadyExists\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMerklePrefix\",\"inputs\":[{\"name\":\"prefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StringsInsufficientHexLength\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"Unreachable\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ackPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgAckPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofAcked\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addClient\",\"inputs\":[{\"name\":\"clientType\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterpartyInfo\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]},{\"name\":\"client\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addIBCApp\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"app\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractILightClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCommitment\",\"inputs\":[{\"name\":\"hashedPath\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCounterparty\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getIBCApp\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIIBCApp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"portCustomizer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrateClient\",\"inputs\":[{\"name\":\"subjectClientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"substituteClientId\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"multicall\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[{\"name\":\"results\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"recvPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgRecvPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"proofCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgSendPacket\",\"components\":[{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitMisbehaviour\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"misbehaviourMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"timeoutPacket\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.MsgTimeoutPacket\",\"components\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"proofTimeout\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"proofHeight\",\"type\":\"tuple\",\"internalType\":\"structIICS02ClientMsgs.Height\",\"components\":[{\"name\":\"revisionNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"revisionHeight\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"updateMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumILightClientMsgs.UpdateResult\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeClient\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"upgradeMsg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AckPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IBCAppAdded\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"app\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ICS02ClientAdded\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"counterpartyInfo\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS02ClientMsgs.CounterpartyInfo\",\"components\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"merklePrefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Noop\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RecvPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SendPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TimeoutPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"WriteAcknowledgement\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structIICS26RouterMsgs.Packet\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"sourceClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destClient\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payloads\",\"type\":\"tuple[]\",\"internalType\":\"structIICS26RouterMsgs.Payload[]\",\"components\":[{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"encoding\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"acknowledgements\",\"type\":\"bytes[]\",\"indexed\":false,\"internalType\":\"bytes[]\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCAppNotFound\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCAsyncAcknowledgementNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCClientNotFound\",\"inputs\":[{\"name\":\"clientId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCCounterpartyClientNotFound\",\"inputs\":[{\"name\":\"counterpartyClientId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidClientType\",\"inputs\":[{\"name\":\"clientType\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidCounterparty\",\"inputs\":[{\"name\":\"expected\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"actual\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidPortIdentifier\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidTimeoutDuration\",\"inputs\":[{\"name\":\"maxTimeoutDuration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualTimeoutDuration\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IBCInvalidTimeoutTimestamp\",\"inputs\":[{\"name\":\"timeoutTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"comparedTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"IBCMultiPayloadPacketNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IBCPacketAcknowledgementAlreadyExists\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"IBCPacketCommitmentAlreadyExists\",\"inputs\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"IBCPacketCommitmentMismatch\",\"inputs\":[{\"name\":\"expected\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"actual\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"IBCPortAlreadyExists\",\"inputs\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMerklePrefix\",\"inputs\":[{\"name\":\"prefix\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StringsInsufficientHexLength\",\"inputs\":[{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"Unreachable\",\"inputs\":[]}]", } // ContractABI is the input ABI used to generate the binding from. @@ -270,12 +270,12 @@ func (_Contract *ContractCallerSession) DEFAULTADMINROLE() ([32]byte, error) { return _Contract.Contract.DEFAULTADMINROLE(&_Contract.CallOpts) } -// IBCSTORE is a free data retrieval call binding the contract method 0xb23a8009. +// GetClient is a free data retrieval call binding the contract method 0x7eb78932. // -// Solidity: function IBC_STORE() view returns(address) -func (_Contract *ContractCaller) IBCSTORE(opts *bind.CallOpts) (common.Address, error) { +// Solidity: function getClient(string clientId) view returns(address) +func (_Contract *ContractCaller) GetClient(opts *bind.CallOpts, clientId string) (common.Address, error) { var out []interface{} - err := _Contract.contract.Call(opts, &out, "IBC_STORE") + err := _Contract.contract.Call(opts, &out, "getClient", clientId) if err != nil { return *new(common.Address), err @@ -287,49 +287,49 @@ func (_Contract *ContractCaller) IBCSTORE(opts *bind.CallOpts) (common.Address, } -// IBCSTORE is a free data retrieval call binding the contract method 0xb23a8009. +// GetClient is a free data retrieval call binding the contract method 0x7eb78932. // -// Solidity: function IBC_STORE() view returns(address) -func (_Contract *ContractSession) IBCSTORE() (common.Address, error) { - return _Contract.Contract.IBCSTORE(&_Contract.CallOpts) +// Solidity: function getClient(string clientId) view returns(address) +func (_Contract *ContractSession) GetClient(clientId string) (common.Address, error) { + return _Contract.Contract.GetClient(&_Contract.CallOpts, clientId) } -// IBCSTORE is a free data retrieval call binding the contract method 0xb23a8009. +// GetClient is a free data retrieval call binding the contract method 0x7eb78932. // -// Solidity: function IBC_STORE() view returns(address) -func (_Contract *ContractCallerSession) IBCSTORE() (common.Address, error) { - return _Contract.Contract.IBCSTORE(&_Contract.CallOpts) +// Solidity: function getClient(string clientId) view returns(address) +func (_Contract *ContractCallerSession) GetClient(clientId string) (common.Address, error) { + return _Contract.Contract.GetClient(&_Contract.CallOpts, clientId) } -// GetClient is a free data retrieval call binding the contract method 0x7eb78932. +// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. // -// Solidity: function getClient(string clientId) view returns(address) -func (_Contract *ContractCaller) GetClient(opts *bind.CallOpts, clientId string) (common.Address, error) { +// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) +func (_Contract *ContractCaller) GetCommitment(opts *bind.CallOpts, hashedPath [32]byte) ([32]byte, error) { var out []interface{} - err := _Contract.contract.Call(opts, &out, "getClient", clientId) + err := _Contract.contract.Call(opts, &out, "getCommitment", hashedPath) if err != nil { - return *new(common.Address), err + return *new([32]byte), err } - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -// GetClient is a free data retrieval call binding the contract method 0x7eb78932. +// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. // -// Solidity: function getClient(string clientId) view returns(address) -func (_Contract *ContractSession) GetClient(clientId string) (common.Address, error) { - return _Contract.Contract.GetClient(&_Contract.CallOpts, clientId) +// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) +func (_Contract *ContractSession) GetCommitment(hashedPath [32]byte) ([32]byte, error) { + return _Contract.Contract.GetCommitment(&_Contract.CallOpts, hashedPath) } -// GetClient is a free data retrieval call binding the contract method 0x7eb78932. +// GetCommitment is a free data retrieval call binding the contract method 0x7795820c. // -// Solidity: function getClient(string clientId) view returns(address) -func (_Contract *ContractCallerSession) GetClient(clientId string) (common.Address, error) { - return _Contract.Contract.GetClient(&_Contract.CallOpts, clientId) +// Solidity: function getCommitment(bytes32 hashedPath) view returns(bytes32) +func (_Contract *ContractCallerSession) GetCommitment(hashedPath [32]byte) ([32]byte, error) { + return _Contract.Contract.GetCommitment(&_Contract.CallOpts, hashedPath) } // GetCounterparty is a free data retrieval call binding the contract method 0xb0777bfa. diff --git a/abigen/ics26router/store.go b/abigen/ics26router/store.go new file mode 100644 index 000000000..b588f80b0 --- /dev/null +++ b/abigen/ics26router/store.go @@ -0,0 +1,4 @@ +package ics26router + +// IbcStoreStorageSlot is the storage slot for the IBC store +const IbcStoreStorageSlot = "0x1260944489272988d9df285149b5aa1b0f48f2136d6f416159f840a3e0747600" diff --git a/contracts/ICS20Transfer.sol b/contracts/ICS20Transfer.sol index d5e9ffcca..2b88ab5b4 100644 --- a/contracts/ICS20Transfer.sol +++ b/contracts/ICS20Transfer.sol @@ -32,8 +32,8 @@ contract ICS20Transfer is MulticallUpgradeable { /// @notice Storage of the ICS20Transfer contract - /// @dev It's implemented on a custom ERC-7201 namespace to reduce the - /// @dev risk of storage collisions when using with upgradeable contracts. + /// @dev It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions when using with + /// upgradeable contracts. /// @param escrow The escrow contract /// @param ibcDenomContracts Mapping of non-native denoms to their respective IBCERC20 contracts /// @param ics26Router The ICS26Router contract diff --git a/contracts/ICS26Router.sol b/contracts/ICS26Router.sol index 61606dc06..f90697f14 100644 --- a/contracts/ICS26Router.sol +++ b/contracts/ICS26Router.sol @@ -3,9 +3,7 @@ pragma solidity ^0.8.28; import { IIBCApp } from "./interfaces/IIBCApp.sol"; import { IICS26Router } from "./interfaces/IICS26Router.sol"; -import { IIBCStore } from "./interfaces/IIBCStore.sol"; -import { IICS24HostErrors } from "./errors/IICS24HostErrors.sol"; -import { IBCStore } from "./utils/IBCStore.sol"; +import { IBCStoreUpgradeable } from "./utils/IBCStoreUpgradeable.sol"; import { IICS26RouterErrors } from "./errors/IICS26RouterErrors.sol"; import { Strings } from "@openzeppelin-contracts/utils/Strings.sol"; import { IBCIdentifiers } from "./utils/IBCIdentifiers.sol"; @@ -23,19 +21,18 @@ contract ICS26Router is IICS26Router, IICS26RouterErrors, ICS02ClientUpgradeable, + IBCStoreUpgradeable, ReentrancyGuardTransientUpgradeable, MulticallUpgradeable { /// @notice Storage of the ICS26Router contract - /// @dev It's implemented on a custom ERC-7201 namespace to reduce the - /// @dev risk of storage collisions when using with upgradeable contracts. + /// @dev It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions when using with + /// upgradeable contracts. /// @param apps The mapping of port identifiers to IBC application contracts - /// @param ibcStore The IBC store contract /// @param ics02Client The ICS02Client contract /// @custom:storage-location erc7201:ibc.storage.ICS26Router struct ICS26RouterStorage { mapping(string => IIBCApp) apps; - IIBCStore ibcStore; } /// @notice ERC-7201 slot for the ICS26Router storage @@ -63,17 +60,9 @@ contract ICS26Router is __ReentrancyGuardTransient_init(); __Multicall_init(); __ICS02Client_init(); + __IBCStoreUpgradeable_init(); _grantRole(PORT_CUSTOMIZER_ROLE, portCustomizer); - - ICS26RouterStorage storage $ = _getICS26RouterStorage(); - - $.ibcStore = new IBCStore(address(this)); // using this contract as the owner - } - - /// @inheritdoc IICS26Router - function IBC_STORE() external view returns (IIBCStore) { - return _getICS26RouterStorage().ibcStore; } /// @notice Returns the address of the IBC application given the port identifier @@ -119,8 +108,6 @@ contract ICS26Router is require(msg_.payloads.length == 1, IBCMultiPayloadPacketNotSupported()); Payload calldata payload = msg_.payloads[0]; - ICS26RouterStorage storage $ = _getICS26RouterStorage(); - string memory counterpartyId = getCounterparty(msg_.sourceClient).clientId; // TODO: validate all identifiers @@ -132,7 +119,7 @@ contract ICS26Router is IBCInvalidTimeoutDuration(MAX_TIMEOUT_DURATION, msg_.timeoutTimestamp - block.timestamp) ); - uint32 sequence = $.ibcStore.nextSequenceSend(msg_.sourceClient); + uint32 sequence = nextSequenceSend(msg_.sourceClient); Packet memory packet = Packet({ sequence: sequence, @@ -152,7 +139,7 @@ contract ICS26Router is }) ); - $.ibcStore.commitPacket(packet); + commitPacket(packet); emit SendPacket(packet); return sequence; @@ -166,8 +153,6 @@ contract ICS26Router is require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported()); Payload calldata payload = msg_.packet.payloads[0]; - ICS26RouterStorage storage $ = _getICS26RouterStorage(); - CounterpartyInfo memory cInfo = getCounterparty(msg_.packet.destClient); require( keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.sourceClient)), @@ -194,9 +179,10 @@ contract ICS26Router is // recvPacket will no-op if the packet receipt already exists // solhint-disable-next-line no-empty-blocks - try $.ibcStore.setPacketReceipt(msg_.packet) { } - catch (bytes memory reason) { - return noopOnCorrectReason(reason, IICS24HostErrors.IBCPacketReceiptAlreadyExists.selector); + bool isReceiptSet = setPacketReceipt(msg_.packet); + if (!isReceiptSet) { + emit Noop(); + return; } bytes[] memory acks = new bytes[](1); @@ -224,8 +210,6 @@ contract ICS26Router is require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported()); Payload calldata payload = msg_.packet.payloads[0]; - ICS26RouterStorage storage $ = _getICS26RouterStorage(); - CounterpartyInfo memory cInfo = getCounterparty(msg_.packet.sourceClient); require( keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.destClient)), @@ -249,14 +233,15 @@ contract ICS26Router is getClient(msg_.packet.sourceClient).membership(membershipMsg); // ackPacket will no-op if the packet commitment does not exist - try $.ibcStore.deletePacketCommitment(msg_.packet) returns (bytes32 storedCommitment) { - require( - storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet), - IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet)) - ); - } catch (bytes memory reason) { - return noopOnCorrectReason(reason, IICS24HostErrors.IBCPacketCommitmentNotFound.selector); + (bool isDeleted, bytes32 storedCommitment) = deletePacketCommitment(msg_.packet); + if (!isDeleted) { + emit Noop(); + return; } + require( + storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet), + IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet)) + ); getIBCApp(payload.sourcePort).onAcknowledgementPacket( IIBCAppCallbacks.OnAcknowledgementPacketCallback({ @@ -280,8 +265,6 @@ contract ICS26Router is require(msg_.packet.payloads.length == 1, IBCMultiPayloadPacketNotSupported()); Payload calldata payload = msg_.packet.payloads[0]; - ICS26RouterStorage storage $ = _getICS26RouterStorage(); - CounterpartyInfo memory cInfo = getCounterparty(msg_.packet.sourceClient); require( keccak256(bytes(cInfo.clientId)) == keccak256(bytes(msg_.packet.destClient)), @@ -304,14 +287,15 @@ contract ICS26Router is ); // timeoutPacket will no-op if the packet commitment does not exist - try $.ibcStore.deletePacketCommitment(msg_.packet) returns (bytes32 storedCommitment) { - require( - storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet), - IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet)) - ); - } catch (bytes memory reason) { - return noopOnCorrectReason(reason, IICS24HostErrors.IBCPacketCommitmentNotFound.selector); + (bool isDeleted, bytes32 storedCommitment) = deletePacketCommitment(msg_.packet); + if (!isDeleted) { + emit Noop(); + return; } + require( + storedCommitment == ICS24Host.packetCommitmentBytes32(msg_.packet), + IBCPacketCommitmentMismatch(storedCommitment, ICS24Host.packetCommitmentBytes32(msg_.packet)) + ); getIBCApp(payload.sourcePort).onTimeoutPacket( IIBCAppCallbacks.OnTimeoutPacketCallback({ @@ -330,26 +314,10 @@ contract ICS26Router is /// @param packet The packet to acknowledge /// @param acks The acknowledgement function writeAcknowledgement(Packet calldata packet, bytes[] memory acks) private { - _getICS26RouterStorage().ibcStore.commitPacketAcknowledgement(packet, acks); + commitPacketAcknowledgement(packet, acks); emit WriteAcknowledgement(packet, acks); } - /// @notice No-op if the reason is correct, otherwise reverts with the same reason - /// @dev Only to be used in catch blocks - /// @param reason The reason to check - /// @param correctReason The correct reason - function noopOnCorrectReason(bytes memory reason, bytes4 correctReason) private { - if (bytes4(reason) == correctReason) { - emit Noop(); - } else { - // reverts with the same reason - // solhint-disable-next-line no-inline-assembly - assembly ("memory-safe") { - revert(add(reason, 32), mload(reason)) - } - } - } - /// @notice Returns the storage of the ICS26Router contract function _getICS26RouterStorage() private pure returns (ICS26RouterStorage storage $) { // solhint-disable-next-line no-inline-assembly diff --git a/contracts/errors/IICS24HostErrors.sol b/contracts/errors/IICS24HostErrors.sol index cf57e3bdd..a57337ce6 100644 --- a/contracts/errors/IICS24HostErrors.sol +++ b/contracts/errors/IICS24HostErrors.sol @@ -2,18 +2,10 @@ pragma solidity ^0.8.28; interface IICS24HostErrors { - /// @notice Packet commitment not found - /// @param path commitment path - error IBCPacketCommitmentNotFound(bytes path); - /// @notice Packet commitment already exists /// @param path commitment path error IBCPacketCommitmentAlreadyExists(bytes path); - /// @notice Packet receipt already exists - /// @param path commitment path - error IBCPacketReceiptAlreadyExists(bytes path); - /// @notice Packet acknowledgement already exists /// @param path commitment path error IBCPacketAcknowledgementAlreadyExists(bytes path); diff --git a/contracts/errors/IICS26RouterErrors.sol b/contracts/errors/IICS26RouterErrors.sol index 59faeeb6a..7763fba50 100644 --- a/contracts/errors/IICS26RouterErrors.sol +++ b/contracts/errors/IICS26RouterErrors.sol @@ -36,7 +36,4 @@ interface IICS26RouterErrors { /// @notice IBC app for port not found /// @param portId port identifier error IBCAppNotFound(string portId); - - /// @notice Multi-payload packets are not supported - error IBCMultiPayloadPacketNotSupported(); } diff --git a/contracts/interfaces/IIBCStore.sol b/contracts/interfaces/IIBCStore.sol index 2fda8c6b9..8ce6f6bb0 100644 --- a/contracts/interfaces/IIBCStore.sol +++ b/contracts/interfaces/IIBCStore.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -import { IICS26RouterMsgs } from "../msgs/IICS26RouterMsgs.sol"; - /// @title IBC Store Interface /// @dev Non-view functions can only be called by owner. interface IIBCStore { @@ -10,30 +8,4 @@ interface IIBCStore { /// @param hashedPath The hashed path to get the commitment for. /// @return The commitment for the given path. function getCommitment(bytes32 hashedPath) external view returns (bytes32); - - /// @notice Gets and increments the next sequence to send for a given channel. - /// @param channelId The channel identifier. - /// @return The next sequence to send. - function nextSequenceSend(string calldata channelId) external returns (uint32); - - /// @notice Commits a packet - /// @param packet The packet to commit - /// @custom:spec - /// https://github.com/cosmos/ibc-go/blob/2b40562bcd59ce820ddd7d6732940728487cf94e/ - /// modules/core/04-channel/types/packet.go#L38 - function commitPacket(IICS26RouterMsgs.Packet memory packet) external; - - /// @notice Deletes a packet commitment and reverts if it does not exist - /// @param packet The packet whose commitment to delete - /// @return The deleted packet commitment - function deletePacketCommitment(IICS26RouterMsgs.Packet memory packet) external returns (bytes32); - - /// @notice Sets a packet receipt - /// @param packet The packet to set the receipt for - function setPacketReceipt(IICS26RouterMsgs.Packet memory packet) external; - - /// @notice Commits a packet acknowledgement - /// @param packet The packet to commit the acknowledgement for - /// @param acks The list of acknowledgements (one for each payload) to commit - function commitPacketAcknowledgement(IICS26RouterMsgs.Packet memory packet, bytes[] memory acks) external; } diff --git a/contracts/interfaces/IICS26Router.sol b/contracts/interfaces/IICS26Router.sol index c4f2d1952..affa1ec62 100644 --- a/contracts/interfaces/IICS26Router.sol +++ b/contracts/interfaces/IICS26Router.sol @@ -3,15 +3,10 @@ pragma solidity ^0.8.28; import { IICS26RouterMsgs } from "../msgs/IICS26RouterMsgs.sol"; import { IIBCApp } from "./IIBCApp.sol"; -import { IIBCStore } from "./IIBCStore.sol"; /// @title ICS26 Router Interface /// @notice IICS26Router is an interface for the IBC Eureka router interface IICS26Router is IICS26RouterMsgs { - /// @notice Returns the IBC storage contract - /// @return The address of the IBC stotage contract - function IBC_STORE() external view returns (IIBCStore); - /// @notice Returns the address of the IBC application given the port identifier /// @param portId The port identifier /// @return The address of the IBC application contract diff --git a/contracts/utils/IBCStore.sol b/contracts/utils/IBCStore.sol deleted file mode 100644 index 697546e17..000000000 --- a/contracts/utils/IBCStore.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.28; - -import { IIBCStore } from "../interfaces/IIBCStore.sol"; -import { IICS26RouterMsgs } from "../msgs/IICS26RouterMsgs.sol"; -import { ICS24Host } from "./ICS24Host.sol"; -import { IICS24HostErrors } from "../errors/IICS24HostErrors.sol"; -import { Ownable } from "@openzeppelin-contracts/access/Ownable.sol"; - -contract IBCStore is IIBCStore, IICS24HostErrors, Ownable { - /// @notice all IBC commitments - /// @dev keccak256(IBC-compatible-store-path) => sha256(IBC-compatible-commitment) - mapping(bytes32 hashedPath => bytes32 commitment) internal commitments; - - /// @notice Previous sequence send for a given port and client pair - /// @dev (portId, clientId) => prevSeqSend - mapping(string clientId => uint32 prevSeqSend) private prevSequenceSends; - - /// @param owner_ The owner of the contract - /// @dev Owner is to be the ICS26Router contract - constructor(address owner_) Ownable(owner_) { } - - /// @inheritdoc IIBCStore - function getCommitment(bytes32 hashedPath) public view returns (bytes32) { - return commitments[hashedPath]; - } - - /// @inheritdoc IIBCStore - function nextSequenceSend(string calldata clientId) public onlyOwner returns (uint32) { - uint32 seq = prevSequenceSends[clientId] + 1; - prevSequenceSends[clientId] = seq; - return seq; - } - - /// @inheritdoc IIBCStore - function commitPacket(IICS26RouterMsgs.Packet memory packet) public onlyOwner { - bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - require( - commitments[path] == 0, - IBCPacketCommitmentAlreadyExists( - ICS24Host.packetCommitmentPathCalldata(packet.sourceClient, packet.sequence) - ) - ); - - bytes32 commitment = ICS24Host.packetCommitmentBytes32(packet); - commitments[path] = commitment; - } - - /// @inheritdoc IIBCStore - function deletePacketCommitment(IICS26RouterMsgs.Packet memory packet) public onlyOwner returns (bytes32) { - bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 commitment = commitments[path]; - require( - commitment != 0, - IBCPacketCommitmentNotFound(ICS24Host.packetCommitmentPathCalldata(packet.sourceClient, packet.sequence)) - ); - - delete commitments[path]; - return commitment; - } - - /// @inheritdoc IIBCStore - function setPacketReceipt(IICS26RouterMsgs.Packet memory packet) public onlyOwner { - bytes32 path = ICS24Host.packetReceiptCommitmentKeyCalldata(packet.destClient, packet.sequence); - require( - commitments[path] == 0, - IBCPacketReceiptAlreadyExists( - ICS24Host.packetReceiptCommitmentPathCalldata(packet.destClient, packet.sequence) - ) - ); - - commitments[path] = ICS24Host.PACKET_RECEIPT_SUCCESSFUL_KECCAK256; - } - - /// @inheritdoc IIBCStore - function commitPacketAcknowledgement(IICS26RouterMsgs.Packet memory packet, bytes[] memory acks) public onlyOwner { - bytes32 path = ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destClient, packet.sequence); - require( - commitments[path] == 0, - IBCPacketAcknowledgementAlreadyExists( - ICS24Host.packetAcknowledgementCommitmentPathCalldata(packet.destClient, packet.sequence) - ) - ); - - bytes32 commitment = ICS24Host.packetAcknowledgementCommitmentBytes32(acks); - commitments[path] = commitment; - } -} diff --git a/contracts/utils/IBCStoreUpgradeable.sol b/contracts/utils/IBCStoreUpgradeable.sol new file mode 100644 index 000000000..9e0ae82c8 --- /dev/null +++ b/contracts/utils/IBCStoreUpgradeable.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import { IIBCStore } from "../interfaces/IIBCStore.sol"; +import { IICS26RouterMsgs } from "../msgs/IICS26RouterMsgs.sol"; +import { ICS24Host } from "./ICS24Host.sol"; +import { IICS24HostErrors } from "../errors/IICS24HostErrors.sol"; +import { Initializable } from "@openzeppelin-upgradeable/proxy/utils/Initializable.sol"; + +abstract contract IBCStoreUpgradeable is IIBCStore, IICS24HostErrors, Initializable { + /// @notice Storage of the IBCStore contract + /// @dev It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions when using with + /// upgradeable contracts. + /// @param commitments Mapping of all IBC commitments + /// @param prevSequenceSends Mapping of previous sequence sends for each client + struct IBCStoreStorage { + // keccak256(IBC-compatible-store-path) => sha256(IBC-compatible-commitment) + mapping(bytes32 hashedPath => bytes32 commitment) commitments; + mapping(string clientId => uint32 prevSeqSend) prevSequenceSends; + } + + /// @notice ERC-7201 slot for the IBCStore storage + /// @dev keccak256(abi.encode(uint256(keccak256("ibc.storage.IBCStore")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant IBCSTORE_STORAGE_SLOT = 0x1260944489272988d9df285149b5aa1b0f48f2136d6f416159f840a3e0747600; + + // no need to run any initialization logic + // solhint-disable-next-line no-empty-blocks + function __IBCStoreUpgradeable_init() internal onlyInitializing { } + + /// @inheritdoc IIBCStore + function getCommitment(bytes32 hashedPath) public view returns (bytes32) { + return _getIBCStoreStorage().commitments[hashedPath]; + } + + function nextSequenceSend(string calldata clientId) internal returns (uint32) { + IBCStoreStorage storage $ = _getIBCStoreStorage(); + + uint32 seq = $.prevSequenceSends[clientId] + 1; + $.prevSequenceSends[clientId] = seq; + return seq; + } + + function commitPacket(IICS26RouterMsgs.Packet memory packet) internal { + IBCStoreStorage storage $ = _getIBCStoreStorage(); + + bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); + require( + $.commitments[path] == 0, + IBCPacketCommitmentAlreadyExists( + ICS24Host.packetCommitmentPathCalldata(packet.sourceClient, packet.sequence) + ) + ); + + bytes32 commitment = ICS24Host.packetCommitmentBytes32(packet); + $.commitments[path] = commitment; + } + + /// @notice Deletes the packet commitment for the given packet if it exists + /// @param packet Packet to delete the commitment for + /// @return True if the packet commitment was deleted, false otherwise + function deletePacketCommitment(IICS26RouterMsgs.Packet memory packet) internal returns (bool, bytes32) { + IBCStoreStorage storage $ = _getIBCStoreStorage(); + + bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); + bytes32 commitment = $.commitments[path]; + if (commitment == 0) { + return (false, 0); + } + + delete $.commitments[path]; + return (true, commitment); + } + + /// @notice Sets the packet receipt for the given packet if it doesn't already exist + /// @param packet Packet to set the receipt for + /// @return True if the packet receipt was set, false otherwise + function setPacketReceipt(IICS26RouterMsgs.Packet memory packet) internal returns (bool) { + IBCStoreStorage storage $ = _getIBCStoreStorage(); + + bytes32 path = ICS24Host.packetReceiptCommitmentKeyCalldata(packet.destClient, packet.sequence); + if ($.commitments[path] != 0) { + return false; + } + + $.commitments[path] = ICS24Host.PACKET_RECEIPT_SUCCESSFUL_KECCAK256; + return true; + } + + function commitPacketAcknowledgement(IICS26RouterMsgs.Packet memory packet, bytes[] memory acks) internal { + IBCStoreStorage storage $ = _getIBCStoreStorage(); + + bytes32 path = ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destClient, packet.sequence); + require( + $.commitments[path] == 0, + IBCPacketAcknowledgementAlreadyExists( + ICS24Host.packetAcknowledgementCommitmentPathCalldata(packet.destClient, packet.sequence) + ) + ); + + bytes32 commitment = ICS24Host.packetAcknowledgementCommitmentBytes32(acks); + $.commitments[path] = commitment; + } + + /// @notice Returns the storage of the IBCStore contract + function _getIBCStoreStorage() private pure returns (IBCStoreStorage storage $) { + // solhint-disable-next-line no-inline-assembly + assembly { + $.slot := IBCSTORE_STORAGE_SLOT + } + } +} diff --git a/e2e/interchaintestv8/e2esuite/light_clients.go b/e2e/interchaintestv8/e2esuite/light_clients.go index 5849d7eaa..724810cc3 100644 --- a/e2e/interchaintestv8/e2esuite/light_clients.go +++ b/e2e/interchaintestv8/e2esuite/light_clients.go @@ -17,6 +17,8 @@ import ( "github.com/strangelove-ventures/interchaintest/v9/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v9/ibc" + "github.com/cosmos/solidity-ibc-eureka/abigen/ics26router" + "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues" ethereumtypes "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types/ethereum" ) @@ -86,7 +88,7 @@ func (s *TestSuite) createEthereumLightClient( clientStateAny, err := clienttypes.PackClientState(&clientState) s.Require().NoError(err) - proofOfIBCContract, err := eth.EthAPI.GetProof(ibcContractAddress, []string{}, executionNumberHex) + proofOfIBCContract, err := eth.EthAPI.GetProof(ibcContractAddress, []string{ics26router.IbcStoreStorageSlot}, executionNumberHex) s.Require().NoError(err) header, err := eth.BeaconAPIClient.GetHeader(strconv.Itoa(int(executionHeight))) diff --git a/e2e/interchaintestv8/ethereum/utils.go b/e2e/interchaintestv8/ethereum/utils.go index a0c6780af..2a66f5474 100644 --- a/e2e/interchaintestv8/ethereum/utils.go +++ b/e2e/interchaintestv8/ethereum/utils.go @@ -28,7 +28,6 @@ type DeployedContracts struct { Ics20Transfer string `json:"ics20Transfer"` Erc20 string `json:"erc20"` Escrow string `json:"escrow"` - IbcStore string `json:"ibcstore"` } func GetEthContractsFromDeployOutput(stdout string) (DeployedContracts, error) { @@ -54,8 +53,7 @@ func GetEthContractsFromDeployOutput(stdout string) (DeployedContracts, error) { embeddedContracts.Ics07Tendermint == "" || embeddedContracts.Ics20Transfer == "" || embeddedContracts.Ics26Router == "" || - embeddedContracts.Escrow == "" || - embeddedContracts.IbcStore == "" { + embeddedContracts.Escrow == "" { return DeployedContracts{}, fmt.Errorf("one or more contracts missing: %+v", embeddedContracts) } diff --git a/e2e/interchaintestv8/ibc_eureka_test.go b/e2e/interchaintestv8/ibc_eureka_test.go index 0278755a9..801eee4d3 100644 --- a/e2e/interchaintestv8/ibc_eureka_test.go +++ b/e2e/interchaintestv8/ibc_eureka_test.go @@ -34,7 +34,6 @@ import ( "github.com/strangelove-ventures/interchaintest/v9/ibc" "github.com/cosmos/solidity-ibc-eureka/abigen/ibcerc20" - "github.com/cosmos/solidity-ibc-eureka/abigen/ibcstore" "github.com/cosmos/solidity-ibc-eureka/abigen/ics20lib" "github.com/cosmos/solidity-ibc-eureka/abigen/ics20transfer" "github.com/cosmos/solidity-ibc-eureka/abigen/ics26router" @@ -69,7 +68,6 @@ type IbcEurekaTestSuite struct { ics26Contract *ics26router.Contract ics20Contract *ics20transfer.Contract erc20Contract *erc20.Contract - ibcStoreContract *ibcstore.Contract escrowContractAddr ethcommon.Address EthToCosmosRelayerClient relayertypes.RelayerServiceClient @@ -178,8 +176,6 @@ func (s *IbcEurekaTestSuite) SetupSuite(ctx context.Context, proofType operator. s.erc20Contract, err = erc20.NewContract(ethcommon.HexToAddress(s.contractAddresses.Erc20), eth.RPCClient) s.Require().NoError(err) s.escrowContractAddr = ethcommon.HexToAddress(s.contractAddresses.Escrow) - s.ibcStoreContract, err = ibcstore.NewContract(ethcommon.HexToAddress(s.contractAddresses.IbcStore), eth.RPCClient) - s.Require().NoError(err) })) s.T().Cleanup(func() { @@ -195,7 +191,7 @@ func (s *IbcEurekaTestSuite) SetupSuite(ctx context.Context, proofType operator. })) s.Require().True(s.Run("Add ethereum light client on Cosmos chain", func() { - s.CreateEthereumLightClient(ctx, simd, s.SimdRelayerSubmitter, s.contractAddresses.IbcStore) + s.CreateEthereumLightClient(ctx, simd, s.SimdRelayerSubmitter, s.contractAddresses.Ics26Router) })) s.Require().True(s.Run("Add client and counterparty on EVM", func() { @@ -1016,7 +1012,7 @@ func (s *IbcEurekaTestSuite) ICS20TransferNativeCosmosCoinsToEthereumAndBackTest var ethPath [32]byte copy(ethPath[:], crypto.Keccak256(packetCommitmentPath)) - resp, err := s.ibcStoreContract.GetCommitment(nil, ethPath) + resp, err := s.ics26Contract.GetCommitment(nil, ethPath) s.Require().NoError(err) s.Require().NotZero(resp) })) @@ -1049,7 +1045,7 @@ func (s *IbcEurekaTestSuite) ICS20TransferNativeCosmosCoinsToEthereumAndBackTest var ethPath [32]byte copy(ethPath[:], crypto.Keccak256(packetCommitmentPath)) - resp, err := s.ibcStoreContract.GetCommitment(nil, ethPath) + resp, err := s.ics26Contract.GetCommitment(nil, ethPath) s.Require().NoError(err) s.Require().Zero(resp) })) @@ -1263,79 +1259,80 @@ func (s *IbcEurekaTestSuite) ICS20ErrorAckToEthereumTest( s.Require().NoError(err) s.Require().Equal(transferAmount, escrowBalance) })) + })) - var ( - denomOnCosmos transfertypes.Denom - ackTxHash []byte - ) - s.Require().True(s.Run("Receive packets on Cosmos chain", func() { - var relayTxBodyBz []byte - s.Require().True(s.Run("Retrieve relay tx", func() { - resp, err := s.EthToCosmosRelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{ - SourceTxIds: [][]byte{ethSendTxHash}, - TargetClientId: testvalues.FirstWasmClientID, - }) - s.Require().NoError(err) - s.Require().NotEmpty(resp.Tx) - s.Require().Empty(resp.Address) + var ( + denomOnCosmos transfertypes.Denom + ackTxHash []byte + ) + s.Require().True(s.Run("Receive packets on Cosmos chain", func() { + var relayTxBodyBz []byte + s.Require().True(s.Run("Retrieve relay tx", func() { + resp, err := s.EthToCosmosRelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{ + SourceTxIds: [][]byte{ethSendTxHash}, + TargetClientId: testvalues.FirstWasmClientID, + }) + s.Require().NoError(err) + s.Require().NotEmpty(resp.Tx) + s.Require().Empty(resp.Address) - relayTxBodyBz = resp.Tx - })) + relayTxBodyBz = resp.Tx + })) - s.Require().True(s.Run("Broadcast relay tx", func() { - resp := s.BroadcastSdkTxBody(ctx, simd, s.SimdRelayerSubmitter, 2_000_000, relayTxBodyBz) + s.Require().True(s.Run("Broadcast relay tx", func() { + resp := s.BroadcastSdkTxBody(ctx, simd, s.SimdRelayerSubmitter, 2_000_000, relayTxBodyBz) - ackTxHash, err = hex.DecodeString(resp.TxHash) - s.Require().NoError(err) - s.Require().NotEmpty(ackTxHash) - })) + var err error + ackTxHash, err = hex.DecodeString(resp.TxHash) + s.Require().NoError(err) + s.Require().NotEmpty(ackTxHash) + })) - s.Require().True(s.Run("Verify no balance on Cosmos chain", func() { - denomOnCosmos = transfertypes.NewDenom(s.contractAddresses.Erc20, transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID)) + s.Require().True(s.Run("Verify no balance on Cosmos chain", func() { + denomOnCosmos = transfertypes.NewDenom(s.contractAddresses.Erc20, transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID)) - _, err := e2esuite.GRPCQuery[banktypes.QueryBalanceResponse](ctx, simd, &banktypes.QueryBalanceRequest{ - Address: ibctesting.InvalidID, - Denom: denomOnCosmos.IBCDenom(), - }) - s.Require().Error(err) - })) + _, err := e2esuite.GRPCQuery[banktypes.QueryBalanceResponse](ctx, simd, &banktypes.QueryBalanceRequest{ + Address: ibctesting.InvalidID, + Denom: denomOnCosmos.IBCDenom(), + }) + s.Require().Error(err) })) + })) - s.Require().True(s.Run("Acknowledge packets on Ethereum", func() { - var ackRelayTx []byte - s.Require().True(s.Run("Retrieve relay tx", func() { - resp, err := s.CosmosToEthRelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{ - SourceTxIds: [][]byte{ackTxHash}, - TargetClientId: ibctesting.FirstClientID, - }) - s.Require().NoError(err) - s.Require().NotEmpty(resp.Tx) - s.Require().Equal(resp.Address, ics26Address.String()) + s.Require().True(s.Run("Acknowledge packets on Ethereum", func() { + var ackRelayTx []byte + s.Require().True(s.Run("Retrieve relay tx", func() { + resp, err := s.CosmosToEthRelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{ + SourceTxIds: [][]byte{ackTxHash}, + TargetClientId: ibctesting.FirstClientID, + }) + s.Require().NoError(err) + s.Require().NotEmpty(resp.Tx) + s.Require().Equal(resp.Address, ics26Address.String()) - ackRelayTx = resp.Tx - })) + ackRelayTx = resp.Tx + })) - s.Require().True(s.Run("Submit relay tx", func() { - receipt, err := eth.BroadcastTx(ctx, s.EthRelayerSubmitter, 5_000_000, ics26Address, ackRelayTx) - s.Require().NoError(err) - s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status) + s.Require().True(s.Run("Submit relay tx", func() { + receipt, err := eth.BroadcastTx(ctx, s.EthRelayerSubmitter, 5_000_000, ics26Address, ackRelayTx) + s.Require().NoError(err) + s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status) - // Verify the ack packet event exists - _, err = e2esuite.GetEvmEvent(receipt, s.ics26Contract.ParseAckPacket) - s.Require().NoError(err) - })) + // Verify the ack packet event exists + _, err = e2esuite.GetEvmEvent(receipt, s.ics26Contract.ParseAckPacket) + s.Require().NoError(err) + })) - s.Require().True(s.Run("Verify balances on Ethereum", func() { - // User balance on Ethereum - userBalance, err := s.erc20Contract.BalanceOf(nil, ethereumUserAddress) - s.Require().NoError(err) - s.Require().Equal(testvalues.StartingERC20Balance, userBalance) + s.Require().True(s.Run("Verify balances on Ethereum", func() { + // User balance on Ethereum + userBalance, err := s.erc20Contract.BalanceOf(nil, ethereumUserAddress) + s.Require().NoError(err) + s.Require().Equal(testvalues.StartingERC20Balance, userBalance) - // ICS20 contract balance on Ethereum - escrowBalance, err := s.erc20Contract.BalanceOf(nil, s.escrowContractAddr) - s.Require().NoError(err) - s.Require().Zero(escrowBalance.Int64()) - })) + // ICS20 contract balance on Ethereum + escrowBalance, err := s.erc20Contract.BalanceOf(nil, s.escrowContractAddr) + s.Require().NoError(err) + s.Require().Zero(escrowBalance.Int64()) })) })) } diff --git a/e2e/interchaintestv8/multichain_test.go b/e2e/interchaintestv8/multichain_test.go index 580438788..b0701c257 100644 --- a/e2e/interchaintestv8/multichain_test.go +++ b/e2e/interchaintestv8/multichain_test.go @@ -36,7 +36,6 @@ import ( "github.com/strangelove-ventures/interchaintest/v9/ibc" "github.com/cosmos/solidity-ibc-eureka/abigen/ibcerc20" - "github.com/cosmos/solidity-ibc-eureka/abigen/ibcstore" "github.com/cosmos/solidity-ibc-eureka/abigen/ics20lib" "github.com/cosmos/solidity-ibc-eureka/abigen/ics20transfer" "github.com/cosmos/solidity-ibc-eureka/abigen/ics26router" @@ -68,7 +67,6 @@ type MultichainTestSuite struct { ics26Contract *ics26router.Contract ics20Contract *ics20transfer.Contract erc20Contract *erc20.Contract - ibcStoreContract *ibcstore.Contract escrowContractAddr ethcommon.Address EthToChainARelayerClient relayertypes.RelayerServiceClient @@ -181,8 +179,6 @@ func (s *MultichainTestSuite) SetupSuite(ctx context.Context, proofType operator s.erc20Contract, err = erc20.NewContract(ethcommon.HexToAddress(s.contractAddresses.Erc20), eth.RPCClient) s.Require().NoError(err) s.escrowContractAddr = ethcommon.HexToAddress(s.contractAddresses.Escrow) - s.ibcStoreContract, err = ibcstore.NewContract(ethcommon.HexToAddress(s.contractAddresses.IbcStore), eth.RPCClient) - s.Require().NoError(err) })) s.Require().True(s.Run("Deploy SimdB light client on ethereum", func() { @@ -235,7 +231,7 @@ func (s *MultichainTestSuite) SetupSuite(ctx context.Context, proofType operator })) s.Require().True(s.Run("Add ethereum light client on SimdA", func() { - s.CreateEthereumLightClient(ctx, simdA, s.SimdARelayerSubmitter, s.contractAddresses.IbcStore) + s.CreateEthereumLightClient(ctx, simdA, s.SimdARelayerSubmitter, s.contractAddresses.Ics26Router) })) s.Require().True(s.Run("Add simdA client and counterparty on EVM", func() { @@ -257,7 +253,7 @@ func (s *MultichainTestSuite) SetupSuite(ctx context.Context, proofType operator })) s.Require().True(s.Run("Add ethereum light client on SimdB", func() { - s.CreateEthereumLightClient(ctx, simdB, s.SimdBRelayerSubmitter, s.contractAddresses.IbcStore) + s.CreateEthereumLightClient(ctx, simdB, s.SimdBRelayerSubmitter, s.contractAddresses.Ics26Router) })) s.Require().True(s.Run("Add simdB client and counterparty on EVM", func() { diff --git a/e2e/interchaintestv8/testvalues/values.go b/e2e/interchaintestv8/testvalues/values.go index 377deaaef..824273c7e 100644 --- a/e2e/interchaintestv8/testvalues/values.go +++ b/e2e/interchaintestv8/testvalues/values.go @@ -13,6 +13,8 @@ import ( ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" "github.com/strangelove-ventures/interchaintest/v9/chain/ethereum" + + "github.com/cosmos/solidity-ibc-eureka/abigen/ics26router" ) const ( @@ -87,7 +89,7 @@ const ( DefaultGovV1ProposalTokenAmount = 500_000_000 // IbcCommitmentSlotHex is the storage slot in the IBC solidity contract for the IBC commitments. - IbcCommitmentSlotHex = "0x1" + IbcCommitmentSlotHex = ics26router.IbcStoreStorageSlot // FirstWasmClientID is the first wasm client ID. Used for testing. FirstWasmClientID = "08-wasm-0" diff --git a/justfile b/justfile index a63252cb4..8c09d9e40 100644 --- a/justfile +++ b/justfile @@ -68,11 +68,9 @@ generate-abi: build-contracts jq '.abi' ./out/SP1ICS07Tendermint.sol/SP1ICS07Tendermint.json > abi/SP1ICS07Tendermint.json jq '.abi' out/ERC20.sol/ERC20.json > abi/ERC20.json jq '.abi' out/IBCERC20.sol/IBCERC20.json > abi/IBCERC20.json - jq '.abi' out/IBCStore.sol/IBCStore.json > abi/IBCStore.json jq '.abi' out/ICS20Lib.sol/ICS20Lib.json > abi/ICS20Lib.json abigen --abi abi/ERC20.json --pkg erc20 --type Contract --out e2e/interchaintestv8/types/erc20/contract.go abigen --abi abi/SP1ICS07Tendermint.json --pkg sp1ics07tendermint --type Contract --out abigen/sp1ics07tendermint/contract.go - abigen --abi abi/IBCStore.json --pkg ibcstore --type Contract --out abigen/ibcstore/contract.go abigen --abi abi/ICS20Transfer.json --pkg ics20transfer --type Contract --out abigen/ics20transfer/contract.go abigen --abi abi/ICS26Router.json --pkg ics26router --type Contract --out abigen/ics26router/contract.go abigen --abi abi/IBCERC20.json --pkg ibcerc20 --type Contract --out abigen/ibcerc20/contract.go diff --git a/packages/solidity/src/ibc_store.rs b/packages/solidity/src/ibc_store.rs deleted file mode 100644 index c850449d0..000000000 --- a/packages/solidity/src/ibc_store.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Solidity types for IBC Store - -#[cfg(feature = "rpc")] -alloy_sol_types::sol!( - #[sol(rpc)] - #[derive(Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq)] - store, - "../../abi/IBCStore.json" -); - -// NOTE: Some environments won't compile with the `rpc` features. -#[cfg(not(feature = "rpc"))] -alloy_sol_types::sol!( - #[derive(Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq)] - #[allow(missing_docs, clippy::pedantic)] - store, - "../../abi/IBCStore.json" -); diff --git a/packages/solidity/src/lib.rs b/packages/solidity/src/lib.rs index 491a1e2aa..bb19ca2ae 100644 --- a/packages/solidity/src/lib.rs +++ b/packages/solidity/src/lib.rs @@ -2,6 +2,5 @@ #![deny(clippy::nursery, clippy::pedantic, warnings)] -pub mod ibc_store; pub mod ics26; pub mod sp1_ics07; diff --git a/scripts/E2ETestDeploy.s.sol b/scripts/E2ETestDeploy.s.sol index 45e39e3d9..8b854aca5 100644 --- a/scripts/E2ETestDeploy.s.sol +++ b/scripts/E2ETestDeploy.s.sol @@ -120,7 +120,6 @@ contract E2ETestDeploy is Script, IICS07TendermintMsgs { json.serialize("ics26Router", Strings.toHexString(address(ics26Router))); json.serialize("ics20Transfer", Strings.toHexString(address(ics20Transfer))); json.serialize("escrow", Strings.toHexString(ics20Transfer.escrow())); - json.serialize("ibcstore", Strings.toHexString(address(ics26Router.IBC_STORE()))); string memory finalJson = json.serialize("erc20", Strings.toHexString(address(erc20))); return finalJson; diff --git a/test/solidity-ibc/BenchmarkTest.t.sol b/test/solidity-ibc/BenchmarkTest.t.sol index 16a671b55..c0522ae5d 100644 --- a/test/solidity-ibc/BenchmarkTest.t.sol +++ b/test/solidity-ibc/BenchmarkTest.t.sol @@ -58,7 +58,7 @@ contract BenchmarkTest is FixtureTest { // ack should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(ackFixture.packet.sourceClient, ackFixture.packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); // Step 3: Cosmos has sent the tokens back and commited a packet, which we will now prove and receive @@ -71,7 +71,7 @@ contract BenchmarkTest is FixtureTest { assertTrue(success); // ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata( recvFixture.packet.destClient, recvFixture.packet.sequence ) @@ -94,7 +94,7 @@ contract BenchmarkTest is FixtureTest { console.log("Multicall native recv gas used: ", vm.lastCallGas().gasTotalUsed); assertTrue(success); - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata( recvNativeFixture.packet.destClient, recvNativeFixture.packet.sequence ) @@ -127,7 +127,7 @@ contract BenchmarkTest is FixtureTest { // ack should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(timeoutFixture.packet.sourceClient, timeoutFixture.packet.sequence); - assertEq(ics26Router.IBC_STORE().getCommitment(path), 0); + assertEq(ics26Router.getCommitment(path), 0); } function sendTransfer(Fixture memory fixture) internal returns (uint64) { @@ -162,7 +162,7 @@ contract BenchmarkTest is FixtureTest { uint64 gasUsed = vm.lastCallGas().gasTotalUsed; bytes32 path = ICS24Host.packetCommitmentKeyCalldata(fixture.packet.sourceClient, fixture.packet.sequence); - assertEq(ics26Router.IBC_STORE().getCommitment(path), ICS24Host.packetCommitmentBytes32(fixture.packet)); + assertEq(ics26Router.getCommitment(path), ICS24Host.packetCommitmentBytes32(fixture.packet)); return gasUsed; } diff --git a/test/solidity-ibc/IntegrationTest.t.sol b/test/solidity-ibc/IntegrationTest.t.sol index 937cc4a51..87fc46e86 100644 --- a/test/solidity-ibc/IntegrationTest.t.sol +++ b/test/solidity-ibc/IntegrationTest.t.sol @@ -10,12 +10,10 @@ import { IICS20TransferMsgs } from "../../contracts/msgs/IICS20TransferMsgs.sol" import { TestERC20 } from "./mocks/TestERC20.sol"; import { IBCERC20 } from "../../contracts/utils/IBCERC20.sol"; import { IICS26Router } from "../../contracts/interfaces/IICS26Router.sol"; -import { IIBCStore } from "../../contracts/interfaces/IIBCStore.sol"; import { IICS26RouterErrors } from "../../contracts/errors/IICS26RouterErrors.sol"; import { ICS26Router } from "../../contracts/ICS26Router.sol"; import { IICS26RouterMsgs } from "../../contracts/msgs/IICS26RouterMsgs.sol"; import { DummyLightClient } from "./mocks/DummyLightClient.sol"; -import { ErroneousIBCStore } from "./mocks/ErroneousIBCStore.sol"; import { ILightClientMsgs } from "../../contracts/msgs/ILightClientMsgs.sol"; import { ICS20Lib } from "../../contracts/utils/ICS20Lib.sol"; import { ICS24Host } from "../../contracts/utils/ICS24Host.sol"; @@ -104,7 +102,7 @@ contract IntegrationTest is Test { ics26Router.ackPacket(ackMsg); // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); uint256 senderBalanceAfter = erc20.balanceOf(sender); @@ -162,7 +160,7 @@ contract IntegrationTest is Test { }); bytes32 path = ICS24Host.packetCommitmentKeyCalldata(transferMsg.sourceClient, sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, ICS24Host.packetCommitmentBytes32(packet)); IICS26RouterMsgs.MsgAckPacket memory ackMsg = IICS26RouterMsgs.MsgAckPacket({ @@ -175,7 +173,7 @@ contract IntegrationTest is Test { ics26Router.ackPacket(ackMsg); // commitment should be deleted - storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); uint256 senderBalanceAfter = erc20.balanceOf(sender); @@ -216,7 +214,7 @@ contract IntegrationTest is Test { ics26Router.ackPacket(ackMsg); // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); // transfer should be reverted @@ -238,7 +236,7 @@ contract IntegrationTest is Test { ics26Router.ackPacket(ackMsg); // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); // call ack again, should be noop @@ -247,33 +245,6 @@ contract IntegrationTest is Test { ics26Router.ackPacket(ackMsg); } - // This test case tests the scenario where IBCStore.deletePacketCommitment fails with custom error - function test_failure_ackNoop() public { - IICS26RouterMsgs.Packet memory packet = _sendICS20TransferPacket(); - - IICS26RouterMsgs.MsgAckPacket memory ackMsg = IICS26RouterMsgs.MsgAckPacket({ - packet: packet, - acknowledgement: ICS20Lib.FAILED_ACKNOWLEDGEMENT_JSON, - proofAcked: bytes("doesntmatter"), // dummy client will accept - proofHeight: IICS02ClientMsgs.Height({ revisionNumber: 1, revisionHeight: 42 }) // dummy client will accept - }); - ics26Router.ackPacket(ackMsg); - // commitment should be deleted - bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); - assertEq(storedCommitment, 0); - - // override IBCStore to ErroneousIBCStore - vm.mockFunction( - address(ics26Router.IBC_STORE()), - address(new ErroneousIBCStore()), - abi.encodeWithSelector(IIBCStore.deletePacketCommitment.selector) - ); - // call ack again, should throw CallFailure - vm.expectRevert(abi.encodeWithSelector(ErroneousIBCStore.CallFailure.selector, "deletePacketCommitment")); - ics26Router.ackPacket(ackMsg); - } - function test_success_timeoutICS20Packet() public { IICS26RouterMsgs.Packet memory packet = _sendICS20TransferPacket(); @@ -289,7 +260,7 @@ contract IntegrationTest is Test { ics26Router.timeoutPacket(timeoutMsg); // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); // transfer should be reverted @@ -313,7 +284,7 @@ contract IntegrationTest is Test { ics26Router.timeoutPacket(timeoutMsg); // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); // call timeout again, should be noop @@ -322,35 +293,6 @@ contract IntegrationTest is Test { ics26Router.timeoutPacket(timeoutMsg); } - // This test case tests the scenario where IBCStore.deletePacketCommitment fails with custom error - function test_failure_timeoutNoop() public { - IICS26RouterMsgs.Packet memory packet = _sendICS20TransferPacket(); - - // make light client return timestamp that is after our timeout - lightClient.setMembershipResult(packet.timeoutTimestamp + 1, false); - - IICS26RouterMsgs.MsgTimeoutPacket memory timeoutMsg = IICS26RouterMsgs.MsgTimeoutPacket({ - packet: packet, - proofTimeout: bytes("doesntmatter"), // dummy client will accept - proofHeight: IICS02ClientMsgs.Height({ revisionNumber: 1, revisionHeight: 42 }) // dummy client will accept - }); - ics26Router.timeoutPacket(timeoutMsg); - // commitment should be deleted - bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); - assertEq(storedCommitment, 0); - - // override IBCStore to ErroneousIBCStore - vm.mockFunction( - address(ics26Router.IBC_STORE()), - address(new ErroneousIBCStore()), - abi.encodeWithSelector(IIBCStore.deletePacketCommitment.selector) - ); - // call timeout again, should throw CallFailure - vm.expectRevert(abi.encodeWithSelector(ErroneousIBCStore.CallFailure.selector, "deletePacketCommitment")); - ics26Router.timeoutPacket(timeoutMsg); - } - function test_success_receiveICS20PacketWithSourceDenom() public { IICS26RouterMsgs.Packet memory packet = _sendICS20TransferPacket(); @@ -365,7 +307,7 @@ contract IntegrationTest is Test { // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); uint256 senderBalanceAfterSend = erc20.balanceOf(sender); @@ -419,7 +361,7 @@ contract IntegrationTest is Test { assertEq(erc20.balanceOf(ics20Transfer.escrow()), 0); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destClient, packet.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -439,7 +381,7 @@ contract IntegrationTest is Test { // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); uint256 senderBalanceAfterSend = erc20.balanceOf(sender); @@ -484,7 +426,7 @@ contract IntegrationTest is Test { ics26Router.recvPacket(msgRecvPacket); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destClient, packet.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -495,82 +437,6 @@ contract IntegrationTest is Test { ics26Router.recvPacket(msgRecvPacket); } - // This test case tests the scenario where IBCStore.setPacketReceipt fails with custom error - function test_failure_recvNoop() public { - IICS26RouterMsgs.Packet memory packet = _sendICS20TransferPacket(); - - IICS26RouterMsgs.MsgAckPacket memory ackMsg = IICS26RouterMsgs.MsgAckPacket({ - packet: packet, - acknowledgement: ICS20Lib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON, - proofAcked: bytes("doesntmatter"), // dummy client will accept - proofHeight: IICS02ClientMsgs.Height({ revisionNumber: 1, revisionHeight: 42 }) // dummy client will accept - }); - - ics26Router.ackPacket(ackMsg); - - // commitment should be deleted - bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); - assertEq(storedCommitment, 0); - - uint256 senderBalanceAfterSend = erc20.balanceOf(sender); - uint256 contractBalanceAfterSend = erc20.balanceOf(ics20Transfer.escrow()); - assertEq(senderBalanceAfterSend, 0); - assertEq(contractBalanceAfterSend, transferAmount); - - // Return the tokens (receive) - receiverStr = senderStr; - receiver = sender; - senderStr = "cosmos1mhmwgrfrcrdex5gnr0vcqt90wknunsxej63feh"; - string memory receivedDenom = string(abi.encodePacked("transfer/", counterpartyId, "/", erc20AddressStr)); - - ICS20Lib.FungibleTokenPacketData memory receivePacketData = ICS20Lib.FungibleTokenPacketData({ - denom: receivedDenom, - sender: senderStr, - receiver: receiverStr, - amount: transferAmount, - memo: "backmemo" - }); - IICS26RouterMsgs.Payload[] memory payloads = new IICS26RouterMsgs.Payload[](1); - payloads[0] = IICS26RouterMsgs.Payload({ - sourcePort: ICS20Lib.DEFAULT_PORT_ID, - destPort: ICS20Lib.DEFAULT_PORT_ID, - version: ICS20Lib.ICS20_VERSION, - encoding: ICS20Lib.ICS20_ENCODING, - value: abi.encode(receivePacketData) - }); - packet = IICS26RouterMsgs.Packet({ - sequence: 1, - sourceClient: counterpartyId, - destClient: clientIdentifier, - timeoutTimestamp: packet.timeoutTimestamp + 1000, - payloads: payloads - }); - - IICS26RouterMsgs.MsgRecvPacket memory msgRecvPacket = IICS26RouterMsgs.MsgRecvPacket({ - packet: packet, - proofCommitment: bytes("doesntmatter"), // dummy client will accept - proofHeight: IICS02ClientMsgs.Height({ revisionNumber: 1, revisionHeight: 42 }) // will accept - }); - ics26Router.recvPacket(msgRecvPacket); - - // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( - ICS24Host.packetAcknowledgementCommitmentKeyCalldata(packet.destClient, packet.sequence) - ); - assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); - - // override IBCStore to ErroneousIBCStore - vm.mockFunction( - address(ics26Router.IBC_STORE()), - address(new ErroneousIBCStore()), - abi.encodeWithSelector(IIBCStore.setPacketReceipt.selector) - ); - // call recv again, should throw CallFailure - vm.expectRevert(abi.encodeWithSelector(ErroneousIBCStore.CallFailure.selector, "setPacketReceipt")); - ics26Router.recvPacket(msgRecvPacket); - } - function test_success_receiveICS20PacketWithForeignBaseDenom() public { string memory foreignDenom = "uatom"; @@ -619,7 +485,7 @@ contract IntegrationTest is Test { ); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(receivePacket.destClient, receivePacket.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -698,7 +564,7 @@ contract IntegrationTest is Test { bytes32 path = ICS24Host.packetCommitmentKeyCalldata(expectedPacketSent.sourceClient, expectedPacketSent.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, ICS24Host.packetCommitmentBytes32(expectedPacketSent)); } @@ -771,11 +637,11 @@ contract IntegrationTest is Test { ics26Router.multicall(multicallData); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(receivePacket.destClient, receivePacket.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); - bytes32 storedAck2 = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck2 = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(receivePacket2.destClient, receivePacket2.sequence) ); assertEq(storedAck2, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -900,7 +766,7 @@ contract IntegrationTest is Test { ); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(receivePacket.destClient, receivePacket.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -982,7 +848,7 @@ contract IntegrationTest is Test { bytes32 path = ICS24Host.packetCommitmentKeyCalldata(expectedPacketSent.sourceClient, expectedPacketSent.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, ICS24Host.packetCommitmentBytes32(expectedPacketSent)); } @@ -1034,7 +900,7 @@ contract IntegrationTest is Test { ); // Check that the ack is written - bytes32 storedAck = ics26Router.IBC_STORE().getCommitment( + bytes32 storedAck = ics26Router.getCommitment( ICS24Host.packetAcknowledgementCommitmentKeyCalldata(receivePacket.destClient, receivePacket.sequence) ); assertEq(storedAck, ICS24Host.packetAcknowledgementCommitmentBytes32(singleSuccessAck)); @@ -1116,7 +982,7 @@ contract IntegrationTest is Test { bytes32 path = ICS24Host.packetCommitmentKeyCalldata(expectedPacketSent.sourceClient, expectedPacketSent.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, ICS24Host.packetCommitmentBytes32(expectedPacketSent)); } @@ -1134,7 +1000,7 @@ contract IntegrationTest is Test { // commitment should be deleted bytes32 path = ICS24Host.packetCommitmentKeyCalldata(packet.sourceClient, packet.sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, 0); uint256 senderBalanceAfterSend = erc20.balanceOf(sender); @@ -1229,7 +1095,7 @@ contract IntegrationTest is Test { }); bytes32 path = ICS24Host.packetCommitmentKeyCalldata(msgSendPacket.sourceClient, sequence); - bytes32 storedCommitment = ics26Router.IBC_STORE().getCommitment(path); + bytes32 storedCommitment = ics26Router.getCommitment(path); assertEq(storedCommitment, ICS24Host.packetCommitmentBytes32(packet)); return packet; diff --git a/test/solidity-ibc/mocks/ErroneousIBCStore.sol b/test/solidity-ibc/mocks/ErroneousIBCStore.sol deleted file mode 100644 index cc43e5045..000000000 --- a/test/solidity-ibc/mocks/ErroneousIBCStore.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.28; - -// solhint-disable no-empty-blocks - -import { IIBCStore } from "../../../contracts/interfaces/IIBCStore.sol"; -import { IICS26RouterMsgs } from "../../../contracts/msgs/IICS26RouterMsgs.sol"; - -/// @title Erroneous IBC Store -/// @dev This contract is used to override some functions of the IBC store contract using cheatcodes -contract ErroneousIBCStore is IIBCStore { - error CallFailure(string reason); - - constructor() { } - - function getCommitment(bytes32) external pure returns (bytes32) { - revert CallFailure("getCommitment"); - } - - function nextSequenceSend(string calldata) external pure returns (uint32) { - revert CallFailure("nextSequenceSend"); - } - - function commitPacket(IICS26RouterMsgs.Packet memory) external pure { - revert CallFailure("commitPacket"); - } - - function deletePacketCommitment(IICS26RouterMsgs.Packet memory) external pure returns (bytes32) { - revert CallFailure("deletePacketCommitment"); - } - - function setPacketReceipt(IICS26RouterMsgs.Packet memory) external pure { - revert CallFailure("setPacketReceipt"); - } - - function commitPacketAcknowledgement(IICS26RouterMsgs.Packet memory, bytes[] memory) external pure { - revert CallFailure("commitPacketAcknowledgement"); - } -}