From 833cb85ad294f771fc025864668971581eeeb45a Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Mon, 9 Oct 2023 22:58:33 +0900 Subject: [PATCH 1/6] add IBCMockApp for testing Signed-off-by: Jun Kimura --- contracts/apps/mock/IBCMockApp.sol | 59 ++++ contracts/apps/mock/IBCMockLib.sol | 11 + pkg/contract/ibcmockapp/ibcmockapp.go | 446 ++++++++++++++++++++++++++ pkg/testing/chains.go | 7 + pkg/testing/config.go | 5 + scripts/abigen.sh | 1 + tests/foundry/src/Deploy.s.sol | 7 +- 7 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 contracts/apps/mock/IBCMockApp.sol create mode 100644 contracts/apps/mock/IBCMockLib.sol create mode 100644 pkg/contract/ibcmockapp/ibcmockapp.go diff --git a/contracts/apps/mock/IBCMockApp.sol b/contracts/apps/mock/IBCMockApp.sol new file mode 100644 index 00000000..daec4578 --- /dev/null +++ b/contracts/apps/mock/IBCMockApp.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.9; + +import "../commons/IBCAppBase.sol"; +import "../../core/05-port/IIBCModule.sol"; +import "../../core/25-handler/IBCHandler.sol"; +import "./IBCMockLib.sol"; + +contract IBCMockApp is IBCAppBase { + IBCHandler ibcHandler; + + constructor(IBCHandler ibcHandler_) { + ibcHandler = ibcHandler_; + } + + function ibcAddress() public view virtual override returns (address) { + return address(ibcHandler); + } + + function sendPacket( + string calldata message, + string calldata sourcePort, + string calldata sourceChannel, + Height.Data calldata timeoutHeight, + uint64 timeoutTimestamp + ) external { + ibcHandler.sendPacket(sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, bytes(message)); + } + + function onRecvPacket(Packet.Data calldata packet, address) + external + override + onlyIBC + returns (bytes memory acknowledgement) + { + if (keccak256(packet.data) == keccak256(IBCMockLib.MOCK_PACKET_DATA)) { + return IBCMockLib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON; + } else if (keccak256(packet.data) == keccak256(IBCMockLib.MOCK_ASYNC_PACKET_DATA)) { + return bytes(""); + } else { + return IBCMockLib.FAILED_ACKNOWLEDGEMENT_JSON; + } + } + + function onAcknowledgementPacket(Packet.Data calldata packet, bytes calldata acknowledgement, address) + external + virtual + override + onlyIBC + { + if (keccak256(packet.data) == keccak256(IBCMockLib.MOCK_PACKET_DATA)) { + require(keccak256(acknowledgement) == keccak256(IBCMockLib.SUCCESSFUL_ACKNOWLEDGEMENT_JSON)); + } else if (keccak256(packet.data) == keccak256(IBCMockLib.MOCK_ASYNC_PACKET_DATA)) { + require(acknowledgement.length == 0); + } else { + require(keccak256(acknowledgement) == keccak256(IBCMockLib.FAILED_ACKNOWLEDGEMENT_JSON)); + } + } +} diff --git a/contracts/apps/mock/IBCMockLib.sol b/contracts/apps/mock/IBCMockLib.sol new file mode 100644 index 00000000..26403fb6 --- /dev/null +++ b/contracts/apps/mock/IBCMockLib.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.9; + +library IBCMockLib { + bytes constant MOCK_PACKET_DATA = bytes("mock packet data"); + bytes constant MOCK_FAIL_PACKET_DATA = bytes("mock failed packet data"); + bytes constant MOCK_ASYNC_PACKET_DATA = bytes("mock async packet data"); + + bytes public constant SUCCESSFUL_ACKNOWLEDGEMENT_JSON = bytes('{"result":"bW9jayBhY2tub3dsZWRnZW1lbnQ="}'); + bytes public constant FAILED_ACKNOWLEDGEMENT_JSON = bytes('{"error":"mock failed acknowledgement"}'); +} diff --git a/pkg/contract/ibcmockapp/ibcmockapp.go b/pkg/contract/ibcmockapp/ibcmockapp.go new file mode 100644 index 00000000..9317a164 --- /dev/null +++ b/pkg/contract/ibcmockapp/ibcmockapp.go @@ -0,0 +1,446 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ibcmockapp + +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 +) + +// ChannelCounterpartyData is an auto generated low-level Go binding around an user-defined struct. +type ChannelCounterpartyData struct { + PortId string + ChannelId string +} + +// HeightData is an auto generated low-level Go binding around an user-defined struct. +type HeightData struct { + RevisionNumber uint64 + RevisionHeight uint64 +} + +// PacketData is an auto generated low-level Go binding around an user-defined struct. +type PacketData struct { + Sequence uint64 + SourcePort string + SourceChannel string + DestinationPort string + DestinationChannel string + Data []byte + TimeoutHeight HeightData + TimeoutTimestamp uint64 +} + +// IbcmockappMetaData contains all meta data concerning the Ibcmockapp contract. +var IbcmockappMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBCHandler\",\"name\":\"ibcHandler_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ibcAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"onAcknowledgementPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"onChanCloseConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"onChanCloseInit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"counterpartyVersion\",\"type\":\"string\"}],\"name\":\"onChanOpenAck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"onChanOpenConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enumChannel.Order\",\"name\":\"\",\"type\":\"uint8\"},{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"onChanOpenInit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enumChannel.Order\",\"name\":\"\",\"type\":\"uint8\"},{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"onChanOpenTry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"onRecvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"onTimeoutPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"sourcePort\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"sourceChannel\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeoutHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeoutTimestamp\",\"type\":\"uint64\"}],\"name\":\"sendPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IbcmockappABI is the input ABI used to generate the binding from. +// Deprecated: Use IbcmockappMetaData.ABI instead. +var IbcmockappABI = IbcmockappMetaData.ABI + +// Ibcmockapp is an auto generated Go binding around an Ethereum contract. +type Ibcmockapp struct { + IbcmockappCaller // Read-only binding to the contract + IbcmockappTransactor // Write-only binding to the contract + IbcmockappFilterer // Log filterer for contract events +} + +// IbcmockappCaller is an auto generated read-only Go binding around an Ethereum contract. +type IbcmockappCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IbcmockappTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IbcmockappTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IbcmockappFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IbcmockappFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IbcmockappSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IbcmockappSession struct { + Contract *Ibcmockapp // 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 +} + +// IbcmockappCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IbcmockappCallerSession struct { + Contract *IbcmockappCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IbcmockappTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IbcmockappTransactorSession struct { + Contract *IbcmockappTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IbcmockappRaw is an auto generated low-level Go binding around an Ethereum contract. +type IbcmockappRaw struct { + Contract *Ibcmockapp // Generic contract binding to access the raw methods on +} + +// IbcmockappCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IbcmockappCallerRaw struct { + Contract *IbcmockappCaller // Generic read-only contract binding to access the raw methods on +} + +// IbcmockappTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IbcmockappTransactorRaw struct { + Contract *IbcmockappTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIbcmockapp creates a new instance of Ibcmockapp, bound to a specific deployed contract. +func NewIbcmockapp(address common.Address, backend bind.ContractBackend) (*Ibcmockapp, error) { + contract, err := bindIbcmockapp(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Ibcmockapp{IbcmockappCaller: IbcmockappCaller{contract: contract}, IbcmockappTransactor: IbcmockappTransactor{contract: contract}, IbcmockappFilterer: IbcmockappFilterer{contract: contract}}, nil +} + +// NewIbcmockappCaller creates a new read-only instance of Ibcmockapp, bound to a specific deployed contract. +func NewIbcmockappCaller(address common.Address, caller bind.ContractCaller) (*IbcmockappCaller, error) { + contract, err := bindIbcmockapp(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IbcmockappCaller{contract: contract}, nil +} + +// NewIbcmockappTransactor creates a new write-only instance of Ibcmockapp, bound to a specific deployed contract. +func NewIbcmockappTransactor(address common.Address, transactor bind.ContractTransactor) (*IbcmockappTransactor, error) { + contract, err := bindIbcmockapp(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IbcmockappTransactor{contract: contract}, nil +} + +// NewIbcmockappFilterer creates a new log filterer instance of Ibcmockapp, bound to a specific deployed contract. +func NewIbcmockappFilterer(address common.Address, filterer bind.ContractFilterer) (*IbcmockappFilterer, error) { + contract, err := bindIbcmockapp(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IbcmockappFilterer{contract: contract}, nil +} + +// bindIbcmockapp binds a generic wrapper to an already deployed contract. +func bindIbcmockapp(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IbcmockappMetaData.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 (_Ibcmockapp *IbcmockappRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ibcmockapp.Contract.IbcmockappCaller.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 (_Ibcmockapp *IbcmockappRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ibcmockapp.Contract.IbcmockappTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ibcmockapp *IbcmockappRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ibcmockapp.Contract.IbcmockappTransactor.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 (_Ibcmockapp *IbcmockappCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Ibcmockapp.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 (_Ibcmockapp *IbcmockappTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Ibcmockapp.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Ibcmockapp *IbcmockappTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Ibcmockapp.Contract.contract.Transact(opts, method, params...) +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ibcmockapp *IbcmockappCaller) IbcAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Ibcmockapp.contract.Call(opts, &out, "ibcAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ibcmockapp *IbcmockappSession) IbcAddress() (common.Address, error) { + return _Ibcmockapp.Contract.IbcAddress(&_Ibcmockapp.CallOpts) +} + +// IbcAddress is a free data retrieval call binding the contract method 0x696a9bf4. +// +// Solidity: function ibcAddress() view returns(address) +func (_Ibcmockapp *IbcmockappCallerSession) IbcAddress() (common.Address, error) { + return _Ibcmockapp.Contract.IbcAddress(&_Ibcmockapp.CallOpts) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnAcknowledgementPacket(opts *bind.TransactOpts, packet PacketData, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onAcknowledgementPacket", packet, acknowledgement, arg2) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ibcmockapp *IbcmockappSession) OnAcknowledgementPacket(packet PacketData, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnAcknowledgementPacket(&_Ibcmockapp.TransactOpts, packet, acknowledgement, arg2) +} + +// OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. +// +// Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnAcknowledgementPacket(packet PacketData, acknowledgement []byte, arg2 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnAcknowledgementPacket(&_Ibcmockapp.TransactOpts, packet, acknowledgement, arg2) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0xef4776d2. +// +// Solidity: function onChanCloseConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanCloseConfirm(opts *bind.TransactOpts, portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanCloseConfirm", portId, channelId) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0xef4776d2. +// +// Solidity: function onChanCloseConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanCloseConfirm(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanCloseConfirm(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanCloseConfirm is a paid mutator transaction binding the contract method 0xef4776d2. +// +// Solidity: function onChanCloseConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanCloseConfirm(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanCloseConfirm(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0xe74a1ac2. +// +// Solidity: function onChanCloseInit(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanCloseInit(opts *bind.TransactOpts, portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanCloseInit", portId, channelId) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0xe74a1ac2. +// +// Solidity: function onChanCloseInit(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanCloseInit(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanCloseInit(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanCloseInit is a paid mutator transaction binding the contract method 0xe74a1ac2. +// +// Solidity: function onChanCloseInit(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanCloseInit(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanCloseInit(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x4942d1ac. +// +// Solidity: function onChanOpenAck(string portId, string channelId, string counterpartyVersion) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanOpenAck(opts *bind.TransactOpts, portId string, channelId string, counterpartyVersion string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanOpenAck", portId, channelId, counterpartyVersion) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x4942d1ac. +// +// Solidity: function onChanOpenAck(string portId, string channelId, string counterpartyVersion) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanOpenAck(portId string, channelId string, counterpartyVersion string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenAck(&_Ibcmockapp.TransactOpts, portId, channelId, counterpartyVersion) +} + +// OnChanOpenAck is a paid mutator transaction binding the contract method 0x4942d1ac. +// +// Solidity: function onChanOpenAck(string portId, string channelId, string counterpartyVersion) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanOpenAck(portId string, channelId string, counterpartyVersion string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenAck(&_Ibcmockapp.TransactOpts, portId, channelId, counterpartyVersion) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0xa113e411. +// +// Solidity: function onChanOpenConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanOpenConfirm(opts *bind.TransactOpts, portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanOpenConfirm", portId, channelId) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0xa113e411. +// +// Solidity: function onChanOpenConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanOpenConfirm(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenConfirm(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanOpenConfirm is a paid mutator transaction binding the contract method 0xa113e411. +// +// Solidity: function onChanOpenConfirm(string portId, string channelId) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanOpenConfirm(portId string, channelId string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenConfirm(&_Ibcmockapp.TransactOpts, portId, channelId) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x44dd9638. +// +// Solidity: function onChanOpenInit(uint8 , string[] , string , string channelId, (string,string) , string ) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanOpenInit(opts *bind.TransactOpts, arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanOpenInit", arg0, arg1, arg2, channelId, arg4, arg5) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x44dd9638. +// +// Solidity: function onChanOpenInit(uint8 , string[] , string , string channelId, (string,string) , string ) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanOpenInit(arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenInit(&_Ibcmockapp.TransactOpts, arg0, arg1, arg2, channelId, arg4, arg5) +} + +// OnChanOpenInit is a paid mutator transaction binding the contract method 0x44dd9638. +// +// Solidity: function onChanOpenInit(uint8 , string[] , string , string channelId, (string,string) , string ) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanOpenInit(arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenInit(&_Ibcmockapp.TransactOpts, arg0, arg1, arg2, channelId, arg4, arg5) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0x981389f2. +// +// Solidity: function onChanOpenTry(uint8 , string[] , string , string channelId, (string,string) , string , string ) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnChanOpenTry(opts *bind.TransactOpts, arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string, arg6 string) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onChanOpenTry", arg0, arg1, arg2, channelId, arg4, arg5, arg6) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0x981389f2. +// +// Solidity: function onChanOpenTry(uint8 , string[] , string , string channelId, (string,string) , string , string ) returns() +func (_Ibcmockapp *IbcmockappSession) OnChanOpenTry(arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string, arg6 string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenTry(&_Ibcmockapp.TransactOpts, arg0, arg1, arg2, channelId, arg4, arg5, arg6) +} + +// OnChanOpenTry is a paid mutator transaction binding the contract method 0x981389f2. +// +// Solidity: function onChanOpenTry(uint8 , string[] , string , string channelId, (string,string) , string , string ) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnChanOpenTry(arg0 uint8, arg1 []string, arg2 string, channelId string, arg4 ChannelCounterpartyData, arg5 string, arg6 string) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnChanOpenTry(&_Ibcmockapp.TransactOpts, arg0, arg1, arg2, channelId, arg4, arg5, arg6) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ibcmockapp *IbcmockappTransactor) OnRecvPacket(opts *bind.TransactOpts, packet PacketData, arg1 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onRecvPacket", packet, arg1) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ibcmockapp *IbcmockappSession) OnRecvPacket(packet PacketData, arg1 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnRecvPacket(&_Ibcmockapp.TransactOpts, packet, arg1) +} + +// OnRecvPacket is a paid mutator transaction binding the contract method 0x2301c6f5. +// +// Solidity: function onRecvPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, address ) returns(bytes acknowledgement) +func (_Ibcmockapp *IbcmockappTransactorSession) OnRecvPacket(packet PacketData, arg1 common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnRecvPacket(&_Ibcmockapp.TransactOpts, packet, arg1) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) , address relayer) returns() +func (_Ibcmockapp *IbcmockappTransactor) OnTimeoutPacket(opts *bind.TransactOpts, arg0 PacketData, relayer common.Address) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "onTimeoutPacket", arg0, relayer) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) , address relayer) returns() +func (_Ibcmockapp *IbcmockappSession) OnTimeoutPacket(arg0 PacketData, relayer common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnTimeoutPacket(&_Ibcmockapp.TransactOpts, arg0, relayer) +} + +// OnTimeoutPacket is a paid mutator transaction binding the contract method 0x52c7157d. +// +// Solidity: function onTimeoutPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) , address relayer) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) OnTimeoutPacket(arg0 PacketData, relayer common.Address) (*types.Transaction, error) { + return _Ibcmockapp.Contract.OnTimeoutPacket(&_Ibcmockapp.TransactOpts, arg0, relayer) +} + +// SendPacket is a paid mutator transaction binding the contract method 0x98e195f9. +// +// Solidity: function sendPacket(string message, string sourcePort, string sourceChannel, (uint64,uint64) timeoutHeight, uint64 timeoutTimestamp) returns() +func (_Ibcmockapp *IbcmockappTransactor) SendPacket(opts *bind.TransactOpts, message string, sourcePort string, sourceChannel string, timeoutHeight HeightData, timeoutTimestamp uint64) (*types.Transaction, error) { + return _Ibcmockapp.contract.Transact(opts, "sendPacket", message, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp) +} + +// SendPacket is a paid mutator transaction binding the contract method 0x98e195f9. +// +// Solidity: function sendPacket(string message, string sourcePort, string sourceChannel, (uint64,uint64) timeoutHeight, uint64 timeoutTimestamp) returns() +func (_Ibcmockapp *IbcmockappSession) SendPacket(message string, sourcePort string, sourceChannel string, timeoutHeight HeightData, timeoutTimestamp uint64) (*types.Transaction, error) { + return _Ibcmockapp.Contract.SendPacket(&_Ibcmockapp.TransactOpts, message, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp) +} + +// SendPacket is a paid mutator transaction binding the contract method 0x98e195f9. +// +// Solidity: function sendPacket(string message, string sourcePort, string sourceChannel, (uint64,uint64) timeoutHeight, uint64 timeoutTimestamp) returns() +func (_Ibcmockapp *IbcmockappTransactorSession) SendPacket(message string, sourcePort string, sourceChannel string, timeoutHeight HeightData, timeoutTimestamp uint64) (*types.Transaction, error) { + return _Ibcmockapp.Contract.SendPacket(&_Ibcmockapp.TransactOpts, message, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp) +} diff --git a/pkg/testing/chains.go b/pkg/testing/chains.go index a8e43917..1c88d16c 100644 --- a/pkg/testing/chains.go +++ b/pkg/testing/chains.go @@ -26,6 +26,7 @@ import ( "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/erc20" ibccommitment "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibccommitmenttesthelper" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibchandler" + "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibcmockapp" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20bank" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ics20transferbank" ibft2clienttypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/clients/ibft2" @@ -96,6 +97,7 @@ type Chain struct { ERC20 erc20.Erc20 ICS20Transfer ics20transferbank.Ics20transferbank ICS20Bank ics20bank.Ics20bank + IBCMockApp ibcmockapp.Ibcmockapp // Input data for light client LatestLCInputData LightClientInputData @@ -130,6 +132,10 @@ func NewChain(t *testing.T, client *client.ETHClient, lc *LightClient, isAutoMin if err != nil { t.Fatal(err) } + ibcMockApp, err := ibcmockapp.NewIbcmockapp(config.IBCMockAppAddress, client) + if err != nil { + t.Fatal(err) + } erc20_, err := erc20.NewErc20(config.ERC20TokenAddress, client) if err != nil { t.Fatal(err) @@ -165,6 +171,7 @@ func NewChain(t *testing.T, client *client.ETHClient, lc *LightClient, isAutoMin ERC20: *erc20_, ICS20Transfer: *ics20transfer, ICS20Bank: *ics20bank, + IBCMockApp: *ibcMockApp, } } diff --git a/pkg/testing/config.go b/pkg/testing/config.go index 40dd66f5..04581891 100644 --- a/pkg/testing/config.go +++ b/pkg/testing/config.go @@ -14,6 +14,7 @@ type ContractConfig struct { ICS20BankAddress common.Address IBCCommitmentTestHelperAddress common.Address ERC20TokenAddress common.Address + IBCMockAppAddress common.Address } func (cc *ContractConfig) Validate() error { @@ -28,6 +29,8 @@ func (cc *ContractConfig) Validate() error { return errors.New("IBCCommitmentTestHelperAddress is empty") } else if cc.ERC20TokenAddress == zero { return errors.New("ERC20TokenAddress is empty") + } else if cc.IBCMockAppAddress == zero { + return errors.New("IBCMockAppAddress is empty") } else { return nil } @@ -69,6 +72,8 @@ func buildContractConfigFromBroadcastLog(path string) (*ContractConfig, error) { cc.IBCCommitmentTestHelperAddress = tx.ContractAddress case "ERC20Token": cc.ERC20TokenAddress = tx.ContractAddress + case "IBCMockApp": + cc.IBCMockAppAddress = tx.ContractAddress } } if err := cc.Validate(); err != nil { diff --git a/scripts/abigen.sh b/scripts/abigen.sh index bb8b7a38..0c952deb 100755 --- a/scripts/abigen.sh +++ b/scripts/abigen.sh @@ -21,6 +21,7 @@ function main() { "ERC20" "ICS20TransferBank" "ICS20Bank" + "IBCMockApp" "IBCCommitmentTestHelper" ) for src in "${srcs[@]}" ; do diff --git a/tests/foundry/src/Deploy.s.sol b/tests/foundry/src/Deploy.s.sol index 086e77fb..76f4d0d3 100644 --- a/tests/foundry/src/Deploy.s.sol +++ b/tests/foundry/src/Deploy.s.sol @@ -13,6 +13,7 @@ import {ICS20Bank} from "../../../contracts/apps/20-transfer/ICS20Bank.sol"; import {ICS20TransferBank} from "../../../contracts/apps/20-transfer/ICS20TransferBank.sol"; import {ERC20Token} from "../../../contracts/apps/20-transfer/ERC20Token.sol"; import {IBCCommitmentTestHelper} from "./helpers/IBCCommitmentTestHelper.sol"; +import {IBCMockApp} from "../../../contracts/apps/mock/IBCMockApp.sol"; contract DeployScript is Script { string private constant MOCK_CLIENT_TYPE = "mock-client"; @@ -30,12 +31,16 @@ contract DeployScript is Script { address ibcPacket = address(new IBCPacket()); OwnableIBCHandler handler = new OwnableIBCHandler(ibcClient, ibcConnection, ibcChannelHandshake, ibcPacket); - // deploy app contracts + // deploy ics20 contract ICS20Bank bank = new ICS20Bank(); address transferBank = address(new ICS20TransferBank(handler, bank)); bank.setOperator(transferBank); handler.bindPort("transfer", transferBank); + // deploy mock app contract + IBCMockApp mockApp = new IBCMockApp(handler); + handler.bindPort("mock", address(mockApp)); + // deploy client contracts MockClient mockClient = new MockClient(address(handler)); IBFT2Client ibft2Client = new IBFT2Client(address(handler)); From 673ec7200772c311387ad4e4b42de1b4d5f67daf Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Tue, 10 Oct 2023 16:50:43 +0900 Subject: [PATCH 2/6] 25-handler: add `getNextSequenceRecv` Signed-off-by: Jun Kimura --- contracts/core/25-handler/IBCQuerier.sol | 4 ++ pkg/contract/ibchandler/ibchandler.go | 33 +++++++++++- pkg/ibc/core/commitment/commitment.go | 4 ++ pkg/testing/chains.go | 46 ++++++++++++++--- tests/integration/contract_test.go | 65 +++++++++++------------- 5 files changed, 107 insertions(+), 45 deletions(-) diff --git a/contracts/core/25-handler/IBCQuerier.sol b/contracts/core/25-handler/IBCQuerier.sol index bb0ebf6e..6891e642 100644 --- a/contracts/core/25-handler/IBCQuerier.sol +++ b/contracts/core/25-handler/IBCQuerier.sol @@ -67,6 +67,10 @@ abstract contract IBCQuerier is IBCStore { return nextSequenceSends[portId][channelId]; } + function getNextSequenceRecv(string calldata portId, string calldata channelId) external view returns (uint64) { + return nextSequenceRecvs[portId][channelId]; + } + function getExpectedTimePerBlock() external view returns (uint64) { return expectedTimePerBlock; } diff --git a/pkg/contract/ibchandler/ibchandler.go b/pkg/contract/ibchandler/ibchandler.go index fcdc06a7..07ff0844 100644 --- a/pkg/contract/ibchandler/ibchandler.go +++ b/pkg/contract/ibchandler/ibchandler.go @@ -224,7 +224,7 @@ type VersionData struct { // IbchandlerMetaData contains all meta data concerning the Ibchandler contract. var IbchandlerMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"AcknowledgePacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedChannelIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedClientIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedConnectionIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"}],\"name\":\"RecvPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"sourcePort\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"sourceChannel\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structHeight.Data\",\"name\":\"timeoutHeight\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"timeoutTimestamp\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"SendPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"}],\"name\":\"TimeoutPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"destinationPortId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"destinationChannel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"WriteAcknowledgement\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgPacketAcknowledgement\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"acknowledgePacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"moduleAddress\",\"type\":\"address\"}],\"name\":\"bindPort\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"channelCapabilityPath\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelCloseConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelCloseConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"internalType\":\"structIBCMsgs.MsgChannelCloseInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelCloseInit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"counterpartyVersion\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"counterpartyChannelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofTry\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenAck\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenAck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofAck\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"channel\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"channel\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"counterpartyVersion\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenTry\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data\",\"name\":\"version\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"counterpartyConnectionID\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofTry\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClient\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofConsensus\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"consensusHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenAck\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenAck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofAck\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delayPeriod\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delayPeriod\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data[]\",\"name\":\"counterpartyVersions\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClient\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofConsensus\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"consensusHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenTry\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientType\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"consensusStateBytes\",\"type\":\"bytes\"}],\"internalType\":\"structIBCMsgs.MsgCreateClient\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"getChannel\",\"outputs\":[{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"}],\"name\":\"getClientState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCommitmentPrefix\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"name\":\"getConnection\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data[]\",\"name\":\"versions\",\"type\":\"tuple[]\"},{\"internalType\":\"enumConnectionEnd.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delay_period\",\"type\":\"uint64\"}],\"internalType\":\"structConnectionEnd.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"height\",\"type\":\"tuple\"}],\"name\":\"getConsensusState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"consensusStateBytes\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedTimePerBlock\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"getHashedPacketAcknowledgementCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"getHashedPacketCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"getNextSequenceSend\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"hasPacketReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"}],\"name\":\"portCapabilityPath\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgPacketRecv\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"recvPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientType\",\"type\":\"string\"},{\"internalType\":\"contractILightClient\",\"name\":\"client\",\"type\":\"address\"}],\"name\":\"registerClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"sourcePort\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"sourceChannel\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeoutHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeoutTimestamp\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"sendPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expectedTimePerBlock_\",\"type\":\"uint64\"}],\"name\":\"setExpectedTimePerBlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proofUnreceived\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClose\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"nextSequenceRecv\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgTimeoutOnClose\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"timeoutOnClose\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"nextSequenceRecv\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgTimeoutPacket\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"timeoutPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientMessage\",\"type\":\"bytes\"}],\"internalType\":\"structIBCMsgs.MsgUpdateClient\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"updateClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"destinationPortId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destinationChannel\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"writeAcknowledgement\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"AcknowledgePacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedChannelIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedClientIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"GeneratedConnectionIdentifier\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"}],\"name\":\"RecvPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"sourcePort\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"sourceChannel\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structHeight.Data\",\"name\":\"timeoutHeight\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"timeoutTimestamp\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"SendPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"}],\"name\":\"TimeoutPacket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"destinationPortId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"destinationChannel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"WriteAcknowledgement\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgPacketAcknowledgement\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"acknowledgePacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"moduleAddress\",\"type\":\"address\"}],\"name\":\"bindPort\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"channelCapabilityPath\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelCloseConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelCloseConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"internalType\":\"structIBCMsgs.MsgChannelCloseInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelCloseInit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"counterpartyVersion\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"counterpartyChannelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofTry\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenAck\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenAck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofAck\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"channel\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"channel\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"counterpartyVersion\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgChannelOpenTry\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data\",\"name\":\"version\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"counterpartyConnectionID\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofTry\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClient\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofConsensus\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"consensusHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenAck\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenAck\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"proofAck\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenConfirm\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delayPeriod\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenInit\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delayPeriod\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data[]\",\"name\":\"counterpartyVersions\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"proofInit\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClient\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofConsensus\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"consensusHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgConnectionOpenTry\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientType\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientStateBytes\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"consensusStateBytes\",\"type\":\"bytes\"}],\"internalType\":\"structIBCMsgs.MsgCreateClient\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"getChannel\",\"outputs\":[{\"components\":[{\"internalType\":\"enumChannel.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"enumChannel.Order\",\"name\":\"ordering\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"port_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channel_id\",\"type\":\"string\"}],\"internalType\":\"structChannelCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"string[]\",\"name\":\"connection_hops\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"internalType\":\"structChannel.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"}],\"name\":\"getClientState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCommitmentPrefix\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"connectionId\",\"type\":\"string\"}],\"name\":\"getConnection\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"features\",\"type\":\"string[]\"}],\"internalType\":\"structVersion.Data[]\",\"name\":\"versions\",\"type\":\"tuple[]\"},{\"internalType\":\"enumConnectionEnd.State\",\"name\":\"state\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"client_id\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"connection_id\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key_prefix\",\"type\":\"bytes\"}],\"internalType\":\"structMerklePrefix.Data\",\"name\":\"prefix\",\"type\":\"tuple\"}],\"internalType\":\"structCounterparty.Data\",\"name\":\"counterparty\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"delay_period\",\"type\":\"uint64\"}],\"internalType\":\"structConnectionEnd.Data\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"height\",\"type\":\"tuple\"}],\"name\":\"getConsensusState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"consensusStateBytes\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedTimePerBlock\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"getHashedPacketAcknowledgementCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"getHashedPacketCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"getNextSequenceRecv\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"}],\"name\":\"getNextSequenceSend\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"name\":\"hasPacketReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"}],\"name\":\"portCapabilityPath\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"}],\"internalType\":\"structIBCMsgs.MsgPacketRecv\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"recvPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"clientType\",\"type\":\"string\"},{\"internalType\":\"contractILightClient\",\"name\":\"client\",\"type\":\"address\"}],\"name\":\"registerClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"sourcePort\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"sourceChannel\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeoutHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeoutTimestamp\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"sendPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expectedTimePerBlock_\",\"type\":\"uint64\"}],\"name\":\"setExpectedTimePerBlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proofUnreceived\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofClose\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"nextSequenceRecv\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgTimeoutOnClose\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"timeoutOnClose\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"source_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"source_channel\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_port\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destination_channel\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"timeout_height\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"timeout_timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPacket.Data\",\"name\":\"packet\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"revision_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revision_height\",\"type\":\"uint64\"}],\"internalType\":\"structHeight.Data\",\"name\":\"proofHeight\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"nextSequenceRecv\",\"type\":\"uint64\"}],\"internalType\":\"structIBCMsgs.MsgTimeoutPacket\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"timeoutPacket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"clientId\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"clientMessage\",\"type\":\"bytes\"}],\"internalType\":\"structIBCMsgs.MsgUpdateClient\",\"name\":\"msg_\",\"type\":\"tuple\"}],\"name\":\"updateClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"destinationPortId\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destinationChannel\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"acknowledgement\",\"type\":\"bytes\"}],\"name\":\"writeAcknowledgement\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // IbchandlerABI is the input ABI used to generate the binding from. @@ -658,6 +658,37 @@ func (_Ibchandler *IbchandlerCallerSession) GetHashedPacketCommitment(portId str return _Ibchandler.Contract.GetHashedPacketCommitment(&_Ibchandler.CallOpts, portId, channelId, sequence) } +// GetNextSequenceRecv is a free data retrieval call binding the contract method 0xe211bb06. +// +// Solidity: function getNextSequenceRecv(string portId, string channelId) view returns(uint64) +func (_Ibchandler *IbchandlerCaller) GetNextSequenceRecv(opts *bind.CallOpts, portId string, channelId string) (uint64, error) { + var out []interface{} + err := _Ibchandler.contract.Call(opts, &out, "getNextSequenceRecv", portId, channelId) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// GetNextSequenceRecv is a free data retrieval call binding the contract method 0xe211bb06. +// +// Solidity: function getNextSequenceRecv(string portId, string channelId) view returns(uint64) +func (_Ibchandler *IbchandlerSession) GetNextSequenceRecv(portId string, channelId string) (uint64, error) { + return _Ibchandler.Contract.GetNextSequenceRecv(&_Ibchandler.CallOpts, portId, channelId) +} + +// GetNextSequenceRecv is a free data retrieval call binding the contract method 0xe211bb06. +// +// Solidity: function getNextSequenceRecv(string portId, string channelId) view returns(uint64) +func (_Ibchandler *IbchandlerCallerSession) GetNextSequenceRecv(portId string, channelId string) (uint64, error) { + return _Ibchandler.Contract.GetNextSequenceRecv(&_Ibchandler.CallOpts, portId, channelId) +} + // GetNextSequenceSend is a free data retrieval call binding the contract method 0x582418b6. // // Solidity: function getNextSequenceSend(string portId, string channelId) view returns(uint64) diff --git a/pkg/ibc/core/commitment/commitment.go b/pkg/ibc/core/commitment/commitment.go index 87617657..3fd60528 100644 --- a/pkg/ibc/core/commitment/commitment.go +++ b/pkg/ibc/core/commitment/commitment.go @@ -39,6 +39,10 @@ func PacketReceiptCommitmentSlot(portID, channelID string, sequence uint64) stri return CalculateCommitmentSlot(host.PacketReceiptKey(portID, channelID, sequence)) } +func NextSequenceRecvCommitmentSlot(portID, channelID string) string { + return CalculateCommitmentSlot(host.NextSequenceRecvKey(portID, channelID)) +} + func CalculateCommitmentSlot(path []byte) string { return crypto.Keccak256Hash(crypto.Keccak256Hash(path).Bytes(), ibcHostCommitmentSlot[:]).Hex() } diff --git a/pkg/testing/chains.go b/pkg/testing/chains.go index 1c88d16c..9ac18521 100644 --- a/pkg/testing/chains.go +++ b/pkg/testing/chains.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ecdsa" "crypto/sha256" + "encoding/binary" "errors" "fmt" "math/big" @@ -43,6 +44,7 @@ const ( DefaultDelayPeriod uint64 = 0 DefaultPrefix = "ibc" TransferPort = "transfer" + MockPort = "mock" RelayerKeyIndex uint32 = 0 ) @@ -818,11 +820,6 @@ func (chain *Chain) TimeoutOnClose( channel TestChannel, counterpartyChannel TestChannel, ) error { - var ( - proofClose []byte - proofUnreceived []byte - ) - counterpartyCh, found, err := counterparty.IBCHandler.GetChannel( counterparty.CallOpts(ctx, RelayerKeyIndex), packet.DestinationPort, @@ -844,10 +841,23 @@ func (chain *Chain) TimeoutOnClose( if err != nil { return err } - proofClose = p.Data + proofClose := p.Data + + nextSequenceRecv, err := counterparty.IBCHandler.GetNextSequenceRecv( + counterparty.CallOpts(ctx, RelayerKeyIndex), + counterpartyChannel.PortID, counterpartyChannel.ID, + ) + if err != nil { + return err + } + var proofUnreceived []byte if counterpartyCh.Ordering == uint8(channeltypes.ORDERED) { - panic("not implemented") + proof, err := counterparty.QueryNextSequenceRecvProof(chain, counterpartyChannel.ClientID, counterpartyChannel, proofHeight) + if err != nil { + return err + } + proofUnreceived = proof.Data } else { if chain.ClientType() == ibcclient.MockClient { proofUnreceived = []byte{} @@ -879,8 +889,9 @@ func (chain *Chain) TimeoutOnClose( ProofUnreceived: proofUnreceived, ProofHeight: ibchandler.HeightData{ RevisionNumber: 0, - RevisionHeight: uint64(counterparty.LatestLCInputData.Header().Number.Int64()), + RevisionHeight: proofHeight.Uint64(), }, + NextSequenceRecv: nextSequenceRecv, }, ), ) @@ -1242,6 +1253,25 @@ func (chain *Chain) QueryPacketReceiptProof(counterparty *Chain, counterpartyCli return proof, nil } +func (chain *Chain) QueryNextSequenceRecvProof(counterparty *Chain, counterpartyClientID string, counterpartyChannel TestChannel, height *big.Int) (*Proof, error) { + proof, err := chain.QueryProof(chain, counterpartyClientID, commitment.NextSequenceRecvCommitmentSlot(counterpartyChannel.PortID, counterpartyChannel.ID), height) + if err != nil { + return nil, err + } + switch counterparty.ClientType() { + case ibcclient.MockClient: + seq, err := chain.IBCHandler.GetNextSequenceRecv(chain.CallOpts(context.Background(), RelayerKeyIndex), counterpartyChannel.PortID, counterpartyChannel.ID) + if err != nil { + return nil, err + } + bz := make([]byte, 8) + binary.BigEndian.PutUint64(bz, seq) + h := sha256.Sum256(bz) + proof.Data = h[:] + } + return proof, nil +} + func (chain *Chain) LastHeader() *gethtypes.Header { return chain.LatestLCInputData.Header() } diff --git a/tests/integration/contract_test.go b/tests/integration/contract_test.go index 509e8ab8..b0af6362 100644 --- a/tests/integration/contract_test.go +++ b/tests/integration/contract_test.go @@ -13,6 +13,7 @@ import ( host "github.com/cosmos/ibc-go/v7/modules/core/24-host" "github.com/ethereum/go-ethereum/common" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/client" + "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibcmockapp" channeltypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/channel" clienttypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/client" ibctesting "github.com/hyperledger-labs/yui-ibc-solidity/pkg/testing" @@ -25,6 +26,10 @@ const ( deployer = ibctesting.RelayerKeyIndex // the key-index of contract deployer on chain alice uint32 = 1 // the key-index of alice on chain bob uint32 = 2 // the key-index of bob on chain + + mockPacketData = "mock packet data" + mockFailPacketData = "mock failed packet data" + mockAsyncPacketData = "mock async packet data" ) /* @@ -107,7 +112,7 @@ func (suite *ContractTestSuite) TestIBCCompatibility() { }) } -func (suite *ContractTestSuite) TestPacketRelay() { +func (suite *ContractTestSuite) TestICS20Relay() { ctx := context.Background() chainA := suite.chainA @@ -228,17 +233,18 @@ func (suite *ContractTestSuite) TestPacketRelay() { func (suite *ContractTestSuite) TestTimeoutPacket() { ctx := context.Background() - + coordinator := suite.coordinator chainA := suite.chainA chainB := suite.chainB - clientA, clientB := suite.coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) - connA, connB := suite.coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) - chanA, _ := suite.coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.TransferPort, ibctesting.TransferPort, channeltypes.UNORDERED) + clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) + connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) + + chanA, _ := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.TransferPort, ibctesting.TransferPort, channeltypes.UNORDERED) denomA := strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()) - suite.Require().NoError(suite.coordinator.ApproveAndDepositToken(ctx, chainA, deployer, 100, alice)) + suite.Require().NoError(coordinator.ApproveAndDepositToken(ctx, chainA, deployer, 100, alice)) // try to transfer the token to chainB suite.Require().NoError(chainA.WaitIfNoError(ctx)( @@ -260,52 +266,39 @@ func (suite *ContractTestSuite) TestTimeoutPacket() { suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) // then, update the client to reach the timeout height - suite.Require().NoError(suite.coordinator.UpdateClient(ctx, chainA, chainB, clientA)) + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) suite.Require().NoError(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA)) // confirm that the packet commitment is deleted suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN) } func (suite *ContractTestSuite) TestTimeoutOnClose() { ctx := context.Background() - + coordinator := suite.coordinator chainA := suite.chainA chainB := suite.chainB - clientA, clientB := suite.coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) - connA, connB := suite.coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) - chanA, chanB := suite.coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.TransferPort, ibctesting.TransferPort, channeltypes.UNORDERED) + clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) + connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) - suite.Require().NoError(suite.coordinator.ApproveAndDepositToken(ctx, chainA, deployer, 100, alice)) - - // try to transfer the token to chainB - suite.Require().NoError(chainA.WaitIfNoError(ctx)( - chainA.ICS20Transfer.SendTransfer( - chainA.TxOpts(ctx, alice), - strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()), - big.NewInt(100), - addressToHexString(chainB.CallOpts(ctx, bob).From), - chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1000, - ), - )) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + mockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) - transferPacket, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) suite.Require().NoError(err) - suite.Require().NoError(suite.coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) - suite.Require().NoError(suite.chainA.TimeoutOnClose(ctx, *transferPacket, chainB, chanA, chanB)) - - // withdraw tokens from the bank - suite.Require().NoError(chainA.WaitIfNoError(ctx)( - chainA.ICS20Bank.Withdraw( - chainA.TxOpts(ctx, alice), - chainA.ContractConfig.ERC20TokenAddress, - big.NewInt(100), - chainA.CallOpts(ctx, deployer).From, - ))) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) } func addressToHexString(addr common.Address) string { From 7f9474bc62f569f1d017378a828ed82f5b60d861 Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Tue, 10 Oct 2023 18:39:08 +0900 Subject: [PATCH 3/6] add test cases for packet timeout Signed-off-by: Jun Kimura --- pkg/testing/chains.go | 30 +++++--- pkg/testing/coordinator.go | 10 --- tests/e2e/chains_test.go | 4 +- tests/integration/contract_test.go | 114 +++++++++++++++++++---------- 4 files changed, 99 insertions(+), 59 deletions(-) diff --git a/pkg/testing/chains.go b/pkg/testing/chains.go index 9ac18521..021b4e90 100644 --- a/pkg/testing/chains.go +++ b/pkg/testing/chains.go @@ -760,6 +760,7 @@ func (chain *Chain) TimeoutPacket( packet channeltypes.Packet, counterparty *Chain, channel TestChannel, + counterpartyChannel TestChannel, ) error { counterpartyCh, found, err := counterparty.IBCHandler.GetChannel( counterparty.CallOpts(ctx, RelayerKeyIndex), @@ -779,7 +780,11 @@ func (chain *Chain) TimeoutPacket( var proof []byte proofHeight := counterparty.LatestLCInputData.Header().Number if counterpartyCh.Ordering == uint8(channeltypes.ORDERED) { - panic("not implemented") + p, err := counterparty.QueryNextSequenceRecvProof(chain, counterpartyChannel.ClientID, counterpartyChannel, proofHeight) + if err != nil { + return err + } + proof = p.Data } else { ok, err := counterparty.IBCHandler.HasPacketReceipt( counterparty.CallOpts(ctx, RelayerKeyIndex), @@ -798,6 +803,13 @@ func (chain *Chain) TimeoutPacket( proof = p.Data } + nextSequenceRecv, err := counterparty.IBCHandler.GetNextSequenceRecv( + counterparty.CallOpts(ctx, RelayerKeyIndex), + counterpartyChannel.PortID, counterpartyChannel.ID, + ) + if err != nil { + return err + } return chain.WaitIfNoError(ctx)( chain.IBCHandler.TimeoutPacket( chain.TxOpts(ctx, RelayerKeyIndex), @@ -808,6 +820,7 @@ func (chain *Chain) TimeoutPacket( RevisionNumber: 0, RevisionHeight: proofHeight.Uint64(), }, + NextSequenceRecv: nextSequenceRecv, }, ), ) @@ -843,14 +856,6 @@ func (chain *Chain) TimeoutOnClose( } proofClose := p.Data - nextSequenceRecv, err := counterparty.IBCHandler.GetNextSequenceRecv( - counterparty.CallOpts(ctx, RelayerKeyIndex), - counterpartyChannel.PortID, counterpartyChannel.ID, - ) - if err != nil { - return err - } - var proofUnreceived []byte if counterpartyCh.Ordering == uint8(channeltypes.ORDERED) { proof, err := counterparty.QueryNextSequenceRecvProof(chain, counterpartyChannel.ClientID, counterpartyChannel, proofHeight) @@ -880,6 +885,13 @@ func (chain *Chain) TimeoutOnClose( } } + nextSequenceRecv, err := counterparty.IBCHandler.GetNextSequenceRecv( + counterparty.CallOpts(ctx, RelayerKeyIndex), + counterpartyChannel.PortID, counterpartyChannel.ID, + ) + if err != nil { + return err + } return chain.WaitIfNoError(ctx)( chain.IBCHandler.TimeoutOnClose( chain.TxOpts(ctx, RelayerKeyIndex), diff --git a/pkg/testing/coordinator.go b/pkg/testing/coordinator.go index ff668ae4..2754207e 100644 --- a/pkg/testing/coordinator.go +++ b/pkg/testing/coordinator.go @@ -510,13 +510,3 @@ func (c *Coordinator) RelayLastSentPacketWithDelay( c.t.Logf("delay for ack@%v %s", source.chainID, delayForAck) require.Greater(c.t, delayForAck, time.Duration(sourceDelayPeriodExtension*source.GetDelayPeriod())) } - -func (c *Coordinator) TimeoutLastSentPacket( - ctx context.Context, - source, counterparty *Chain, - sourceChannel TestChannel, -) error { - packet, err := source.GetLastSentPacket(ctx, sourceChannel.PortID, sourceChannel.ID) - require.NoError(c.t, err) - return source.TimeoutPacket(ctx, *packet, counterparty, sourceChannel) -} diff --git a/tests/e2e/chains_test.go b/tests/e2e/chains_test.go index 93957d87..b0f65e8f 100644 --- a/tests/e2e/chains_test.go +++ b/tests/e2e/chains_test.go @@ -151,13 +151,13 @@ func (suite *ChainTestSuite) TestPacketRelay() { transferPacket, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) suite.Require().NoError(err) // should fail to timeout packet because the timeout height is not reached - suite.Require().Error(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA)) + suite.Require().Error(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA, chanB)) suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) // then, update the client to reach the timeout height suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) - suite.Require().NoError(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA)) + suite.Require().NoError(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA, chanB)) // confirm that the packet commitment is deleted suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) } diff --git a/tests/integration/contract_test.go b/tests/integration/contract_test.go index b0af6362..f8c4204b 100644 --- a/tests/integration/contract_test.go +++ b/tests/integration/contract_test.go @@ -240,39 +240,61 @@ func (suite *ContractTestSuite) TestTimeoutPacket() { clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) - chanA, _ := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.TransferPort, ibctesting.TransferPort, channeltypes.UNORDERED) + // Case: timeout packet on ordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + mockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) - denomA := strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()) + // should fail to timeout packet because the timeout height is not reached + suite.Require().Error(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + + suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) - suite.Require().NoError(coordinator.ApproveAndDepositToken(ctx, chainA, deployer, 100, alice)) + // then, update the client to reach the timeout height + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) - // try to transfer the token to chainB - suite.Require().NoError(chainA.WaitIfNoError(ctx)( - chainA.ICS20Transfer.SendTransfer( + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + suite.Require().NoError(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + // confirm that the packet commitment is deleted + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + + // Case: timeout packet on unordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( chainA.TxOpts(ctx, alice), - denomA, - big.NewInt(100), - addressToHexString(chainB.CallOpts(ctx, bob).From), + mockPacketData, chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1, - ), - )) - transferPacket, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) - suite.Require().NoError(err) + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) - // should fail to timeout packet because the timeout height is not reached - suite.Require().Error(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA)) + // should fail to timeout packet because the timeout height is not reached + suite.Require().Error(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) - suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) + suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) - // then, update the client to reach the timeout height - suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) + // then, update the client to reach the timeout height + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) - suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) - suite.Require().NoError(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA)) - // confirm that the packet commitment is deleted - suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) - chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN) + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + suite.Require().NoError(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + // confirm that the packet commitment is deleted + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN) + } } func (suite *ContractTestSuite) TestTimeoutOnClose() { @@ -283,22 +305,38 @@ func (suite *ContractTestSuite) TestTimeoutOnClose() { clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) - chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) - suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( - chainA.TxOpts(ctx, alice), - mockPacketData, - chanA.PortID, chanA.ID, - ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, - 0, - ))) - - packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) - suite.Require().NoError(err) + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + mockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } - suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) - suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) - chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + mockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } } func addressToHexString(addr common.Address) string { From 730f1b7b7de84463b5de118947cb5b2f2059534c Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Tue, 10 Oct 2023 23:50:13 +0900 Subject: [PATCH 4/6] add tests for timeout and channel closing Signed-off-by: Jun Kimura --- pkg/testing/chains.go | 56 ++++++----- tests/e2e/chains_test.go | 146 ++++++++++++++++++++++++----- tests/integration/contract_test.go | 87 +++++++++-------- 3 files changed, 195 insertions(+), 94 deletions(-) diff --git a/pkg/testing/chains.go b/pkg/testing/chains.go index 021b4e90..6f27e63d 100644 --- a/pkg/testing/chains.go +++ b/pkg/testing/chains.go @@ -47,6 +47,10 @@ const ( MockPort = "mock" RelayerKeyIndex uint32 = 0 + + MockPacketData = "mock packet data" + MockFailPacketData = "mock failed packet data" + MockAsyncPacketData = "mock async packet data" ) var ( @@ -453,7 +457,7 @@ func (chain *Chain) ConnectionOpenTry(ctx context.Context, counterparty *Chain, if err != nil { return "", err } - clientStateBytes, proofClient, err := counterparty.QueryClientProof(chain, counterpartyConnection.ClientID, proofConnection.Height.ToBN()) + clientStateBytes, proofClient, err := counterparty.QueryClientProof(chain, connection.ClientID, counterpartyConnection.ClientID, proofConnection.Height.ToBN()) if err != nil { return "", err } @@ -493,7 +497,7 @@ func (chain *Chain) ConnectionOpenAck( if err != nil { return err } - clientStateBytes, proofClient, err := counterparty.QueryClientProof(chain, counterpartyConnection.ClientID, proofConnection.Height.ToBN()) + clientStateBytes, proofClient, err := counterparty.QueryClientProof(chain, connection.ClientID, counterpartyConnection.ClientID, proofConnection.Height.ToBN()) if err != nil { return err } @@ -850,7 +854,7 @@ func (chain *Chain) TimeoutOnClose( proofHeight := counterparty.LatestLCInputData.Header().Number - p, err := counterparty.QueryChannelProof(chain, counterpartyChannel.ClientID, counterpartyChannel, proofHeight) + p, err := counterparty.QueryChannelProof(chain, channel.ClientID, counterpartyChannel, proofHeight) if err != nil { return err } @@ -1170,18 +1174,18 @@ func (chain *Chain) QueryProof(counterparty *Chain, counterpartyClientID string, }, nil } -func (counterparty *Chain) QueryClientProof(chain *Chain, counterpartyClientID string, height *big.Int) ([]byte, *Proof, error) { - cs, found, err := counterparty.IBCHandler.GetClientState(counterparty.CallOpts(context.Background(), RelayerKeyIndex), counterpartyClientID) +func (chain *Chain) QueryClientProof(counterparty *Chain, clientID, counterpartyClientID string, height *big.Int) ([]byte, *Proof, error) { + cs, found, err := chain.IBCHandler.GetClientState(chain.CallOpts(context.Background(), RelayerKeyIndex), clientID) if err != nil { return nil, nil, err } else if !found { return nil, nil, fmt.Errorf("client not found: %v", counterpartyClientID) } - proof, err := counterparty.QueryProof(chain, counterpartyClientID, commitment.ClientStateCommitmentSlot(counterpartyClientID), height) + proof, err := chain.QueryProof(counterparty, counterpartyClientID, commitment.ClientStateCommitmentSlot(clientID), height) if err != nil { return nil, nil, err } - switch counterparty.ClientType() { + switch chain.ClientType() { case ibcclient.MockClient: h := sha256.Sum256(cs) proof.Data = h[:] @@ -1189,21 +1193,21 @@ func (counterparty *Chain) QueryClientProof(chain *Chain, counterpartyClientID s return cs, proof, nil } -func (counterparty *Chain) QueryConnectionProof(chain *Chain, counterpartyClientID string, counterpartyConnectionID string, height *big.Int) (*Proof, error) { - proof, err := counterparty.QueryProof(chain, counterpartyClientID, commitment.ConnectionStateCommitmentSlot(counterpartyConnectionID), height) +func (chain *Chain) QueryConnectionProof(counterparty *Chain, counterpartyClientID string, connectionID string, height *big.Int) (*Proof, error) { + proof, err := chain.QueryProof(counterparty, counterpartyClientID, commitment.ConnectionStateCommitmentSlot(connectionID), height) if err != nil { return nil, err } - switch counterparty.ClientType() { + switch chain.ClientType() { case ibcclient.MockClient: - conn, found, err := counterparty.IBCHandler.GetConnection( - counterparty.CallOpts(context.Background(), RelayerKeyIndex), - counterpartyConnectionID, + conn, found, err := chain.IBCHandler.GetConnection( + chain.CallOpts(context.Background(), RelayerKeyIndex), + connectionID, ) if err != nil { return nil, err } else if !found { - return nil, fmt.Errorf("connection not found: %v", counterpartyConnectionID) + return nil, fmt.Errorf("connection not found: %v", connectionID) } bz, err := proto.Marshal(connectionEndToPB(conn)) if err != nil { @@ -1215,21 +1219,21 @@ func (counterparty *Chain) QueryConnectionProof(chain *Chain, counterpartyClient return proof, nil } -func (counterparty *Chain) QueryChannelProof(chain *Chain, counterpartyClientID string, counterpartyChannel TestChannel, height *big.Int) (*Proof, error) { - proof, err := counterparty.QueryProof(chain, counterpartyClientID, commitment.ChannelStateCommitmentSlot(counterpartyChannel.PortID, counterpartyChannel.ID), height) +func (chain *Chain) QueryChannelProof(counterparty *Chain, counterpartyClientID string, channel TestChannel, height *big.Int) (*Proof, error) { + proof, err := chain.QueryProof(counterparty, counterpartyClientID, commitment.ChannelStateCommitmentSlot(channel.PortID, channel.ID), height) if err != nil { return nil, err } - switch counterparty.ClientType() { + switch chain.ClientType() { case ibcclient.MockClient: - ch, found, err := counterparty.IBCHandler.GetChannel( - counterparty.CallOpts(context.Background(), RelayerKeyIndex), - counterpartyChannel.PortID, counterpartyChannel.ID, + ch, found, err := chain.IBCHandler.GetChannel( + chain.CallOpts(context.Background(), RelayerKeyIndex), + channel.PortID, channel.ID, ) if err != nil { return nil, err } else if !found { - return nil, fmt.Errorf("channel not found: %v", counterpartyChannel) + return nil, fmt.Errorf("channel not found: %v", channel) } bz, err := proto.Marshal(channelToPB(ch)) if err != nil { @@ -1250,7 +1254,7 @@ func (chain *Chain) QueryPacketReceiptProof(counterparty *Chain, counterpartyCli if err != nil { return nil, err } - switch counterparty.ClientType() { + switch chain.ClientType() { case ibcclient.MockClient: exists, err := chain.IBCHandler.HasPacketReceipt(chain.CallOpts(context.Background(), RelayerKeyIndex), packetFromCounterparty.DestinationPort, packetFromCounterparty.DestinationChannel, packetFromCounterparty.Sequence) if err != nil { @@ -1265,14 +1269,14 @@ func (chain *Chain) QueryPacketReceiptProof(counterparty *Chain, counterpartyCli return proof, nil } -func (chain *Chain) QueryNextSequenceRecvProof(counterparty *Chain, counterpartyClientID string, counterpartyChannel TestChannel, height *big.Int) (*Proof, error) { - proof, err := chain.QueryProof(chain, counterpartyClientID, commitment.NextSequenceRecvCommitmentSlot(counterpartyChannel.PortID, counterpartyChannel.ID), height) +func (chain *Chain) QueryNextSequenceRecvProof(counterparty *Chain, counterpartyClientID string, channel TestChannel, height *big.Int) (*Proof, error) { + proof, err := chain.QueryProof(counterparty, counterpartyClientID, commitment.NextSequenceRecvCommitmentSlot(channel.PortID, channel.ID), height) if err != nil { return nil, err } - switch counterparty.ClientType() { + switch chain.ClientType() { case ibcclient.MockClient: - seq, err := chain.IBCHandler.GetNextSequenceRecv(chain.CallOpts(context.Background(), RelayerKeyIndex), counterpartyChannel.PortID, counterpartyChannel.ID) + seq, err := chain.IBCHandler.GetNextSequenceRecv(chain.CallOpts(context.Background(), RelayerKeyIndex), channel.PortID, channel.ID) if err != nil { return nil, err } diff --git a/tests/e2e/chains_test.go b/tests/e2e/chains_test.go index b0f65e8f..5b78c183 100644 --- a/tests/e2e/chains_test.go +++ b/tests/e2e/chains_test.go @@ -12,6 +12,7 @@ import ( ibcchanneltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/ethereum/go-ethereum/common" "github.com/hyperledger-labs/yui-ibc-solidity/pkg/client" + "github.com/hyperledger-labs/yui-ibc-solidity/pkg/contract/ibcmockapp" channeltypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/channel" clienttypes "github.com/hyperledger-labs/yui-ibc-solidity/pkg/ibc/core/client" ibctesting "github.com/hyperledger-labs/yui-ibc-solidity/pkg/testing" @@ -35,7 +36,7 @@ type ChainTestSuite struct { func (suite *ChainTestSuite) SetupTest() {} -func (suite *ChainTestSuite) TestPacketRelay() { +func (suite *ChainTestSuite) TestICS20() { ctx := context.Background() ethClA, err := client.NewETHClient("http://127.0.0.1:8645") @@ -160,28 +161,7 @@ func (suite *ChainTestSuite) TestPacketRelay() { suite.Require().NoError(chainA.TimeoutPacket(ctx, *transferPacket, chainB, chanA, chanB)) // confirm that the packet commitment is deleted suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, transferPacket.SourcePort, transferPacket.SourceChannel, transferPacket.Sequence)) - } - - { - // try to transfer the token to chainB - suite.Require().NoError(chainA.WaitIfNoError(ctx)( - chainA.ICS20Transfer.SendTransfer( - chainA.TxOpts(ctx, aliceA), - strings.ToLower(chainA.ContractConfig.ERC20TokenAddress.String()), - big.NewInt(50), - addressToHexString(chainB.CallOpts(ctx, bobB).From), - chanA.PortID, chanA.ID, - uint64(chainB.LastHeader().Number.Int64())+1000, - ), - )) - - transferPacket, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) - suite.Require().NoError(err) - - // close channel - suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) - suite.Require().NoError(chainA.TimeoutOnClose(ctx, *transferPacket, chainB, chanA, chanB)) - suite.Require().NoError(coordinator.ChanCloseConfirm(ctx, chainA, chainB, chanA, chanB)) + suite.Require().NoError(chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN)) } // withdraw tokens from the bank @@ -199,6 +179,126 @@ func (suite *ChainTestSuite) TestPacketRelay() { suite.Require().Equal(beforeBalanceA.Int64(), afterBalanceA.Int64()) } +func (suite *ChainTestSuite) TestTimeoutAndClose() { + ctx := context.Background() + + ethClA, err := client.NewETHClient("http://127.0.0.1:8645") + suite.Require().NoError(err) + ethClB, err := client.NewETHClient("http://127.0.0.1:8745") + suite.Require().NoError(err) + + chainA := ibctesting.NewChain(suite.T(), ethClA, ibctesting.NewLightClient(ethClA, clienttypes.BesuIBFT2Client), true) + chainB := ibctesting.NewChain(suite.T(), ethClB, ibctesting.NewLightClient(ethClB, clienttypes.BesuIBFT2Client), true) + coordinator := ibctesting.NewCoordinator(suite.T(), chainA, chainB) + + clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.BesuIBFT2Client) + connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) + + // Case: timeoutOnClose on ordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) + suite.Require().NoError(coordinator.UpdateClient(ctx, chainB, chainA, clientB)) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, aliceA), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + + // Case: timeoutOnClose on unordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, aliceA), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + + // Case: timeout packet on ordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, aliceA), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + + // should fail to timeout packet because the timeout height is not reached + suite.Require().Error(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + + suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) + + // then, update the client to reach the timeout height + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) + + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + suite.Require().NoError(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + // confirm that the packet commitment is deleted + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + + // Case: timeout packet on unordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, aliceA), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + + // should fail to timeout packet because the timeout height is not reached + suite.Require().Error(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + + suite.Require().NoError(chainB.AdvanceBlockNumber(ctx, uint64(chainB.LastHeader().Number.Int64())+1)) + + // then, update the client to reach the timeout height + suite.Require().NoError(coordinator.UpdateClient(ctx, chainA, chainB, clientA)) + + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, true, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + suite.Require().NoError(chainA.TimeoutPacket(ctx, *packet, chainB, chanA, chanB)) + // confirm that the packet commitment is deleted + suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, packet.SourcePort, packet.SourceChannel, packet.Sequence)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN) + } + + // Case: close channel on ordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + coordinator.CloseChannel(ctx, chainA, chainB, chanA, chanB) + } + + // Case: close channel on unordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + coordinator.CloseChannel(ctx, chainA, chainB, chanA, chanB) + } +} + func (suite *ChainTestSuite) TestPacketRelayWithDelay() { ctx := context.Background() diff --git a/tests/integration/contract_test.go b/tests/integration/contract_test.go index f8c4204b..e9b014f8 100644 --- a/tests/integration/contract_test.go +++ b/tests/integration/contract_test.go @@ -26,10 +26,6 @@ const ( deployer = ibctesting.RelayerKeyIndex // the key-index of contract deployer on chain alice uint32 = 1 // the key-index of alice on chain bob uint32 = 2 // the key-index of bob on chain - - mockPacketData = "mock packet data" - mockFailPacketData = "mock failed packet data" - mockAsyncPacketData = "mock async packet data" ) /* @@ -112,7 +108,7 @@ func (suite *ContractTestSuite) TestIBCCompatibility() { }) } -func (suite *ContractTestSuite) TestICS20Relay() { +func (suite *ContractTestSuite) TestICS20() { ctx := context.Background() chainA := suite.chainA @@ -226,12 +222,9 @@ func (suite *ContractTestSuite) TestICS20Relay() { suite.Require().NoError(err) suite.Require().Equal(balanceA0.Int64(), balanceA2.Int64()) } - - // close channel - suite.coordinator.CloseChannel(ctx, chainA, chainB, chanA, chanB) } -func (suite *ContractTestSuite) TestTimeoutPacket() { +func (suite *ContractTestSuite) TestTimeoutAndClose() { ctx := context.Background() coordinator := suite.coordinator chainA := suite.chainA @@ -240,12 +233,46 @@ func (suite *ContractTestSuite) TestTimeoutPacket() { clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) + // Case: timeoutOnClose on ordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + + // Case: timeoutOnClose on unordered channel + { + chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) + suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( + chainA.TxOpts(ctx, alice), + ibctesting.MockPacketData, + chanA.PortID, chanA.ID, + ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, + 0, + ))) + packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) + suite.Require().NoError(err) + suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) + suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) + chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + } + // Case: timeout packet on ordered channel { chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( chainA.TxOpts(ctx, alice), - mockPacketData, + ibctesting.MockPacketData, chanA.PortID, chanA.ID, ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, 0, @@ -273,7 +300,7 @@ func (suite *ContractTestSuite) TestTimeoutPacket() { chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( chainA.TxOpts(ctx, alice), - mockPacketData, + ibctesting.MockPacketData, chanA.PortID, chanA.ID, ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1}, 0, @@ -295,47 +322,17 @@ func (suite *ContractTestSuite) TestTimeoutPacket() { suite.Require().NoError(chainA.EnsurePacketCommitmentExistence(ctx, false, packet.SourcePort, packet.SourceChannel, packet.Sequence)) chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.OPEN) } -} - -func (suite *ContractTestSuite) TestTimeoutOnClose() { - ctx := context.Background() - coordinator := suite.coordinator - chainA := suite.chainA - chainB := suite.chainB - - clientA, clientB := coordinator.SetupClients(ctx, chainA, chainB, clienttypes.MockClient) - connA, connB := coordinator.CreateConnection(ctx, chainA, chainB, clientA, clientB) + // Case: close channel on ordered channel { chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.ORDERED) - suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( - chainA.TxOpts(ctx, alice), - mockPacketData, - chanA.PortID, chanA.ID, - ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, - 0, - ))) - packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) - suite.Require().NoError(err) - suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) - suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) - chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + coordinator.CloseChannel(ctx, chainA, chainB, chanA, chanB) } + // Case: close channel on unordered channel { chanA, chanB := coordinator.CreateChannel(ctx, chainA, chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, channeltypes.UNORDERED) - suite.Require().NoError(chainA.WaitIfNoError(ctx)(chainA.IBCMockApp.SendPacket( - chainA.TxOpts(ctx, alice), - mockPacketData, - chanA.PortID, chanA.ID, - ibcmockapp.HeightData{RevisionNumber: 0, RevisionHeight: uint64(chainB.LastHeader().Number.Int64()) + 1000}, - 0, - ))) - packet, err := chainA.GetLastSentPacket(ctx, chanA.PortID, chanA.ID) - suite.Require().NoError(err) - suite.Require().NoError(coordinator.ChanCloseInit(ctx, chainB, chainA, chanB)) - suite.Require().NoError(chainA.TimeoutOnClose(ctx, *packet, chainB, chanA, chanB)) - chainA.EnsureChannelState(ctx, chanA.PortID, chanA.ID, channeltypes.CLOSED) + coordinator.CloseChannel(ctx, chainA, chainB, chanA, chanB) } } From baf0405bc23e33215562e3c274766cd332c9bd24 Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Tue, 10 Oct 2023 23:50:44 +0900 Subject: [PATCH 5/6] set next sequence recv commitment Signed-off-by: Jun Kimura --- contracts/core/04-channel/IBCChannelHandshake.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/core/04-channel/IBCChannelHandshake.sol b/contracts/core/04-channel/IBCChannelHandshake.sol index 3a1736b0..ddab82ed 100644 --- a/contracts/core/04-channel/IBCChannelHandshake.sol +++ b/contracts/core/04-channel/IBCChannelHandshake.sol @@ -36,6 +36,8 @@ contract IBCChannelHandshake is IBCStore, IIBCChannelHandshake { nextSequenceRecvs[msg_.portId][channelId] = 1; nextSequenceAcks[msg_.portId][channelId] = 1; updateChannelCommitment(msg_.portId, channelId); + commitments[IBCCommitment.nextSequenceRecvCommitmentKey(msg_.portId, channelId)] = + keccak256(abi.encodePacked((bytes8(uint64(1))))); return channelId; } @@ -80,6 +82,8 @@ contract IBCChannelHandshake is IBCStore, IIBCChannelHandshake { nextSequenceRecvs[msg_.portId][channelId] = 1; nextSequenceAcks[msg_.portId][channelId] = 1; updateChannelCommitment(msg_.portId, channelId); + commitments[IBCCommitment.nextSequenceRecvCommitmentKey(msg_.portId, channelId)] = + keccak256(abi.encodePacked((bytes8(uint64(1))))); return channelId; } From 035d8c8f6cb4ce11803e1e7fff47c8b6f7ea6cc8 Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Wed, 11 Oct 2023 00:01:04 +0900 Subject: [PATCH 6/6] mock: specify visibility explicitly Signed-off-by: Jun Kimura --- contracts/apps/mock/IBCMockLib.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/apps/mock/IBCMockLib.sol b/contracts/apps/mock/IBCMockLib.sol index 26403fb6..ff54d061 100644 --- a/contracts/apps/mock/IBCMockLib.sol +++ b/contracts/apps/mock/IBCMockLib.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.9; library IBCMockLib { - bytes constant MOCK_PACKET_DATA = bytes("mock packet data"); - bytes constant MOCK_FAIL_PACKET_DATA = bytes("mock failed packet data"); - bytes constant MOCK_ASYNC_PACKET_DATA = bytes("mock async packet data"); + bytes public constant MOCK_PACKET_DATA = bytes("mock packet data"); + bytes public constant MOCK_FAIL_PACKET_DATA = bytes("mock failed packet data"); + bytes public constant MOCK_ASYNC_PACKET_DATA = bytes("mock async packet data"); bytes public constant SUCCESSFUL_ACKNOWLEDGEMENT_JSON = bytes('{"result":"bW9jayBhY2tub3dsZWRnZW1lbnQ="}'); bytes public constant FAILED_ACKNOWLEDGEMENT_JSON = bytes('{"error":"mock failed acknowledgement"}');