From ffc8a14adc058877b9ca9a2f485e3724b5267743 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 5 Oct 2023 09:23:56 +0800
Subject: [PATCH 01/25] Problem: relayer does't make use of binding contract

---
 CHANGELOG.md                                  |   1 +
 nix/default.nix                               |   2 +-
 nix/sources.json                              |   6 +-
 scripts/gen-bindings-contracts                |   2 +
 .../relayer/i_relayer_functions.abigen.go     | 516 ++++++++++++++++++
 .../events/bindings/src/RelayerFunctions.sol  |  21 +
 x/cronos/keeper/precompiles/relayer.go        | 144 +++--
 7 files changed, 614 insertions(+), 78 deletions(-)
 create mode 100644 x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
 create mode 100644 x/cronos/events/bindings/src/RelayerFunctions.sol

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d4adde98c..f1cfa2cf94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -86,6 +86,7 @@
 - [#1179](https://github.com/crypto-org-chain/cronos/pull/1179) Support blocking addresses in mempool.
 - [#1182](https://github.com/crypto-org-chain/cronos/pull/1182) Bump librocksdb to 8.5.3.
 - [#1183](https://github.com/crypto-org-chain/cronos/pull/1183) Avoid redundant logs added from relayer.
+- [#](https://github.com/crypto-org-chain/cronos/pull/) Make use of binding contract in relayer.
 
 *April 13, 2023*
 
diff --git a/nix/default.nix b/nix/default.nix
index de060f0175..53b6f64b95 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -56,7 +56,7 @@ import sources.nixpkgs {
         name = "rly";
         src = sources.relayer;
         subPackages = [ "." ];
-        vendorSha256 = "sha256-IoaGLD3XKRmD61qcr/sPn3aWaa7zYAO9EbMiJFnF5BY=";
+        vendorSha256 = "sha256-5s5URiAZk59mOfZdUcqYAB/IvzFuBiQH5jDBuh6huTE=";
         doCheck = false;
         GOWORK = "off";
         postInstall = ''
diff --git a/nix/sources.json b/nix/sources.json
index bf51bd3309..c40e70da36 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -126,10 +126,10 @@
         "homepage": "https://github.com/crypto-org-chain/relayer",
         "owner": "crypto-org-chain",
         "repo": "relayer",
-        "rev": "f202a264463e9d5829398f6be50bff990421b483",
-        "sha256": "08x4bhwglx12rp78gs4hzgp2cywzqwr7gghk1kxasmvy9z0qxp92",
+        "rev": "efc56cdee7e8148e8c70945e974da12060f110f0",
+        "sha256": "0dm5vrkdq9q0qysykxw407r3w8gbpzhf9yhh92l68vcqs1y3qp11",
         "type": "tarball",
-        "url": "https://github.com/crypto-org-chain/relayer/archive/f202a264463e9d5829398f6be50bff990421b483.tar.gz",
+        "url": "https://github.com/mmsqe/relayer/archive/efc56cdee7e8148e8c70945e974da12060f110f0.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     }
 }
diff --git a/scripts/gen-bindings-contracts b/scripts/gen-bindings-contracts
index 4c55e25c2b..b32930e0fc 100755
--- a/scripts/gen-bindings-contracts
+++ b/scripts/gen-bindings-contracts
@@ -2,6 +2,7 @@
 
 solc08 --abi --bin x/cronos/events/bindings/src/CosmosTypes.sol -o build --overwrite
 solc08 --abi --bin x/cronos/events/bindings/src/Relayer.sol -o build --overwrite
+solc08 --abi --bin x/cronos/events/bindings/src/RelayerFunctions.sol -o build --overwrite
 solc08 --abi --bin x/cronos/events/bindings/src/Bank.sol -o build --overwrite
 solc08 --abi --bin x/cronos/events/bindings/src/ICA.sol -o build --overwrite
 solc08 --abi --bin x/cronos/events/bindings/src/ICACallback.sol -o build --overwrite
@@ -9,6 +10,7 @@ solc08 --abi --bin x/cronos/events/bindings/src/ICACallback.sol -o build --overw
 
 abigen --pkg lib --abi build/CosmosTypes.abi --bin build/CosmosTypes.bin --out x/cronos/events/bindings/cosmos/lib/cosmos_types.abigen.go --type CosmosTypes
 abigen --pkg relayer --abi build/IRelayerModule.abi --bin build/IRelayerModule.bin --out x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_module.abigen.go --type RelayerModule
+abigen --pkg relayer --abi build/IRelayerFunctions.abi --bin build/IRelayerFunctions.bin --out x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go --type RelayerFunctions
 abigen --pkg bank --abi build/IBankModule.abi --bin build/IBankModule.bin --out x/cronos/events/bindings/cosmos/precompile/bank/i_bank_module.abigen.go --type BankModule
 abigen --pkg ica --abi build/IICAModule.abi --bin build/IICAModule.bin --out x/cronos/events/bindings/cosmos/precompile/ica/i_ica_module.abigen.go --type ICAModule
 abigen --pkg icacallback --abi build/IICACallback.abi --bin build/IICACallback.bin --out x/cronos/events/bindings/cosmos/precompile/icacallback/i_ica_callback.abigen.go --type ICACallback
diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
new file mode 100644
index 0000000000..cf2ee241a6
--- /dev/null
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -0,0 +1,516 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package relayer
+
+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
+)
+
+// RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
+var RelayerFunctionsMetaData = &bind.MetaData{
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+}
+
+// RelayerFunctionsABI is the input ABI used to generate the binding from.
+// Deprecated: Use RelayerFunctionsMetaData.ABI instead.
+var RelayerFunctionsABI = RelayerFunctionsMetaData.ABI
+
+// RelayerFunctions is an auto generated Go binding around an Ethereum contract.
+type RelayerFunctions struct {
+	RelayerFunctionsCaller     // Read-only binding to the contract
+	RelayerFunctionsTransactor // Write-only binding to the contract
+	RelayerFunctionsFilterer   // Log filterer for contract events
+}
+
+// RelayerFunctionsCaller is an auto generated read-only Go binding around an Ethereum contract.
+type RelayerFunctionsCaller struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// RelayerFunctionsTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type RelayerFunctionsTransactor struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// RelayerFunctionsFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type RelayerFunctionsFilterer struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// RelayerFunctionsSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type RelayerFunctionsSession struct {
+	Contract     *RelayerFunctions // 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
+}
+
+// RelayerFunctionsCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type RelayerFunctionsCallerSession struct {
+	Contract *RelayerFunctionsCaller // Generic contract caller binding to set the session for
+	CallOpts bind.CallOpts           // Call options to use throughout this session
+}
+
+// RelayerFunctionsTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type RelayerFunctionsTransactorSession struct {
+	Contract     *RelayerFunctionsTransactor // Generic contract transactor binding to set the session for
+	TransactOpts bind.TransactOpts           // Transaction auth options to use throughout this session
+}
+
+// RelayerFunctionsRaw is an auto generated low-level Go binding around an Ethereum contract.
+type RelayerFunctionsRaw struct {
+	Contract *RelayerFunctions // Generic contract binding to access the raw methods on
+}
+
+// RelayerFunctionsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type RelayerFunctionsCallerRaw struct {
+	Contract *RelayerFunctionsCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// RelayerFunctionsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type RelayerFunctionsTransactorRaw struct {
+	Contract *RelayerFunctionsTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewRelayerFunctions creates a new instance of RelayerFunctions, bound to a specific deployed contract.
+func NewRelayerFunctions(address common.Address, backend bind.ContractBackend) (*RelayerFunctions, error) {
+	contract, err := bindRelayerFunctions(address, backend, backend, backend)
+	if err != nil {
+		return nil, err
+	}
+	return &RelayerFunctions{RelayerFunctionsCaller: RelayerFunctionsCaller{contract: contract}, RelayerFunctionsTransactor: RelayerFunctionsTransactor{contract: contract}, RelayerFunctionsFilterer: RelayerFunctionsFilterer{contract: contract}}, nil
+}
+
+// NewRelayerFunctionsCaller creates a new read-only instance of RelayerFunctions, bound to a specific deployed contract.
+func NewRelayerFunctionsCaller(address common.Address, caller bind.ContractCaller) (*RelayerFunctionsCaller, error) {
+	contract, err := bindRelayerFunctions(address, caller, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+	return &RelayerFunctionsCaller{contract: contract}, nil
+}
+
+// NewRelayerFunctionsTransactor creates a new write-only instance of RelayerFunctions, bound to a specific deployed contract.
+func NewRelayerFunctionsTransactor(address common.Address, transactor bind.ContractTransactor) (*RelayerFunctionsTransactor, error) {
+	contract, err := bindRelayerFunctions(address, nil, transactor, nil)
+	if err != nil {
+		return nil, err
+	}
+	return &RelayerFunctionsTransactor{contract: contract}, nil
+}
+
+// NewRelayerFunctionsFilterer creates a new log filterer instance of RelayerFunctions, bound to a specific deployed contract.
+func NewRelayerFunctionsFilterer(address common.Address, filterer bind.ContractFilterer) (*RelayerFunctionsFilterer, error) {
+	contract, err := bindRelayerFunctions(address, nil, nil, filterer)
+	if err != nil {
+		return nil, err
+	}
+	return &RelayerFunctionsFilterer{contract: contract}, nil
+}
+
+// bindRelayerFunctions binds a generic wrapper to an already deployed contract.
+func bindRelayerFunctions(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+	parsed, err := abi.JSON(strings.NewReader(RelayerFunctionsABI))
+	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 (_RelayerFunctions *RelayerFunctionsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+	return _RelayerFunctions.Contract.RelayerFunctionsCaller.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 (_RelayerFunctions *RelayerFunctionsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.RelayerFunctionsTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_RelayerFunctions *RelayerFunctionsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.RelayerFunctionsTransactor.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 (_RelayerFunctions *RelayerFunctionsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+	return _RelayerFunctions.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 (_RelayerFunctions *RelayerFunctionsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_RelayerFunctions *RelayerFunctionsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.contract.Transact(opts, method, params...)
+}
+
+// Acknowledgement is a paid mutator transaction binding the contract method 0x07ed2b37.
+//
+// Solidity: function acknowledgement(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) Acknowledgement(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "acknowledgement", data)
+}
+
+// Acknowledgement is a paid mutator transaction binding the contract method 0x07ed2b37.
+//
+// Solidity: function acknowledgement(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) Acknowledgement(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.Acknowledgement(&_RelayerFunctions.TransactOpts, data)
+}
+
+// Acknowledgement is a paid mutator transaction binding the contract method 0x07ed2b37.
+//
+// Solidity: function acknowledgement(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) Acknowledgement(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.Acknowledgement(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenAck is a paid mutator transaction binding the contract method 0xd859b9f4.
+//
+// Solidity: function channelOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelOpenAck(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelOpenAck", data)
+}
+
+// ChannelOpenAck is a paid mutator transaction binding the contract method 0xd859b9f4.
+//
+// Solidity: function channelOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelOpenAck(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenAck(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenAck is a paid mutator transaction binding the contract method 0xd859b9f4.
+//
+// Solidity: function channelOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelOpenAck(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenAck(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenConfirm is a paid mutator transaction binding the contract method 0x5e1fad7d.
+//
+// Solidity: function channelOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelOpenConfirm(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelOpenConfirm", data)
+}
+
+// ChannelOpenConfirm is a paid mutator transaction binding the contract method 0x5e1fad7d.
+//
+// Solidity: function channelOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelOpenConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenConfirm is a paid mutator transaction binding the contract method 0x5e1fad7d.
+//
+// Solidity: function channelOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelOpenConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenInit is a paid mutator transaction binding the contract method 0x63d2dc06.
+//
+// Solidity: function channelOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelOpenInit(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelOpenInit", data)
+}
+
+// ChannelOpenInit is a paid mutator transaction binding the contract method 0x63d2dc06.
+//
+// Solidity: function channelOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelOpenInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenInit(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenInit is a paid mutator transaction binding the contract method 0x63d2dc06.
+//
+// Solidity: function channelOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelOpenInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenInit(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenTry is a paid mutator transaction binding the contract method 0xf45b605e.
+//
+// Solidity: function channelOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelOpenTry(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelOpenTry", data)
+}
+
+// ChannelOpenTry is a paid mutator transaction binding the contract method 0xf45b605e.
+//
+// Solidity: function channelOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelOpenTry(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenTry(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelOpenTry is a paid mutator transaction binding the contract method 0xf45b605e.
+//
+// Solidity: function channelOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelOpenTry(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelOpenTry(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenAck is a paid mutator transaction binding the contract method 0xe9984826.
+//
+// Solidity: function connectionOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ConnectionOpenAck(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "connectionOpenAck", data)
+}
+
+// ConnectionOpenAck is a paid mutator transaction binding the contract method 0xe9984826.
+//
+// Solidity: function connectionOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ConnectionOpenAck(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenAck(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenAck is a paid mutator transaction binding the contract method 0xe9984826.
+//
+// Solidity: function connectionOpenAck(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ConnectionOpenAck(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenAck(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenConfirm is a paid mutator transaction binding the contract method 0xb710bcf2.
+//
+// Solidity: function connectionOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ConnectionOpenConfirm(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "connectionOpenConfirm", data)
+}
+
+// ConnectionOpenConfirm is a paid mutator transaction binding the contract method 0xb710bcf2.
+//
+// Solidity: function connectionOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ConnectionOpenConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenConfirm is a paid mutator transaction binding the contract method 0xb710bcf2.
+//
+// Solidity: function connectionOpenConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ConnectionOpenConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenInit is a paid mutator transaction binding the contract method 0x528e6644.
+//
+// Solidity: function connectionOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ConnectionOpenInit(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "connectionOpenInit", data)
+}
+
+// ConnectionOpenInit is a paid mutator transaction binding the contract method 0x528e6644.
+//
+// Solidity: function connectionOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ConnectionOpenInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenInit(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenInit is a paid mutator transaction binding the contract method 0x528e6644.
+//
+// Solidity: function connectionOpenInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ConnectionOpenInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenInit(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenTry is a paid mutator transaction binding the contract method 0x986fa270.
+//
+// Solidity: function connectionOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ConnectionOpenTry(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "connectionOpenTry", data)
+}
+
+// ConnectionOpenTry is a paid mutator transaction binding the contract method 0x986fa270.
+//
+// Solidity: function connectionOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ConnectionOpenTry(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenTry(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ConnectionOpenTry is a paid mutator transaction binding the contract method 0x986fa270.
+//
+// Solidity: function connectionOpenTry(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ConnectionOpenTry(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ConnectionOpenTry(&_RelayerFunctions.TransactOpts, data)
+}
+
+// CreateClient is a paid mutator transaction binding the contract method 0x3df83afa.
+//
+// Solidity: function createClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) CreateClient(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "createClient", data)
+}
+
+// CreateClient is a paid mutator transaction binding the contract method 0x3df83afa.
+//
+// Solidity: function createClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) CreateClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.CreateClient(&_RelayerFunctions.TransactOpts, data)
+}
+
+// CreateClient is a paid mutator transaction binding the contract method 0x3df83afa.
+//
+// Solidity: function createClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) CreateClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.CreateClient(&_RelayerFunctions.TransactOpts, data)
+}
+
+// RecvPacket is a paid mutator transaction binding the contract method 0xf6a1539d.
+//
+// Solidity: function recvPacket(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) RecvPacket(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "recvPacket", data)
+}
+
+// RecvPacket is a paid mutator transaction binding the contract method 0xf6a1539d.
+//
+// Solidity: function recvPacket(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) RecvPacket(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.RecvPacket(&_RelayerFunctions.TransactOpts, data)
+}
+
+// RecvPacket is a paid mutator transaction binding the contract method 0xf6a1539d.
+//
+// Solidity: function recvPacket(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) RecvPacket(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.RecvPacket(&_RelayerFunctions.TransactOpts, data)
+}
+
+// SubmitMisbehaviour is a paid mutator transaction binding the contract method 0xa53b1c82.
+//
+// Solidity: function submitMisbehaviour(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) SubmitMisbehaviour(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "submitMisbehaviour", data)
+}
+
+// SubmitMisbehaviour is a paid mutator transaction binding the contract method 0xa53b1c82.
+//
+// Solidity: function submitMisbehaviour(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) SubmitMisbehaviour(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.SubmitMisbehaviour(&_RelayerFunctions.TransactOpts, data)
+}
+
+// SubmitMisbehaviour is a paid mutator transaction binding the contract method 0xa53b1c82.
+//
+// Solidity: function submitMisbehaviour(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) SubmitMisbehaviour(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.SubmitMisbehaviour(&_RelayerFunctions.TransactOpts, data)
+}
+
+// Timeout is a paid mutator transaction binding the contract method 0x6d2a27f6.
+//
+// Solidity: function timeout(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) Timeout(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "timeout", data)
+}
+
+// Timeout is a paid mutator transaction binding the contract method 0x6d2a27f6.
+//
+// Solidity: function timeout(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) Timeout(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.Timeout(&_RelayerFunctions.TransactOpts, data)
+}
+
+// Timeout is a paid mutator transaction binding the contract method 0x6d2a27f6.
+//
+// Solidity: function timeout(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) Timeout(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.Timeout(&_RelayerFunctions.TransactOpts, data)
+}
+
+// TimeoutOnClose is a paid mutator transaction binding the contract method 0x08f5d079.
+//
+// Solidity: function timeoutOnClose(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) TimeoutOnClose(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "timeoutOnClose", data)
+}
+
+// TimeoutOnClose is a paid mutator transaction binding the contract method 0x08f5d079.
+//
+// Solidity: function timeoutOnClose(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) TimeoutOnClose(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.TimeoutOnClose(&_RelayerFunctions.TransactOpts, data)
+}
+
+// TimeoutOnClose is a paid mutator transaction binding the contract method 0x08f5d079.
+//
+// Solidity: function timeoutOnClose(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) TimeoutOnClose(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.TimeoutOnClose(&_RelayerFunctions.TransactOpts, data)
+}
+
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
+//
+// Solidity: function updateClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClient(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClient", data)
+}
+
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
+//
+// Solidity: function updateClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClient(&_RelayerFunctions.TransactOpts, data)
+}
+
+// UpdateClient is a paid mutator transaction binding the contract method 0x0bece356.
+//
+// Solidity: function updateClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClient(&_RelayerFunctions.TransactOpts, data)
+}
+
+// UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
+//
+// Solidity: function upgradeClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpgradeClient(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "upgradeClient", data)
+}
+
+// UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
+//
+// Solidity: function upgradeClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) UpgradeClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpgradeClient(&_RelayerFunctions.TransactOpts, data)
+}
+
+// UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
+//
+// Solidity: function upgradeClient(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpgradeClient(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpgradeClient(&_RelayerFunctions.TransactOpts, data)
+}
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
new file mode 100644
index 0000000000..5fd89b99cc
--- /dev/null
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.4;
+
+interface IRelayerFunctions {
+    function createClient(bytes calldata data) external payable returns (bytes calldata);
+    function updateClient(bytes calldata data) external payable returns (bytes calldata);
+    function upgradeClient(bytes calldata data) external payable returns (bytes calldata);
+    function submitMisbehaviour(bytes calldata data) external payable returns (bytes calldata);
+    function connectionOpenInit(bytes calldata data) external payable returns (bytes calldata);
+    function connectionOpenTry(bytes calldata data) external payable returns (bytes calldata);
+    function connectionOpenAck(bytes calldata data) external payable returns (bytes calldata);
+    function connectionOpenConfirm(bytes calldata data) external payable returns (bytes calldata);
+    function channelOpenInit(bytes calldata data) external payable returns (bytes calldata);
+    function channelOpenTry(bytes calldata data) external payable returns (bytes calldata);
+    function channelOpenAck(bytes calldata data) external payable returns (bytes calldata);
+    function channelOpenConfirm(bytes calldata data) external payable returns (bytes calldata);
+    function recvPacket(bytes calldata data) external payable returns (bytes calldata);
+    function acknowledgement(bytes calldata data) external payable returns (bytes calldata);
+    function timeout(bytes calldata data) external payable returns (bytes calldata);
+    function timeoutOnClose(bytes calldata data) external payable returns (bytes calldata);
+}
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 8154e271ae..55d0c7f722 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -1,41 +1,63 @@
 package precompiles
 
 import (
-	"encoding/binary"
 	"errors"
 
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
 
 	"github.com/cosmos/cosmos-sdk/codec"
+	"github.com/ethereum/go-ethereum/accounts/abi"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
 
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
+	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
 )
 
 var (
+	irelayerABI                abi.ABI
 	relayerContractAddress     = common.BytesToAddress([]byte{101})
-	relayerGasRequiredByMethod = map[int]uint64{}
+	relayerGasRequiredByMethod = map[[4]byte]uint64{}
+)
+
+const (
+	CreateClient          = "createClient"
+	UpdateClient          = "updateClient"
+	UpgradeClient         = "upgradeClient"
+	SubmitMisbehaviour    = "submitMisbehaviour"
+	ConnectionOpenInit    = "connectionOpenInit"
+	ConnectionOpenTry     = "connectionOpenTry"
+	ConnectionOpenAck     = "connectionOpenAck"
+	ConnectionOpenConfirm = "connectionOpenConfirm"
+	ChannelOpenInit       = "channelOpenInit"
+	ChannelOpenTry        = "channelOpenTry"
+	ChannelOpenAck        = "channelOpenAck"
+	ChannelOpenConfirm    = "channelOpenConfirm"
+	RecvPacket            = "recvPacket"
+	Acknowledgement       = "acknowledgement"
+	Timeout               = "timeout"
+	TimeoutOnClose        = "timeoutOnClose"
 )
 
 func init() {
-	relayerGasRequiredByMethod[prefixCreateClient] = 200000
-	relayerGasRequiredByMethod[prefixUpdateClient] = 400000
-	relayerGasRequiredByMethod[prefixUpgradeClient] = 400000
-	relayerGasRequiredByMethod[prefixSubmitMisbehaviour] = 100000
-	relayerGasRequiredByMethod[prefixConnectionOpenInit] = 100000
-	relayerGasRequiredByMethod[prefixConnectionOpenTry] = 100000
-	relayerGasRequiredByMethod[prefixConnectionOpenAck] = 100000
-	relayerGasRequiredByMethod[prefixConnectionOpenConfirm] = 100000
-	relayerGasRequiredByMethod[prefixChannelOpenInit] = 100000
-	relayerGasRequiredByMethod[prefixChannelOpenTry] = 100000
-	relayerGasRequiredByMethod[prefixChannelOpenAck] = 100000
-	relayerGasRequiredByMethod[prefixChannelOpenConfirm] = 100000
-	relayerGasRequiredByMethod[prefixRecvPacket] = 250000
-	relayerGasRequiredByMethod[prefixAcknowledgement] = 250000
-	relayerGasRequiredByMethod[prefixTimeout] = 100000
-	relayerGasRequiredByMethod[prefixTimeoutOnClose] = 100000
+	if err := irelayerABI.UnmarshalJSON([]byte(relayer.RelayerFunctionsMetaData.ABI)); err != nil {
+		panic(err)
+	}
+	for methodName := range irelayerABI.Methods {
+		var methodID [4]byte
+		copy(methodID[:], irelayerABI.Methods[methodName].ID[:4])
+		switch methodName {
+		case CreateClient:
+			relayerGasRequiredByMethod[methodID] = 200000
+		case RecvPacket, Acknowledgement:
+			relayerGasRequiredByMethod[methodID] = 250000
+		case UpdateClient, UpgradeClient:
+			relayerGasRequiredByMethod[methodID] = 400000
+		default:
+			relayerGasRequiredByMethod[methodID] = 100000
+		}
+	}
 }
 
 type RelayerContract struct {
@@ -63,11 +85,9 @@ func (bc *RelayerContract) Address() common.Address {
 func (bc *RelayerContract) RequiredGas(input []byte) uint64 {
 	// base cost to prevent large input size
 	baseCost := uint64(len(input)) * bc.kvGasConfig.WriteCostPerByte
-	if len(input) < prefixSize4Bytes {
-		return 0
-	}
-	prefix := int(binary.LittleEndian.Uint32(input[:prefixSize4Bytes]))
-	requiredGas, ok := relayerGasRequiredByMethod[prefix]
+	var methodID [4]byte
+	copy(methodID[:], input[:4])
+	requiredGas, ok := relayerGasRequiredByMethod[methodID]
 	if ok {
 		return requiredGas + baseCost
 	}
@@ -78,82 +98,58 @@ func (bc *RelayerContract) IsStateful() bool {
 	return true
 }
 
-// prefix bytes for the relayer msg type
-const (
-	prefixSize4Bytes = 4
-	// Client
-	prefixCreateClient = iota + 1
-	prefixUpdateClient
-	prefixUpgradeClient
-	prefixSubmitMisbehaviour
-	// Connection
-	prefixConnectionOpenInit
-	prefixConnectionOpenTry
-	prefixConnectionOpenAck
-	prefixConnectionOpenConfirm
-	// Channel
-	prefixChannelOpenInit
-	prefixChannelOpenTry
-	prefixChannelOpenAck
-	prefixChannelOpenConfirm
-	prefixChannelCloseInit
-	prefixChannelCloseConfirm
-	prefixRecvPacket
-	prefixAcknowledgement
-	prefixTimeout
-	prefixTimeoutOnClose
-)
-
 func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
 	if readonly {
 		return nil, errors.New("the method is not readonly")
 	}
 	// parse input
-	if len(contract.Input) < int(prefixSize4Bytes) {
-		return nil, errors.New("data too short to contain prefix")
+	methodID := contract.Input[:4]
+	method, err := irelayerABI.MethodById(methodID)
+	if err != nil {
+		return nil, err
 	}
-	prefix := int(binary.LittleEndian.Uint32(contract.Input[:prefixSize4Bytes]))
-	input := contract.Input[prefixSize4Bytes:]
 	stateDB := evm.StateDB.(ExtStateDB)
 
-	var (
-		err error
-		res []byte
-	)
+	var res []byte
 	precompileAddr := bc.Address()
+	args, err := method.Inputs.Unpack(contract.Input[4:])
+	if err != nil {
+		return nil, errors.New("fail to unpack input arguments")
+	}
+	input := args[0].([]byte)
 	converter := cronosevents.RelayerConvertEvent
-	switch prefix {
-	case prefixCreateClient:
+	switch method.Name {
+	case CreateClient:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.CreateClient, converter)
-	case prefixUpdateClient:
+	case UpdateClient:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.UpdateClient, converter)
-	case prefixUpgradeClient:
+	case UpgradeClient:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.UpgradeClient, converter)
-	case prefixSubmitMisbehaviour:
+	case SubmitMisbehaviour:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.SubmitMisbehaviour, converter)
-	case prefixConnectionOpenInit:
+	case ConnectionOpenInit:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenInit, converter)
-	case prefixConnectionOpenTry:
+	case ConnectionOpenTry:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenTry, converter)
-	case prefixConnectionOpenAck:
+	case ConnectionOpenAck:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenAck, converter)
-	case prefixConnectionOpenConfirm:
+	case ConnectionOpenConfirm:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenConfirm, converter)
-	case prefixChannelOpenInit:
+	case ChannelOpenInit:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenInit, converter)
-	case prefixChannelOpenTry:
+	case ChannelOpenTry:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenTry, converter)
-	case prefixChannelOpenAck:
+	case ChannelOpenAck:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenAck, converter)
-	case prefixChannelOpenConfirm:
+	case ChannelOpenConfirm:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenConfirm, converter)
-	case prefixRecvPacket:
+	case RecvPacket:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.RecvPacket, converter)
-	case prefixAcknowledgement:
+	case Acknowledgement:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.Acknowledgement, converter)
-	case prefixTimeout:
+	case Timeout:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.Timeout, converter)
-	case prefixTimeoutOnClose:
+	case TimeoutOnClose:
 		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.TimeoutOnClose, converter)
 	default:
 		return nil, errors.New("unknown method")

From 48f11c0f5d338669fdebccdb2b9924c405286f97 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 5 Oct 2023 09:24:03 +0800
Subject: [PATCH 02/25] add executor

---
 x/cronos/keeper/precompiles/relayer.go | 35 ++++++++++++++------------
 x/cronos/keeper/precompiles/utils.go   | 24 ++++++++++--------
 2 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 55d0c7f722..722eb5eb20 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -118,39 +118,42 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	}
 	input := args[0].([]byte)
 	converter := cronosevents.RelayerConvertEvent
+	e := &Executor{
+		bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, converter,
+	}
 	switch method.Name {
 	case CreateClient:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.CreateClient, converter)
+		res, err = exec(e, bc.ibcKeeper.CreateClient)
 	case UpdateClient:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.UpdateClient, converter)
+		res, err = exec(e, bc.ibcKeeper.UpdateClient)
 	case UpgradeClient:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.UpgradeClient, converter)
+		res, err = exec(e, bc.ibcKeeper.UpgradeClient)
 	case SubmitMisbehaviour:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.SubmitMisbehaviour, converter)
+		res, err = exec(e, bc.ibcKeeper.SubmitMisbehaviour)
 	case ConnectionOpenInit:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenInit, converter)
+		res, err = exec(e, bc.ibcKeeper.ConnectionOpenInit)
 	case ConnectionOpenTry:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenTry, converter)
+		res, err = exec(e, bc.ibcKeeper.ConnectionOpenTry)
 	case ConnectionOpenAck:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenAck, converter)
+		res, err = exec(e, bc.ibcKeeper.ConnectionOpenAck)
 	case ConnectionOpenConfirm:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ConnectionOpenConfirm, converter)
+		res, err = exec(e, bc.ibcKeeper.ConnectionOpenConfirm)
 	case ChannelOpenInit:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenInit, converter)
+		res, err = exec(e, bc.ibcKeeper.ChannelOpenInit)
 	case ChannelOpenTry:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenTry, converter)
+		res, err = exec(e, bc.ibcKeeper.ChannelOpenTry)
 	case ChannelOpenAck:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenAck, converter)
+		res, err = exec(e, bc.ibcKeeper.ChannelOpenAck)
 	case ChannelOpenConfirm:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.ChannelOpenConfirm, converter)
+		res, err = exec(e, bc.ibcKeeper.ChannelOpenConfirm)
 	case RecvPacket:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.RecvPacket, converter)
+		res, err = exec(e, bc.ibcKeeper.RecvPacket)
 	case Acknowledgement:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.Acknowledgement, converter)
+		res, err = exec(e, bc.ibcKeeper.Acknowledgement)
 	case Timeout:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.Timeout, converter)
+		res, err = exec(e, bc.ibcKeeper.Timeout)
 	case TimeoutOnClose:
-		res, err = exec(bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, bc.ibcKeeper.TimeoutOnClose, converter)
+		res, err = exec(e, bc.ibcKeeper.TimeoutOnClose)
 	default:
 		return nil, errors.New("unknown method")
 	}
diff --git a/x/cronos/keeper/precompiles/utils.go b/x/cronos/keeper/precompiles/utils.go
index 34c70ceb0d..f463df6c71 100644
--- a/x/cronos/keeper/precompiles/utils.go
+++ b/x/cronos/keeper/precompiles/utils.go
@@ -16,21 +16,25 @@ type NativeMessage interface {
 	GetSigners() []sdk.AccAddress
 }
 
+type Executor struct {
+	cdc       codec.Codec
+	stateDB   ExtStateDB
+	caller    common.Address
+	contract  common.Address
+	input     []byte
+	converter statedb.EventConverter
+}
+
 // exec is a generic function that executes the given action in statedb, and marshal/unmarshal the input/output
 func exec[Req any, PReq interface {
 	*Req
 	NativeMessage
 }, Resp codec.ProtoMarshaler](
-	cdc codec.Codec,
-	stateDB ExtStateDB,
-	caller common.Address,
-	contract common.Address,
-	input []byte,
+	e *Executor,
 	action func(context.Context, PReq) (Resp, error),
-	converter statedb.EventConverter,
 ) ([]byte, error) {
 	msg := PReq(new(Req))
-	if err := cdc.Unmarshal(input, msg); err != nil {
+	if err := e.cdc.Unmarshal(e.input, msg); err != nil {
 		return nil, fmt.Errorf("fail to Unmarshal %T %w", msg, err)
 	}
 
@@ -38,12 +42,12 @@ func exec[Req any, PReq interface {
 	if len(signers) != 1 {
 		return nil, errors.New("don't support multi-signers message")
 	}
-	if common.BytesToAddress(signers[0].Bytes()) != caller {
+	if common.BytesToAddress(signers[0].Bytes()) != e.caller {
 		return nil, errors.New("caller is not authenticated")
 	}
 
 	var res Resp
-	if err := stateDB.ExecuteNativeAction(contract, converter, func(ctx sdk.Context) error {
+	if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
 		var err error
 		res, err = action(ctx, msg)
 		return err
@@ -51,5 +55,5 @@ func exec[Req any, PReq interface {
 		return nil, err
 	}
 
-	return cdc.Marshal(res)
+	return e.cdc.Marshal(res)
 }

From 7c4c82a85f6aaa895334afe3e49ee5a0ab27c4fb Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 5 Oct 2023 09:25:25 +0800
Subject: [PATCH 03/25] Update CHANGELOG.md

Signed-off-by: mmsqe <mavis@crypto.com>
---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1cfa2cf94..69d8be290d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -86,7 +86,7 @@
 - [#1179](https://github.com/crypto-org-chain/cronos/pull/1179) Support blocking addresses in mempool.
 - [#1182](https://github.com/crypto-org-chain/cronos/pull/1182) Bump librocksdb to 8.5.3.
 - [#1183](https://github.com/crypto-org-chain/cronos/pull/1183) Avoid redundant logs added from relayer.
-- [#](https://github.com/crypto-org-chain/cronos/pull/) Make use of binding contract in relayer.
+- [#1193](https://github.com/crypto-org-chain/cronos/pull/1193) Make use of binding contract in relayer.
 
 *April 13, 2023*
 

From ddf6e8d1bac813ff4e05d653d7607b457c02b53b Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 16 Oct 2023 09:29:07 +0800
Subject: [PATCH 04/25] Problem: estimate gas in evm tx is not accurate in
 relayer

---
 integration_tests/ibc_utils.py    |  6 ++++--
 integration_tests/test_ibc_rly.py | 30 +++++++++++++++++++++++-------
 nix/sources.json                  | 10 +++++-----
 3 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/integration_tests/ibc_utils.py b/integration_tests/ibc_utils.py
index a00b3c2986..ebed4980d9 100644
--- a/integration_tests/ibc_utils.py
+++ b/integration_tests/ibc_utils.py
@@ -31,6 +31,7 @@ class IBCNetwork(NamedTuple):
     chainmain: Chainmain
     hermes: Hermes | None
     incentivized: bool
+    proc: subprocess.Popen[bytes] | None
 
 
 def call_hermes_cmd(
@@ -163,6 +164,7 @@ def prepare_network(
         else:
             call_rly_cmd(path, connection_only, version)
 
+        proc = None
         if incentivized:
             # register fee payee
             src_chain = cronos.cosmos_cli()
@@ -183,7 +185,7 @@ def prepare_network(
                 cronos.supervisorctl("start", "relayer-demo")
                 port = hermes.port
             else:
-                subprocess.Popen(
+                proc = subprocess.Popen(
                     [
                         "rly",
                         "start",
@@ -194,7 +196,7 @@ def prepare_network(
                     preexec_fn=os.setsid,
                 )
                 port = 5183
-        yield IBCNetwork(cronos, chainmain, hermes, incentivized)
+        yield IBCNetwork(cronos, chainmain, hermes, incentivized, proc)
         if port:
             wait_for_port(port)
 
diff --git a/integration_tests/test_ibc_rly.py b/integration_tests/test_ibc_rly.py
index 7e32f0c2f1..967fbd6a74 100644
--- a/integration_tests/test_ibc_rly.py
+++ b/integration_tests/test_ibc_rly.py
@@ -1,4 +1,6 @@
 import json
+import os
+import signal
 import subprocess
 
 import pytest
@@ -42,13 +44,27 @@
 @pytest.fixture(scope="module")
 def ibc(request, tmp_path_factory):
     "prepare-network"
-    name = "ibc_rly"
-    path = tmp_path_factory.mktemp(name)
-    yield from prepare_network(
-        path,
-        name,
-        relayer=cluster.Relayer.RLY.value,
-    )
+    path = tmp_path_factory.mktemp("ibc_rly")
+    procs = []
+    try:
+        for network in prepare_network(
+            path,
+            "ibc_rly",
+            relayer=cluster.Relayer.RLY.value,
+        ):
+            if network.proc:
+                procs.append(network.proc)
+                print("append:", network.proc)
+            yield network
+    finally:
+        print("finally:", procs)
+        for proc in procs:
+            try:
+                os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
+            except ProcessLookupError:
+                pass
+            # proc.terminate()
+            proc.wait()
 
 
 def rly_transfer(ibc):
diff --git a/nix/sources.json b/nix/sources.json
index bf51bd3309..1bac7ed3e2 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -123,13 +123,13 @@
     "relayer": {
         "branch": "main",
         "description": "An IBC relayer for ibc-go",
-        "homepage": "https://github.com/crypto-org-chain/relayer",
-        "owner": "crypto-org-chain",
+        "homepage": "https://github.com/mmsqe/relayer",
+        "owner": "mmsqe",
         "repo": "relayer",
-        "rev": "f202a264463e9d5829398f6be50bff990421b483",
-        "sha256": "08x4bhwglx12rp78gs4hzgp2cywzqwr7gghk1kxasmvy9z0qxp92",
+        "rev": "723e4785841a5e2e274929d6a8c2bebd8d4d2760",
+        "sha256": "0ghf98vmaz80nr519n559b4snwgz3kvds9b2wvzdj02cyprbrfhv",
         "type": "tarball",
-        "url": "https://github.com/crypto-org-chain/relayer/archive/f202a264463e9d5829398f6be50bff990421b483.tar.gz",
+        "url": "https://github.com/mmsqe/relayer/archive/723e4785841a5e2e274929d6a8c2bebd8d4d2760.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     }
 }

From 214d81927a49ae4aa48cc920bcdb1bfb8de219e2 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Tue, 17 Oct 2023 10:58:27 +0800
Subject: [PATCH 05/25] try continuous state changes

---
 .../relayer/i_relayer_functions.abigen.go     |  86 +++++++++++-
 .../events/bindings/src/RelayerFunctions.sol  |   4 +
 x/cronos/keeper/precompiles/relayer.go        | 125 +++++++++++++++---
 3 files changed, 198 insertions(+), 17 deletions(-)

diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
index cf2ee241a6..a24626979d 100644
--- a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -30,7 +30,7 @@ var (
 
 // RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
 var RelayerFunctionsMetaData = &bind.MetaData{
-	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
 }
 
 // RelayerFunctionsABI is the input ABI used to generate the binding from.
@@ -494,6 +494,90 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClient(data []
 	return _RelayerFunctions.Contract.UpdateClient(&_RelayerFunctions.TransactOpts, data)
 }
 
+// UpdateClientAndChannelOpenConfirm is a paid mutator transaction binding the contract method 0x0982b806.
+//
+// Solidity: function updateClientAndChannelOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelOpenConfirm(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelOpenConfirm", data1, data2)
+}
+
+// UpdateClientAndChannelOpenConfirm is a paid mutator transaction binding the contract method 0x0982b806.
+//
+// Solidity: function updateClientAndChannelOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelOpenConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelOpenConfirm is a paid mutator transaction binding the contract method 0x0982b806.
+//
+// Solidity: function updateClientAndChannelOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelOpenConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelOpenTry is a paid mutator transaction binding the contract method 0x33978088.
+//
+// Solidity: function updateClientAndChannelOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelOpenTry(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelOpenTry", data1, data2)
+}
+
+// UpdateClientAndChannelOpenTry is a paid mutator transaction binding the contract method 0x33978088.
+//
+// Solidity: function updateClientAndChannelOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelOpenTry(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelOpenTry is a paid mutator transaction binding the contract method 0x33978088.
+//
+// Solidity: function updateClientAndChannelOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelOpenTry(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenConfirm is a paid mutator transaction binding the contract method 0x70009dfc.
+//
+// Solidity: function updateClientAndConnectionOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndConnectionOpenConfirm(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndConnectionOpenConfirm", data1, data2)
+}
+
+// UpdateClientAndConnectionOpenConfirm is a paid mutator transaction binding the contract method 0x70009dfc.
+//
+// Solidity: function updateClientAndConnectionOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndConnectionOpenConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenConfirm is a paid mutator transaction binding the contract method 0x70009dfc.
+//
+// Solidity: function updateClientAndConnectionOpenConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConnectionOpenConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenTry is a paid mutator transaction binding the contract method 0x5f3a7169.
+//
+// Solidity: function updateClientAndConnectionOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndConnectionOpenTry(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndConnectionOpenTry", data1, data2)
+}
+
+// UpdateClientAndConnectionOpenTry is a paid mutator transaction binding the contract method 0x5f3a7169.
+//
+// Solidity: function updateClientAndConnectionOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndConnectionOpenTry(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenTry is a paid mutator transaction binding the contract method 0x5f3a7169.
+//
+// Solidity: function updateClientAndConnectionOpenTry(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConnectionOpenTry(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
 //
 // Solidity: function upgradeClient(bytes data) payable returns(bytes)
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
index 5fd89b99cc..1d3b6b0349 100644
--- a/x/cronos/events/bindings/src/RelayerFunctions.sol
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -18,4 +18,8 @@ interface IRelayerFunctions {
     function acknowledgement(bytes calldata data) external payable returns (bytes calldata);
     function timeout(bytes calldata data) external payable returns (bytes calldata);
     function timeoutOnClose(bytes calldata data) external payable returns (bytes calldata);
+    function updateClientAndConnectionOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndConnectionOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
 }
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 722eb5eb20..b15474cf16 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -2,14 +2,19 @@ package precompiles
 
 import (
 	"errors"
+	"fmt"
 
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
+	sdk "github.com/cosmos/cosmos-sdk/types"
 
 	"github.com/cosmos/cosmos-sdk/codec"
 	"github.com/ethereum/go-ethereum/accounts/abi"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
 
+	clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+	connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
+	channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
@@ -22,22 +27,26 @@ var (
 )
 
 const (
-	CreateClient          = "createClient"
-	UpdateClient          = "updateClient"
-	UpgradeClient         = "upgradeClient"
-	SubmitMisbehaviour    = "submitMisbehaviour"
-	ConnectionOpenInit    = "connectionOpenInit"
-	ConnectionOpenTry     = "connectionOpenTry"
-	ConnectionOpenAck     = "connectionOpenAck"
-	ConnectionOpenConfirm = "connectionOpenConfirm"
-	ChannelOpenInit       = "channelOpenInit"
-	ChannelOpenTry        = "channelOpenTry"
-	ChannelOpenAck        = "channelOpenAck"
-	ChannelOpenConfirm    = "channelOpenConfirm"
-	RecvPacket            = "recvPacket"
-	Acknowledgement       = "acknowledgement"
-	Timeout               = "timeout"
-	TimeoutOnClose        = "timeoutOnClose"
+	CreateClient                         = "createClient"
+	UpdateClient                         = "updateClient"
+	UpgradeClient                        = "upgradeClient"
+	SubmitMisbehaviour                   = "submitMisbehaviour"
+	ConnectionOpenInit                   = "connectionOpenInit"
+	ConnectionOpenTry                    = "connectionOpenTry"
+	ConnectionOpenAck                    = "connectionOpenAck"
+	ConnectionOpenConfirm                = "connectionOpenConfirm"
+	ChannelOpenInit                      = "channelOpenInit"
+	ChannelOpenTry                       = "channelOpenTry"
+	ChannelOpenAck                       = "channelOpenAck"
+	ChannelOpenConfirm                   = "channelOpenConfirm"
+	RecvPacket                           = "recvPacket"
+	Acknowledgement                      = "acknowledgement"
+	Timeout                              = "timeout"
+	TimeoutOnClose                       = "timeoutOnClose"
+	UpdateClientAndConnectionOpenTry     = "updateClientAndConnectionOpenTry"
+	UpdateClientAndConnectionOpenConfirm = "updateClientAndConnectionOpenConfirm"
+	UpdateClientAndChannelOpenTry        = "updateClientAndChannelOpenTry"
+	UpdateClientAndChannelOpenConfirm    = "updateClientAndChannelOpenConfirm"
 )
 
 func init() {
@@ -154,6 +163,90 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		res, err = exec(e, bc.ibcKeeper.Timeout)
 	case TimeoutOnClose:
 		res, err = exec(e, bc.ibcKeeper.TimeoutOnClose)
+	case UpdateClientAndConnectionOpenTry:
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 connectiontypes.MsgConnectionOpenTry
+			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err = bc.ibcKeeper.ConnectionOpenTry(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ConnectionOpenTry %w", err)
+			}
+			return err
+		}); err != nil {
+			return nil, err
+		}
+	case UpdateClientAndConnectionOpenConfirm:
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 connectiontypes.MsgConnectionOpenConfirm
+			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err := bc.ibcKeeper.ConnectionOpenConfirm(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ConnectionOpenConfirm %w", err)
+			}
+			return err
+		}); err != nil {
+			return nil, err
+		}
+	case UpdateClientAndChannelOpenTry:
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 channeltypes.MsgChannelOpenTry
+			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err := bc.ibcKeeper.ChannelOpenTry(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ChannelOpenTry %w", err)
+			}
+			return err
+		}); err != nil {
+			return nil, err
+		}
+	case UpdateClientAndChannelOpenConfirm:
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 channeltypes.MsgChannelOpenConfirm
+			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
+			}
+			return err
+		}); err != nil {
+			return nil, err
+		}
 	default:
 		return nil, errors.New("unknown method")
 	}

From 65eebef7ba9397a611d8234d82c9cad41d678279 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Tue, 17 Oct 2023 11:00:23 +0800
Subject: [PATCH 06/25] add execMultiple

---
 x/cronos/keeper/precompiles/relayer.go | 99 ++++----------------------
 x/cronos/keeper/precompiles/utils.go   | 50 +++++++++++++
 2 files changed, 63 insertions(+), 86 deletions(-)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index b15474cf16..9c9e45a389 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -2,19 +2,14 @@ package precompiles
 
 import (
 	"errors"
-	"fmt"
 
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
-	sdk "github.com/cosmos/cosmos-sdk/types"
 
 	"github.com/cosmos/cosmos-sdk/codec"
 	"github.com/ethereum/go-ethereum/accounts/abi"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
 
-	clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
-	connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
-	channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
@@ -128,7 +123,15 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	input := args[0].([]byte)
 	converter := cronosevents.RelayerConvertEvent
 	e := &Executor{
-		bc.cdc, stateDB, contract.CallerAddress, precompileAddr, input, converter,
+		cdc:       bc.cdc,
+		stateDB:   stateDB,
+		caller:    contract.CallerAddress,
+		contract:  precompileAddr,
+		input:     input,
+		converter: converter,
+	}
+	if len(args) > 1 {
+		e.input2 = args[1].([]byte)
 	}
 	switch method.Name {
 	case CreateClient:
@@ -164,89 +167,13 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	case TimeoutOnClose:
 		res, err = exec(e, bc.ibcKeeper.TimeoutOnClose)
 	case UpdateClientAndConnectionOpenTry:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			var msg1 connectiontypes.MsgConnectionOpenTry
-			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err = bc.ibcKeeper.ConnectionOpenTry(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ConnectionOpenTry %w", err)
-			}
-			return err
-		}); err != nil {
-			return nil, err
-		}
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenTry)
 	case UpdateClientAndConnectionOpenConfirm:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			var msg1 connectiontypes.MsgConnectionOpenConfirm
-			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err := bc.ibcKeeper.ConnectionOpenConfirm(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ConnectionOpenConfirm %w", err)
-			}
-			return err
-		}); err != nil {
-			return nil, err
-		}
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenConfirm)
 	case UpdateClientAndChannelOpenTry:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			var msg1 channeltypes.MsgChannelOpenTry
-			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err := bc.ibcKeeper.ChannelOpenTry(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ChannelOpenTry %w", err)
-			}
-			return err
-		}); err != nil {
-			return nil, err
-		}
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenTry)
 	case UpdateClientAndChannelOpenConfirm:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			var msg1 channeltypes.MsgChannelOpenConfirm
-			if err := e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
-			}
-			return err
-		}); err != nil {
-			return nil, err
-		}
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenConfirm)
 	default:
 		return nil, errors.New("unknown method")
 	}
diff --git a/x/cronos/keeper/precompiles/utils.go b/x/cronos/keeper/precompiles/utils.go
index f463df6c71..5a0dff75ba 100644
--- a/x/cronos/keeper/precompiles/utils.go
+++ b/x/cronos/keeper/precompiles/utils.go
@@ -22,6 +22,7 @@ type Executor struct {
 	caller    common.Address
 	contract  common.Address
 	input     []byte
+	input2    []byte
 	converter statedb.EventConverter
 }
 
@@ -57,3 +58,52 @@ func exec[Req any, PReq interface {
 
 	return e.cdc.Marshal(res)
 }
+
+func execMultiple[Req any,
+	PReq interface {
+		*Req
+		NativeMessage
+	},
+	Resp codec.ProtoMarshaler,
+	Req2 any,
+	PReq2 interface {
+		*Req2
+		NativeMessage
+	},
+	Resp2 codec.ProtoMarshaler,
+](
+	e *Executor,
+	action func(context.Context, PReq) (Resp, error),
+	action2 func(context.Context, PReq2) (Resp2, error),
+) ([]byte, error) {
+	msg := PReq(new(Req))
+	if err := e.cdc.Unmarshal(e.input, msg); err != nil {
+		return nil, fmt.Errorf("fail to Unmarshal %T %w", msg, err)
+	}
+
+	msg2 := PReq2(new(Req2))
+	if err := e.cdc.Unmarshal(e.input2, msg2); err != nil {
+		return nil, fmt.Errorf("fail to Unmarshal %T %w", msg2, err)
+	}
+
+	signers := msg.GetSigners()
+	if len(signers) != 1 {
+		return nil, errors.New("don't support multi-signers message")
+	}
+	if common.BytesToAddress(signers[0].Bytes()) != e.caller {
+		return nil, errors.New("caller is not authenticated")
+	}
+
+	var res Resp
+	if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+		var err error
+		res, err = action(ctx, msg)
+		if err == nil && len(e.input2) > 0 {
+			_, err = action2(ctx, msg2)
+		}
+		return err
+	}); err != nil {
+		return nil, err
+	}
+	return e.cdc.Marshal(res)
+}

From ee480351f61466be4748802155b3b530736f1820 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 19 Oct 2023 15:28:25 +0800
Subject: [PATCH 07/25] pass capability check

---
 app/app.go                             |   2 +-
 x/cronos/keeper/precompiles/relayer.go | 101 ++++++++++++++++++++++---
 2 files changed, 92 insertions(+), 11 deletions(-)

diff --git a/app/app.go b/app/app.go
index b764b33675..10ea03e7a3 100644
--- a/app/app.go
+++ b/app/app.go
@@ -553,7 +553,7 @@ func New(
 		tracer,
 		evmS,
 		[]vm.PrecompiledContract{
-			cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec, gasConfig),
+			cronosprecompiles.NewRelayerContract(app.IBCKeeper, &app.ScopedIBCKeeper, memKeys, appCodec, gasConfig),
 			cronosprecompiles.NewIcaContract(&app.ICAAuthKeeper, &app.CronosKeeper, appCodec, gasConfig),
 		},
 		allKeys,
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 9c9e45a389..45ce3025b4 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -2,6 +2,7 @@ package precompiles
 
 import (
 	"errors"
+	"fmt"
 
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
 
@@ -10,6 +11,12 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
 
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
+	capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
+	clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
+	channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+	"github.com/cosmos/ibc-go/v7/modules/core/exported"
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
@@ -67,17 +74,21 @@ func init() {
 type RelayerContract struct {
 	BaseContract
 
-	cdc         codec.Codec
-	ibcKeeper   *ibckeeper.Keeper
-	kvGasConfig storetypes.GasConfig
+	cdc             codec.Codec
+	ibcKeeper       *ibckeeper.Keeper
+	scopedIBCKeeper *capabilitykeeper.ScopedKeeper
+	memKeys         map[string]*storetypes.MemoryStoreKey
+	kvGasConfig     storetypes.GasConfig
 }
 
-func NewRelayerContract(ibcKeeper *ibckeeper.Keeper, cdc codec.Codec, kvGasConfig storetypes.GasConfig) vm.PrecompiledContract {
+func NewRelayerContract(ibcKeeper *ibckeeper.Keeper, scopedIBCKeeper *capabilitykeeper.ScopedKeeper, memKeys map[string]*storetypes.MemoryStoreKey, cdc codec.Codec, kvGasConfig storetypes.GasConfig) vm.PrecompiledContract {
 	return &RelayerContract{
-		BaseContract: NewBaseContract(relayerContractAddress),
-		ibcKeeper:    ibcKeeper,
-		cdc:          cdc,
-		kvGasConfig:  kvGasConfig,
+		BaseContract:    NewBaseContract(relayerContractAddress),
+		ibcKeeper:       ibcKeeper,
+		scopedIBCKeeper: scopedIBCKeeper,
+		memKeys:         memKeys,
+		cdc:             cdc,
+		kvGasConfig:     kvGasConfig,
 	}
 }
 
@@ -102,6 +113,15 @@ func (bc *RelayerContract) IsStateful() bool {
 	return true
 }
 
+func (bc *RelayerContract) findMemkey() *storetypes.MemoryStoreKey {
+	for _, m := range bc.memKeys {
+		if m.Name() == capabilitytypes.MemStoreKey {
+			return m
+		}
+	}
+	return nil
+}
+
 func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
 	if readonly {
 		return nil, errors.New("the method is not readonly")
@@ -133,6 +153,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	if len(args) > 1 {
 		e.input2 = args[1].([]byte)
 	}
+	memKey := bc.findMemkey()
 	switch method.Name {
 	case CreateClient:
 		res, err = exec(e, bc.ibcKeeper.CreateClient)
@@ -171,9 +192,69 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	case UpdateClientAndConnectionOpenConfirm:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenConfirm)
 	case UpdateClientAndChannelOpenTry:
-		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenTry)
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			memStore := ctx.KVStore(memKey)
+			index := uint64(1)
+			name := "ports/transfer"
+			key := []byte(fmt.Sprintf("ibc/rev/%s", name))
+			memStore.Set(key, sdk.Uint64ToBigEndian(index))
+			cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, name)
+			if !ok {
+				return fmt.Errorf("fail to find cap for %s", name)
+			}
+			key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
+			memStore.Set(key, []byte(name))
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 channeltypes.MsgChannelOpenTry
+			if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err := bc.ibcKeeper.ChannelOpenTry(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ChannelOpenTry %w", err)
+			}
+			return nil
+		}); err != nil {
+			return nil, err
+		}
 	case UpdateClientAndChannelOpenConfirm:
-		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenConfirm)
+		var msg0 clienttypes.MsgUpdateClient
+		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
+			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
+		}
+		input1 := args[1].([]byte)
+		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
+			memStore := ctx.KVStore(memKey)
+			index := uint64(2)
+			name := "capabilities/ports/transfer/channels/channel-0"
+			key := []byte(fmt.Sprintf("ibc/rev/%s", name))
+			memStore.Set(key, sdk.Uint64ToBigEndian(index))
+			cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, name)
+			key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
+			if !ok {
+				return fmt.Errorf("fail to find cap for %s", name)
+			}
+			memStore.Set(key, []byte(name))
+			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
+				return fmt.Errorf("fail to UpdateClient %w", err)
+			}
+			var msg1 channeltypes.MsgChannelOpenConfirm
+			if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
+				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+			}
+			if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
+				return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
+			}
+			return nil
+		}); err != nil {
+			return nil, err
+		}
 	default:
 		return nil, errors.New("unknown method")
 	}

From 9f8c340e8038f0eaf4fe6c9de47cab5b6dd13895 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 19 Oct 2023 15:30:48 +0800
Subject: [PATCH 08/25] add updateClientAndRecvPacket to combos

---
 .../relayer/i_relayer_functions.abigen.go     | 23 ++++++++++++++++-
 .../events/bindings/src/RelayerFunctions.sol  |  1 +
 x/cronos/keeper/precompiles/relayer.go        | 25 +++++++++++++------
 3 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
index a24626979d..d05c0b04b0 100644
--- a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -30,7 +30,7 @@ var (
 
 // RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
 var RelayerFunctionsMetaData = &bind.MetaData{
-	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
 }
 
 // RelayerFunctionsABI is the input ABI used to generate the binding from.
@@ -578,6 +578,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConne
 	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndRecvPacket is a paid mutator transaction binding the contract method 0xd3cffc28.
+//
+// Solidity: function updateClientAndRecvPacket(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndRecvPacket(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndRecvPacket", data1, data2)
+}
+
+// UpdateClientAndRecvPacket is a paid mutator transaction binding the contract method 0xd3cffc28.
+//
+// Solidity: function updateClientAndRecvPacket(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndRecvPacket(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndRecvPacket(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndRecvPacket is a paid mutator transaction binding the contract method 0xd3cffc28.
+//
+// Solidity: function updateClientAndRecvPacket(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndRecvPacket(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndRecvPacket(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
 //
 // Solidity: function upgradeClient(bytes data) payable returns(bytes)
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
index 1d3b6b0349..1f709111d4 100644
--- a/x/cronos/events/bindings/src/RelayerFunctions.sol
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -22,4 +22,5 @@ interface IRelayerFunctions {
     function updateClientAndConnectionOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndChannelOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndChannelOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndRecvPacket(bytes calldata data1, bytes calldata data2) external payable returns (bool);
 }
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 45ce3025b4..8c6cea6b19 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -49,6 +49,7 @@ const (
 	UpdateClientAndConnectionOpenConfirm = "updateClientAndConnectionOpenConfirm"
 	UpdateClientAndChannelOpenTry        = "updateClientAndChannelOpenTry"
 	UpdateClientAndChannelOpenConfirm    = "updateClientAndChannelOpenConfirm"
+	UpdateClientAndRecvPacket            = "updateClientAndRecvPacket"
 )
 
 func init() {
@@ -223,7 +224,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		}); err != nil {
 			return nil, err
 		}
-	case UpdateClientAndChannelOpenConfirm:
+	case UpdateClientAndChannelOpenConfirm, UpdateClientAndRecvPacket:
 		var msg0 clienttypes.MsgUpdateClient
 		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
 			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
@@ -244,12 +245,22 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
 				return fmt.Errorf("fail to UpdateClient %w", err)
 			}
-			var msg1 channeltypes.MsgChannelOpenConfirm
-			if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
+			if method.Name == UpdateClientAndChannelOpenConfirm {
+				var msg1 channeltypes.MsgChannelOpenConfirm
+				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
+					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+				}
+				if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
+					return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
+				}
+			} else {
+				var msg1 channeltypes.MsgRecvPacket
+				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
+					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+				}
+				if _, err := bc.ibcKeeper.RecvPacket(ctx, &msg1); err != nil {
+					return fmt.Errorf("fail to RecvPacket %w", err)
+				}
 			}
 			return nil
 		}); err != nil {

From 4c48569266588677c198c79f68a839699c6fc12c Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 19 Oct 2023 15:32:44 +0800
Subject: [PATCH 09/25] test less

---
 scripts/run-integration-tests | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/run-integration-tests b/scripts/run-integration-tests
index ffd159b251..ef3db807d4 100755
--- a/scripts/run-integration-tests
+++ b/scripts/run-integration-tests
@@ -10,4 +10,4 @@ cd ../integration_tests/contracts
 HUSKY_SKIP_INSTALL=1 npm install
 npm run typechain
 cd ..
-nix-shell --run "pytest -vv -s"
\ No newline at end of file
+nix-shell --run "pytest -v -s test_ibc_rly.py::test_ibc"
\ No newline at end of file

From 2bbd1e32f6f476497cd8c7a36e827f29bca9fff5 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 19 Oct 2023 15:37:21 +0800
Subject: [PATCH 10/25] update rly

---
 nix/sources.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/nix/sources.json b/nix/sources.json
index 6c4dfcf0dd..d2a895f0e7 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -126,10 +126,10 @@
         "homepage": "https://github.com/mmsqe/relayer",
         "owner": "mmsqe",
         "repo": "relayer",
-        "rev": "468fc43e0fa97794f6cfd5b5156d8f5093eb59e0",
-        "sha256": "1fnydlpbqbfy7i9k1kf04v4jli8g4hn20xf1ccqyiv91nq6h8zzj",
+        "rev": "54126405d4d9182ced43c1437dfd11887c955aa5",
+        "sha256": "1grhrzg6gphqayqhxapdp7y278xiw5iz8c2r40gjaqcwiqjnpkgp",
         "type": "tarball",
-        "url": "https://github.com/mmsqe/relayer/archive/468fc43e0fa97794f6cfd5b5156d8f5093eb59e0.tar.gz",
+        "url": "https://github.com/mmsqe/relayer/archive/54126405d4d9182ced43c1437dfd11887c955aa5.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     }
 }

From 06f2b77d27e98a621684560c40410bf8e9510a04 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Fri, 20 Oct 2023 09:19:08 +0800
Subject: [PATCH 11/25] add updateClientAndAcknowledgement

---
 .../relayer/i_relayer_functions.abigen.go     | 23 ++++++++++++++++++-
 .../events/bindings/src/RelayerFunctions.sol  |  1 +
 x/cronos/keeper/precompiles/relayer.go        | 13 +++++++++--
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
index d05c0b04b0..f39dbbcb1d 100644
--- a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -30,7 +30,7 @@ var (
 
 // RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
 var RelayerFunctionsMetaData = &bind.MetaData{
-	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndAcknowledgement\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
 }
 
 // RelayerFunctionsABI is the input ABI used to generate the binding from.
@@ -494,6 +494,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClient(data []
 	return _RelayerFunctions.Contract.UpdateClient(&_RelayerFunctions.TransactOpts, data)
 }
 
+// UpdateClientAndAcknowledgement is a paid mutator transaction binding the contract method 0x65a939c6.
+//
+// Solidity: function updateClientAndAcknowledgement(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndAcknowledgement(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndAcknowledgement", data1, data2)
+}
+
+// UpdateClientAndAcknowledgement is a paid mutator transaction binding the contract method 0x65a939c6.
+//
+// Solidity: function updateClientAndAcknowledgement(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndAcknowledgement(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndAcknowledgement(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndAcknowledgement is a paid mutator transaction binding the contract method 0x65a939c6.
+//
+// Solidity: function updateClientAndAcknowledgement(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndAcknowledgement(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndAcknowledgement(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndChannelOpenConfirm is a paid mutator transaction binding the contract method 0x0982b806.
 //
 // Solidity: function updateClientAndChannelOpenConfirm(bytes data1, bytes data2) payable returns(bool)
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
index 1f709111d4..831a3d0a27 100644
--- a/x/cronos/events/bindings/src/RelayerFunctions.sol
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -23,4 +23,5 @@ interface IRelayerFunctions {
     function updateClientAndChannelOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndChannelOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndRecvPacket(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndAcknowledgement(bytes calldata data1, bytes calldata data2) external payable returns (bool);
 }
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 8c6cea6b19..2b29fd483e 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -50,6 +50,7 @@ const (
 	UpdateClientAndChannelOpenTry        = "updateClientAndChannelOpenTry"
 	UpdateClientAndChannelOpenConfirm    = "updateClientAndChannelOpenConfirm"
 	UpdateClientAndRecvPacket            = "updateClientAndRecvPacket"
+	UpdateClientAndAcknowledgement       = "updateClientAndAcknowledgement"
 )
 
 func init() {
@@ -224,7 +225,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		}); err != nil {
 			return nil, err
 		}
-	case UpdateClientAndChannelOpenConfirm, UpdateClientAndRecvPacket:
+	case UpdateClientAndChannelOpenConfirm, UpdateClientAndRecvPacket, UpdateClientAndAcknowledgement:
 		var msg0 clienttypes.MsgUpdateClient
 		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
 			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
@@ -253,7 +254,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 				if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
 					return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
 				}
-			} else {
+			} else if method.Name == UpdateClientAndRecvPacket {
 				var msg1 channeltypes.MsgRecvPacket
 				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
 					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
@@ -261,6 +262,14 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 				if _, err := bc.ibcKeeper.RecvPacket(ctx, &msg1); err != nil {
 					return fmt.Errorf("fail to RecvPacket %w", err)
 				}
+			} else {
+				var msg1 channeltypes.MsgAcknowledgement
+				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
+					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
+				}
+				if _, err := bc.ibcKeeper.Acknowledgement(ctx, &msg1); err != nil {
+					return fmt.Errorf("fail to Acknowledgement %w", err)
+				}
 			}
 			return nil
 		}); err != nil {

From cc3014f6c15b62a3f16df29d52fc9dce9efa73bf Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Thu, 19 Oct 2023 22:34:02 +0800
Subject: [PATCH 12/25] execMultipleWithHooks with preAction

---
 x/cronos/keeper/precompiles/relayer.go | 141 +++++++++++--------------
 x/cronos/keeper/precompiles/utils.go   |  34 +++++-
 2 files changed, 89 insertions(+), 86 deletions(-)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 2b29fd483e..1a875502ab 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -15,7 +15,8 @@ import (
 	capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
 	capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
 	clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
-	channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+	"github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
+	host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
 	"github.com/cosmos/ibc-go/v7/modules/core/exported"
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
@@ -124,6 +125,24 @@ func (bc *RelayerContract) findMemkey() *storetypes.MemoryStoreKey {
 	return nil
 }
 
+func (bc *RelayerContract) setMemStoreKeys(
+	ctx sdk.Context,
+	memKey storetypes.StoreKey,
+	index uint64,
+	keyName string,
+) error {
+	memStore := ctx.KVStore(memKey)
+	key := []byte(fmt.Sprintf("ibc/rev/%s", keyName))
+	memStore.Set(key, sdk.Uint64ToBigEndian(index))
+	cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, keyName)
+	if !ok {
+		return fmt.Errorf("fail to find cap for %s", keyName)
+	}
+	key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
+	memStore.Set(key, []byte(keyName))
+	return nil
+}
+
 func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
 	if readonly {
 		return nil, errors.New("the method is not readonly")
@@ -194,87 +213,45 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	case UpdateClientAndConnectionOpenConfirm:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenConfirm)
 	case UpdateClientAndChannelOpenTry:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			memStore := ctx.KVStore(memKey)
-			index := uint64(1)
-			name := "ports/transfer"
-			key := []byte(fmt.Sprintf("ibc/rev/%s", name))
-			memStore.Set(key, sdk.Uint64ToBigEndian(index))
-			cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, name)
-			if !ok {
-				return fmt.Errorf("fail to find cap for %s", name)
-			}
-			key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
-			memStore.Set(key, []byte(name))
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			var msg1 channeltypes.MsgChannelOpenTry
-			if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
-				return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-			}
-			if _, err := bc.ibcKeeper.ChannelOpenTry(ctx, &msg1); err != nil {
-				return fmt.Errorf("fail to ChannelOpenTry %w", err)
-			}
-			return nil
-		}); err != nil {
-			return nil, err
-		}
-	case UpdateClientAndChannelOpenConfirm, UpdateClientAndRecvPacket, UpdateClientAndAcknowledgement:
-		var msg0 clienttypes.MsgUpdateClient
-		if err := e.cdc.Unmarshal(input, &msg0); err != nil {
-			return nil, fmt.Errorf("fail to Unmarshal %T %w", msg0, err)
-		}
-		input1 := args[1].([]byte)
-		if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-			memStore := ctx.KVStore(memKey)
-			index := uint64(2)
-			name := "capabilities/ports/transfer/channels/channel-0"
-			key := []byte(fmt.Sprintf("ibc/rev/%s", name))
-			memStore.Set(key, sdk.Uint64ToBigEndian(index))
-			cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, name)
-			key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
-			if !ok {
-				return fmt.Errorf("fail to find cap for %s", name)
-			}
-			memStore.Set(key, []byte(name))
-			if _, err := bc.ibcKeeper.UpdateClient(ctx, &msg0); err != nil {
-				return fmt.Errorf("fail to UpdateClient %w", err)
-			}
-			if method.Name == UpdateClientAndChannelOpenConfirm {
-				var msg1 channeltypes.MsgChannelOpenConfirm
-				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
-					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-				}
-				if _, err := bc.ibcKeeper.ChannelOpenConfirm(ctx, &msg1); err != nil {
-					return fmt.Errorf("fail to ChannelOpenConfirm %w", err)
-				}
-			} else if method.Name == UpdateClientAndRecvPacket {
-				var msg1 channeltypes.MsgRecvPacket
-				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
-					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-				}
-				if _, err := bc.ibcKeeper.RecvPacket(ctx, &msg1); err != nil {
-					return fmt.Errorf("fail to RecvPacket %w", err)
-				}
-			} else {
-				var msg1 channeltypes.MsgAcknowledgement
-				if err = e.cdc.Unmarshal(input1, &msg1); err != nil {
-					return fmt.Errorf("fail to Unmarshal %T %w", msg1, err)
-				}
-				if _, err := bc.ibcKeeper.Acknowledgement(ctx, &msg1); err != nil {
-					return fmt.Errorf("fail to Acknowledgement %w", err)
-				}
-			}
-			return nil
-		}); err != nil {
-			return nil, err
-		}
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcot *types.MsgChannelOpenTry) error {
+				keyName := host.PortPath(mcot.PortId)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(1), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.ChannelOpenTry,
+		)
+	case UpdateClientAndChannelOpenConfirm:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoc *types.MsgChannelOpenConfirm) error {
+				keyName := host.ChannelCapabilityPath(mcoc.PortId, mcoc.ChannelId)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.ChannelOpenConfirm,
+		)
+	case UpdateClientAndRecvPacket:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mrp *types.MsgRecvPacket) error {
+				keyName := host.ChannelCapabilityPath(mrp.Packet.DestinationPort, mrp.Packet.DestinationChannel)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.RecvPacket,
+		)
+	case UpdateClientAndAcknowledgement:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mack *types.MsgAcknowledgement) error {
+				keyName := host.ChannelCapabilityPath(mack.Packet.DestinationPort, mack.Packet.DestinationChannel)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.Acknowledgement,
+		)
 	default:
 		return nil, errors.New("unknown method")
 	}
diff --git a/x/cronos/keeper/precompiles/utils.go b/x/cronos/keeper/precompiles/utils.go
index 5a0dff75ba..fc60b3d26a 100644
--- a/x/cronos/keeper/precompiles/utils.go
+++ b/x/cronos/keeper/precompiles/utils.go
@@ -59,7 +59,7 @@ func exec[Req any, PReq interface {
 	return e.cdc.Marshal(res)
 }
 
-func execMultiple[Req any,
+func execMultipleWithHooks[Req any,
 	PReq interface {
 		*Req
 		NativeMessage
@@ -73,6 +73,7 @@ func execMultiple[Req any,
 	Resp2 codec.ProtoMarshaler,
 ](
 	e *Executor,
+	preAction func(sdk.Context, PReq, PReq2) error,
 	action func(context.Context, PReq) (Resp, error),
 	action2 func(context.Context, PReq2) (Resp2, error),
 ) ([]byte, error) {
@@ -95,15 +96,40 @@ func execMultiple[Req any,
 	}
 
 	var res Resp
-	if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) error {
-		var err error
+	if err := e.stateDB.ExecuteNativeAction(e.contract, e.converter, func(ctx sdk.Context) (err error) {
+		if preAction != nil {
+			if err = preAction(ctx, msg, msg2); err != nil {
+				return err
+			}
+		}
+
 		res, err = action(ctx, msg)
 		if err == nil && len(e.input2) > 0 {
 			_, err = action2(ctx, msg2)
 		}
-		return err
+		return
 	}); err != nil {
 		return nil, err
 	}
 	return e.cdc.Marshal(res)
 }
+
+func execMultiple[Req any,
+	PReq interface {
+		*Req
+		NativeMessage
+	},
+	Resp codec.ProtoMarshaler,
+	Req2 any,
+	PReq2 interface {
+		*Req2
+		NativeMessage
+	},
+	Resp2 codec.ProtoMarshaler,
+](
+	e *Executor,
+	action func(context.Context, PReq) (Resp, error),
+	action2 func(context.Context, PReq2) (Resp2, error),
+) ([]byte, error) {
+	return execMultipleWithHooks(e, nil, action, action2)
+}

From 97840ba90d16cad588fe8db16f637f4875427573 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Fri, 20 Oct 2023 09:22:23 +0800
Subject: [PATCH 13/25] fix channel capability key name

---
 x/cronos/keeper/precompiles/relayer.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 1a875502ab..d4629b1cb4 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -246,7 +246,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		res, err = execMultipleWithHooks(
 			e,
 			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mack *types.MsgAcknowledgement) error {
-				keyName := host.ChannelCapabilityPath(mack.Packet.DestinationPort, mack.Packet.DestinationChannel)
+				keyName := host.ChannelCapabilityPath(mack.Packet.SourcePort, mack.Packet.SourceChannel)
 				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
 			},
 			bc.ibcKeeper.UpdateClient,

From 4af0a81ef18ca6ff512e8b05349bb1d3e9382abb Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Fri, 20 Oct 2023 09:22:36 +0800
Subject: [PATCH 14/25] add rest methods

---
 integration_tests/test_ibc_rly.py             |   5 +-
 .../relayer/i_relayer_functions.abigen.go     | 107 +++++++++++++++++-
 .../events/bindings/src/RelayerFunctions.sol  |   5 +
 x/cronos/keeper/precompiles/relayer.go        |  51 +++++++++
 4 files changed, 165 insertions(+), 3 deletions(-)

diff --git a/integration_tests/test_ibc_rly.py b/integration_tests/test_ibc_rly.py
index 967fbd6a74..fc72f74e94 100644
--- a/integration_tests/test_ibc_rly.py
+++ b/integration_tests/test_ibc_rly.py
@@ -44,12 +44,13 @@
 @pytest.fixture(scope="module")
 def ibc(request, tmp_path_factory):
     "prepare-network"
-    path = tmp_path_factory.mktemp("ibc_rly")
+    name = "ibc_rly"
+    path = tmp_path_factory.mktemp(name)
     procs = []
     try:
         for network in prepare_network(
             path,
-            "ibc_rly",
+            name,
             relayer=cluster.Relayer.RLY.value,
         ):
             if network.proc:
diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
index f39dbbcb1d..ca5b2841ae 100644
--- a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -30,7 +30,7 @@ var (
 
 // RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
 var RelayerFunctionsMetaData = &bind.MetaData{
-	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndAcknowledgement\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndAcknowledgement\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndTimeout\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
 }
 
 // RelayerFunctionsABI is the input ABI used to generate the binding from.
@@ -515,6 +515,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndAckno
 	return _RelayerFunctions.Contract.UpdateClientAndAcknowledgement(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndChannelOpenAck is a paid mutator transaction binding the contract method 0xc518ffc8.
+//
+// Solidity: function updateClientAndChannelOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelOpenAck(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelOpenAck", data1, data2)
+}
+
+// UpdateClientAndChannelOpenAck is a paid mutator transaction binding the contract method 0xc518ffc8.
+//
+// Solidity: function updateClientAndChannelOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelOpenAck(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenAck(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelOpenAck is a paid mutator transaction binding the contract method 0xc518ffc8.
+//
+// Solidity: function updateClientAndChannelOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelOpenAck(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenAck(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndChannelOpenConfirm is a paid mutator transaction binding the contract method 0x0982b806.
 //
 // Solidity: function updateClientAndChannelOpenConfirm(bytes data1, bytes data2) payable returns(bool)
@@ -536,6 +557,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChann
 	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndChannelOpenInit is a paid mutator transaction binding the contract method 0x66365fc4.
+//
+// Solidity: function updateClientAndChannelOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelOpenInit(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelOpenInit", data1, data2)
+}
+
+// UpdateClientAndChannelOpenInit is a paid mutator transaction binding the contract method 0x66365fc4.
+//
+// Solidity: function updateClientAndChannelOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelOpenInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelOpenInit is a paid mutator transaction binding the contract method 0x66365fc4.
+//
+// Solidity: function updateClientAndChannelOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelOpenInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndChannelOpenTry is a paid mutator transaction binding the contract method 0x33978088.
 //
 // Solidity: function updateClientAndChannelOpenTry(bytes data1, bytes data2) payable returns(bool)
@@ -557,6 +599,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChann
 	return _RelayerFunctions.Contract.UpdateClientAndChannelOpenTry(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndConnectionOpenAck is a paid mutator transaction binding the contract method 0xfedb9353.
+//
+// Solidity: function updateClientAndConnectionOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndConnectionOpenAck(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndConnectionOpenAck", data1, data2)
+}
+
+// UpdateClientAndConnectionOpenAck is a paid mutator transaction binding the contract method 0xfedb9353.
+//
+// Solidity: function updateClientAndConnectionOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndConnectionOpenAck(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenAck(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenAck is a paid mutator transaction binding the contract method 0xfedb9353.
+//
+// Solidity: function updateClientAndConnectionOpenAck(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConnectionOpenAck(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenAck(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndConnectionOpenConfirm is a paid mutator transaction binding the contract method 0x70009dfc.
 //
 // Solidity: function updateClientAndConnectionOpenConfirm(bytes data1, bytes data2) payable returns(bool)
@@ -578,6 +641,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConne
 	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndConnectionOpenInit is a paid mutator transaction binding the contract method 0x491e69c7.
+//
+// Solidity: function updateClientAndConnectionOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndConnectionOpenInit(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndConnectionOpenInit", data1, data2)
+}
+
+// UpdateClientAndConnectionOpenInit is a paid mutator transaction binding the contract method 0x491e69c7.
+//
+// Solidity: function updateClientAndConnectionOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndConnectionOpenInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndConnectionOpenInit is a paid mutator transaction binding the contract method 0x491e69c7.
+//
+// Solidity: function updateClientAndConnectionOpenInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndConnectionOpenInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndConnectionOpenInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndConnectionOpenTry is a paid mutator transaction binding the contract method 0x5f3a7169.
 //
 // Solidity: function updateClientAndConnectionOpenTry(bytes data1, bytes data2) payable returns(bool)
@@ -620,6 +704,27 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndRecvP
 	return _RelayerFunctions.Contract.UpdateClientAndRecvPacket(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndTimeout is a paid mutator transaction binding the contract method 0xca4c72a0.
+//
+// Solidity: function updateClientAndTimeout(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndTimeout(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndTimeout", data1, data2)
+}
+
+// UpdateClientAndTimeout is a paid mutator transaction binding the contract method 0xca4c72a0.
+//
+// Solidity: function updateClientAndTimeout(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndTimeout(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndTimeout(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndTimeout is a paid mutator transaction binding the contract method 0xca4c72a0.
+//
+// Solidity: function updateClientAndTimeout(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndTimeout(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndTimeout(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpgradeClient is a paid mutator transaction binding the contract method 0x8a8e4c5d.
 //
 // Solidity: function upgradeClient(bytes data) payable returns(bytes)
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
index 831a3d0a27..30d91a4835 100644
--- a/x/cronos/events/bindings/src/RelayerFunctions.sol
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -18,10 +18,15 @@ interface IRelayerFunctions {
     function acknowledgement(bytes calldata data) external payable returns (bytes calldata);
     function timeout(bytes calldata data) external payable returns (bytes calldata);
     function timeoutOnClose(bytes calldata data) external payable returns (bytes calldata);
+    function updateClientAndConnectionOpenInit(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndConnectionOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndConnectionOpenAck(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndConnectionOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelOpenInit(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndChannelOpenTry(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelOpenAck(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndChannelOpenConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndRecvPacket(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndAcknowledgement(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndTimeout(bytes calldata data1, bytes calldata data2) external payable returns (bool);
 }
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index d4629b1cb4..60159e469e 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -46,12 +46,18 @@ const (
 	Acknowledgement                      = "acknowledgement"
 	Timeout                              = "timeout"
 	TimeoutOnClose                       = "timeoutOnClose"
+	UpdateClientAndConnectionOpenInit    = "updateClientAndConnectionOpenInit"
 	UpdateClientAndConnectionOpenTry     = "updateClientAndConnectionOpenTry"
+	UpdateClientAndConnectionOpenAck     = "updateClientAndConnectionOpenAck"
 	UpdateClientAndConnectionOpenConfirm = "updateClientAndConnectionOpenConfirm"
+	UpdateClientAndChannelOpenInit       = "updateClientAndChannelOpenInit"
 	UpdateClientAndChannelOpenTry        = "updateClientAndChannelOpenTry"
+	UpdateClientAndChannelOpenAck        = "updateClientAndChannelOpenAck"
 	UpdateClientAndChannelOpenConfirm    = "updateClientAndChannelOpenConfirm"
 	UpdateClientAndRecvPacket            = "updateClientAndRecvPacket"
 	UpdateClientAndAcknowledgement       = "updateClientAndAcknowledgement"
+	UpdateClientAndTimeout               = "updateClientAndTimeout"
+	UpdateClientAndTimeoutOnClose        = "updateClientAndTimeoutOnClose"
 )
 
 func init() {
@@ -175,6 +181,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		e.input2 = args[1].([]byte)
 	}
 	memKey := bc.findMemkey()
+	fmt.Println("mm-method.Name", method.Name)
 	switch method.Name {
 	case CreateClient:
 		res, err = exec(e, bc.ibcKeeper.CreateClient)
@@ -208,10 +215,24 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		res, err = exec(e, bc.ibcKeeper.Timeout)
 	case TimeoutOnClose:
 		res, err = exec(e, bc.ibcKeeper.TimeoutOnClose)
+	case UpdateClientAndConnectionOpenInit:
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenInit)
 	case UpdateClientAndConnectionOpenTry:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenTry)
+	case UpdateClientAndConnectionOpenAck:
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenAck)
 	case UpdateClientAndConnectionOpenConfirm:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenConfirm)
+	case UpdateClientAndChannelOpenInit:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoi *types.MsgChannelOpenInit) error {
+				keyName := host.PortPath(mcoi.PortId)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(1), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.ChannelOpenInit,
+		)
 	case UpdateClientAndChannelOpenTry:
 		res, err = execMultipleWithHooks(
 			e,
@@ -222,6 +243,16 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 			bc.ibcKeeper.UpdateClient,
 			bc.ibcKeeper.ChannelOpenTry,
 		)
+	case UpdateClientAndChannelOpenAck:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoa *types.MsgChannelOpenAck) error {
+				keyName := host.ChannelCapabilityPath(mcoa.PortId, mcoa.ChannelId)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.ChannelOpenAck,
+		)
 	case UpdateClientAndChannelOpenConfirm:
 		res, err = execMultipleWithHooks(
 			e,
@@ -252,6 +283,26 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 			bc.ibcKeeper.UpdateClient,
 			bc.ibcKeeper.Acknowledgement,
 		)
+	case UpdateClientAndTimeout:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mt *types.MsgTimeout) error {
+				keyName := host.ChannelCapabilityPath(mt.Packet.SourcePort, mt.Packet.SourceChannel)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.Timeout,
+		)
+	case UpdateClientAndTimeoutOnClose:
+		res, err = execMultipleWithHooks(
+			e,
+			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mtoc *types.MsgTimeoutOnClose) error {
+				keyName := host.ChannelCapabilityPath(mtoc.Packet.SourcePort, mtoc.Packet.SourceChannel)
+				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
+			},
+			bc.ibcKeeper.UpdateClient,
+			bc.ibcKeeper.TimeoutOnClose,
+		)
 	default:
 		return nil, errors.New("unknown method")
 	}

From 04a473871a401d50fa8ffeface358bb2e20b74a7 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Fri, 20 Oct 2023 09:29:07 +0800
Subject: [PATCH 15/25] Revert "test less"

This reverts commit 4c48569266588677c198c79f68a839699c6fc12c.
---
 scripts/run-integration-tests | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/run-integration-tests b/scripts/run-integration-tests
index ef3db807d4..ffd159b251 100755
--- a/scripts/run-integration-tests
+++ b/scripts/run-integration-tests
@@ -10,4 +10,4 @@ cd ../integration_tests/contracts
 HUSKY_SKIP_INSTALL=1 npm install
 npm run typechain
 cd ..
-nix-shell --run "pytest -v -s test_ibc_rly.py::test_ibc"
\ No newline at end of file
+nix-shell --run "pytest -vv -s"
\ No newline at end of file

From 1bdb91c01fc828f17f002838c8c2eab588dfa6a5 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 30 Oct 2023 09:42:03 +0800
Subject: [PATCH 16/25] rm setMemStoreKeys

---
 app/app.go                             |   2 +-
 x/cronos/keeper/precompiles/relayer.go | 137 +++----------------------
 2 files changed, 17 insertions(+), 122 deletions(-)

diff --git a/app/app.go b/app/app.go
index 10ea03e7a3..b764b33675 100644
--- a/app/app.go
+++ b/app/app.go
@@ -553,7 +553,7 @@ func New(
 		tracer,
 		evmS,
 		[]vm.PrecompiledContract{
-			cronosprecompiles.NewRelayerContract(app.IBCKeeper, &app.ScopedIBCKeeper, memKeys, appCodec, gasConfig),
+			cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec, gasConfig),
 			cronosprecompiles.NewIcaContract(&app.ICAAuthKeeper, &app.CronosKeeper, appCodec, gasConfig),
 		},
 		allKeys,
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 60159e469e..8ce357ba31 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -2,7 +2,6 @@ package precompiles
 
 import (
 	"errors"
-	"fmt"
 
 	storetypes "github.com/cosmos/cosmos-sdk/store/types"
 
@@ -11,13 +10,6 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
 
-	sdk "github.com/cosmos/cosmos-sdk/types"
-	capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
-	capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
-	clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
-	"github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
-	host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
-	"github.com/cosmos/ibc-go/v7/modules/core/exported"
 	ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
@@ -83,21 +75,17 @@ func init() {
 type RelayerContract struct {
 	BaseContract
 
-	cdc             codec.Codec
-	ibcKeeper       *ibckeeper.Keeper
-	scopedIBCKeeper *capabilitykeeper.ScopedKeeper
-	memKeys         map[string]*storetypes.MemoryStoreKey
-	kvGasConfig     storetypes.GasConfig
+	cdc         codec.Codec
+	ibcKeeper   *ibckeeper.Keeper
+	kvGasConfig storetypes.GasConfig
 }
 
-func NewRelayerContract(ibcKeeper *ibckeeper.Keeper, scopedIBCKeeper *capabilitykeeper.ScopedKeeper, memKeys map[string]*storetypes.MemoryStoreKey, cdc codec.Codec, kvGasConfig storetypes.GasConfig) vm.PrecompiledContract {
+func NewRelayerContract(ibcKeeper *ibckeeper.Keeper, cdc codec.Codec, kvGasConfig storetypes.GasConfig) vm.PrecompiledContract {
 	return &RelayerContract{
-		BaseContract:    NewBaseContract(relayerContractAddress),
-		ibcKeeper:       ibcKeeper,
-		scopedIBCKeeper: scopedIBCKeeper,
-		memKeys:         memKeys,
-		cdc:             cdc,
-		kvGasConfig:     kvGasConfig,
+		BaseContract: NewBaseContract(relayerContractAddress),
+		ibcKeeper:    ibcKeeper,
+		cdc:          cdc,
+		kvGasConfig:  kvGasConfig,
 	}
 }
 
@@ -122,33 +110,6 @@ func (bc *RelayerContract) IsStateful() bool {
 	return true
 }
 
-func (bc *RelayerContract) findMemkey() *storetypes.MemoryStoreKey {
-	for _, m := range bc.memKeys {
-		if m.Name() == capabilitytypes.MemStoreKey {
-			return m
-		}
-	}
-	return nil
-}
-
-func (bc *RelayerContract) setMemStoreKeys(
-	ctx sdk.Context,
-	memKey storetypes.StoreKey,
-	index uint64,
-	keyName string,
-) error {
-	memStore := ctx.KVStore(memKey)
-	key := []byte(fmt.Sprintf("ibc/rev/%s", keyName))
-	memStore.Set(key, sdk.Uint64ToBigEndian(index))
-	cap, ok := bc.scopedIBCKeeper.GetCapability(ctx, keyName)
-	if !ok {
-		return fmt.Errorf("fail to find cap for %s", keyName)
-	}
-	key = capabilitytypes.FwdCapabilityKey(exported.ModuleName, cap)
-	memStore.Set(key, []byte(keyName))
-	return nil
-}
-
 func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
 	if readonly {
 		return nil, errors.New("the method is not readonly")
@@ -180,8 +141,6 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	if len(args) > 1 {
 		e.input2 = args[1].([]byte)
 	}
-	memKey := bc.findMemkey()
-	fmt.Println("mm-method.Name", method.Name)
 	switch method.Name {
 	case CreateClient:
 		res, err = exec(e, bc.ibcKeeper.CreateClient)
@@ -224,85 +183,21 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	case UpdateClientAndConnectionOpenConfirm:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ConnectionOpenConfirm)
 	case UpdateClientAndChannelOpenInit:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoi *types.MsgChannelOpenInit) error {
-				keyName := host.PortPath(mcoi.PortId)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(1), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.ChannelOpenInit,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenInit)
 	case UpdateClientAndChannelOpenTry:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcot *types.MsgChannelOpenTry) error {
-				keyName := host.PortPath(mcot.PortId)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(1), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.ChannelOpenTry,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenTry)
 	case UpdateClientAndChannelOpenAck:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoa *types.MsgChannelOpenAck) error {
-				keyName := host.ChannelCapabilityPath(mcoa.PortId, mcoa.ChannelId)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.ChannelOpenAck,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenAck)
 	case UpdateClientAndChannelOpenConfirm:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mcoc *types.MsgChannelOpenConfirm) error {
-				keyName := host.ChannelCapabilityPath(mcoc.PortId, mcoc.ChannelId)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.ChannelOpenConfirm,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenConfirm)
 	case UpdateClientAndRecvPacket:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mrp *types.MsgRecvPacket) error {
-				keyName := host.ChannelCapabilityPath(mrp.Packet.DestinationPort, mrp.Packet.DestinationChannel)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.RecvPacket,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.RecvPacket)
 	case UpdateClientAndAcknowledgement:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mack *types.MsgAcknowledgement) error {
-				keyName := host.ChannelCapabilityPath(mack.Packet.SourcePort, mack.Packet.SourceChannel)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.Acknowledgement,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.Acknowledgement)
 	case UpdateClientAndTimeout:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mt *types.MsgTimeout) error {
-				keyName := host.ChannelCapabilityPath(mt.Packet.SourcePort, mt.Packet.SourceChannel)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.Timeout,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.Timeout)
 	case UpdateClientAndTimeoutOnClose:
-		res, err = execMultipleWithHooks(
-			e,
-			func(ctx sdk.Context, _ *clienttypes.MsgUpdateClient, mtoc *types.MsgTimeoutOnClose) error {
-				keyName := host.ChannelCapabilityPath(mtoc.Packet.SourcePort, mtoc.Packet.SourceChannel)
-				return bc.setMemStoreKeys(ctx, memKey, uint64(2), keyName)
-			},
-			bc.ibcKeeper.UpdateClient,
-			bc.ibcKeeper.TimeoutOnClose,
-		)
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.TimeoutOnClose)
 	default:
 		return nil, errors.New("unknown method")
 	}

From b804a2b454e76dd5e5f79c55d59f4092e03ffa1c Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 30 Oct 2023 09:50:39 +0800
Subject: [PATCH 17/25] fix gas formula

---
 app/app.go                                    |  2 +-
 integration_tests/configs/ibc_rly.jsonnet     | 17 +++++-
 integration_tests/configs/ibc_rly_evm.jsonnet |  9 +++
 integration_tests/cosmoscli.py                | 12 ++++
 integration_tests/ibc_utils.py                | 34 +++++++++++
 integration_tests/test_ibc_rly.py             | 17 +-----
 integration_tests/test_ibc_rly_gas.py         | 31 ++++++++++
 scripts/.env                                  | 18 ++++++
 x/cronos/keeper/precompiles/relayer.go        | 60 +++++++++++++------
 9 files changed, 165 insertions(+), 35 deletions(-)
 create mode 100644 integration_tests/configs/ibc_rly_evm.jsonnet
 create mode 100644 integration_tests/test_ibc_rly_gas.py

diff --git a/app/app.go b/app/app.go
index e589267c39..846a19f5aa 100644
--- a/app/app.go
+++ b/app/app.go
@@ -536,7 +536,7 @@ func New(
 		tracer,
 		evmS,
 		[]vm.PrecompiledContract{
-			cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec, gasConfig),
+			cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec, app.Logger()),
 			cronosprecompiles.NewIcaContract(&app.ICAAuthKeeper, &app.CronosKeeper, appCodec, gasConfig),
 		},
 		allKeys,
diff --git a/integration_tests/configs/ibc_rly.jsonnet b/integration_tests/configs/ibc_rly.jsonnet
index 50dfd73524..db80c79b02 100644
--- a/integration_tests/configs/ibc_rly.jsonnet
+++ b/integration_tests/configs/ibc_rly.jsonnet
@@ -1,9 +1,24 @@
 local ibc = import 'ibc.jsonnet';
 
 ibc {
+  'chainmain-1'+: {
+    validators: [
+      {
+        coins: '987870000000000000cro',
+        staked: '20000000000000cro',
+        mnemonic: '${VALIDATOR' + i + '_MNEMONIC}',
+        client_config: {
+          'broadcast-mode': 'block',
+        },
+        base_port: 26800 + i * 10,
+      }
+      for i in std.range(1, 2)
+    ],
+  },
   relayer+: {
     chains: [super.chains[0] {
-      precompiled_contract_address: '0x0000000000000000000000000000000000000065',
+      max_gas: 1000000,
+      gas_multiplier: 1.2,
     }] + super.chains[1:],
   },
 }
diff --git a/integration_tests/configs/ibc_rly_evm.jsonnet b/integration_tests/configs/ibc_rly_evm.jsonnet
new file mode 100644
index 0000000000..b7b673d082
--- /dev/null
+++ b/integration_tests/configs/ibc_rly_evm.jsonnet
@@ -0,0 +1,9 @@
+local ibc = import 'ibc_rly.jsonnet';
+
+ibc {
+  relayer+: {
+    chains: [super.chains[0] {
+      precompiled_contract_address: '0x0000000000000000000000000000000000000065',
+    }] + super.chains[1:],
+  },
+}
diff --git a/integration_tests/cosmoscli.py b/integration_tests/cosmoscli.py
index 6019d2ea92..0b95a59eb8 100644
--- a/integration_tests/cosmoscli.py
+++ b/integration_tests/cosmoscli.py
@@ -9,6 +9,7 @@
 from collections import namedtuple
 
 import bech32
+import requests
 from dateutil.parser import isoparse
 from pystarport.utils import build_cli_args_safe, format_doc_string, interact
 
@@ -221,6 +222,17 @@ def tx_search(self, events: str):
             self.raw("query", "txs", events=events, output="json", node=self.node_rpc)
         )
 
+    def tx_search_rpc(self, criteria: str):
+        node_rpc_http = "http" + self.node_rpc.removeprefix("tcp")
+        rsp = requests.get(
+            f"{node_rpc_http}/tx_search",
+            params={
+                "query": f'"{criteria}"',
+            },
+        ).json()
+        assert "error" not in rsp, rsp["error"]
+        return rsp["result"]["txs"]
+
     def distribution_commission(self, addr):
         coin = json.loads(
             self.raw(
diff --git a/integration_tests/ibc_utils.py b/integration_tests/ibc_utils.py
index 2dcf6cb5cf..82d8ce018f 100644
--- a/integration_tests/ibc_utils.py
+++ b/integration_tests/ibc_utils.py
@@ -217,6 +217,25 @@ def hermes_transfer(ibc):
     return src_amount
 
 
+def rly_transfer(ibc):
+    # chainmain-1 -> cronos_777-1
+    my_ibc0 = "chainmain-1"
+    my_ibc1 = "cronos_777-1"
+    channel = "channel-0"
+    dst_addr = eth_to_bech32(ADDRS["signer2"])
+    src_amount = 10
+    src_denom = "basecro"
+    path = ibc.cronos.base_dir.parent / "relayer"
+    # srcchainid dstchainid amount dst_addr srchannelid
+    cmd = (
+        f"rly tx transfer {my_ibc0} {my_ibc1} {src_amount}{src_denom} "
+        f"{dst_addr} {channel} "
+        f"--path chainmain-cronos "
+        f"--home {str(path)}"
+    )
+    subprocess.run(cmd, check=True, shell=True)
+
+
 def find_duplicate(attributes):
     res = set()
     key = attributes[0]["key"]
@@ -638,3 +657,18 @@ def gen_send_msg(sender, receiver, denom, amount):
         "to_address": receiver,
         "amount": [{"denom": denom, "amount": f"{amount}"}],
     }
+
+
+def log_gas_records(cli):
+    criteria = "tx.height >= 0"
+    txs = cli.tx_search_rpc(criteria)
+    records = []
+    for tx in txs:
+        res = tx["tx_result"]
+        actions = []
+        for event in res["events"]:
+            for attribute in event["attributes"]:
+                if attribute["key"] == "action":
+                    actions.append(attribute["value"])
+        records.append(res["gas_used"])
+    print("records", records)
diff --git a/integration_tests/test_ibc_rly.py b/integration_tests/test_ibc_rly.py
index 7e32f0c2f1..dd48f42b5c 100644
--- a/integration_tests/test_ibc_rly.py
+++ b/integration_tests/test_ibc_rly.py
@@ -1,5 +1,4 @@
 import json
-import subprocess
 
 import pytest
 from eth_utils import keccak, to_checksum_address
@@ -14,6 +13,7 @@
     ibc_denom,
     ibc_incentivized_transfer,
     prepare_network,
+    rly_transfer,
 )
 from .utils import (
     ADDRS,
@@ -51,21 +51,6 @@ def ibc(request, tmp_path_factory):
     )
 
 
-def rly_transfer(ibc):
-    # chainmain-1 -> cronos_777-1
-    my_ibc0 = "chainmain-1"
-    my_ibc1 = "cronos_777-1"
-    path = ibc.cronos.base_dir.parent / "relayer"
-    # srcchainid dstchainid amount dst_addr srchannelid
-    cmd = (
-        f"rly tx transfer {my_ibc0} {my_ibc1} {src_amount}{src_denom} "
-        f"{eth_to_bech32(cronos_signer2)} {channel} "
-        f"--path chainmain-cronos "
-        f"--home {str(path)}"
-    )
-    subprocess.run(cmd, check=True, shell=True)
-
-
 def coin_received(receiver, amt, denom):
     return {
         "receiver": receiver,
diff --git a/integration_tests/test_ibc_rly_gas.py b/integration_tests/test_ibc_rly_gas.py
new file mode 100644
index 0000000000..aae57db849
--- /dev/null
+++ b/integration_tests/test_ibc_rly_gas.py
@@ -0,0 +1,31 @@
+import pytest
+from pystarport import cluster
+
+from .ibc_utils import log_gas_records, prepare_network, rly_transfer
+from .utils import wait_for_new_blocks
+
+
+@pytest.fixture(scope="module", params=["ibc_rly", "ibc_rly_evm"])
+def ibc(request, tmp_path_factory):
+    "prepare-network"
+    name = request.param
+    path = tmp_path_factory.mktemp(name)
+    yield from prepare_network(path, name, relayer=cluster.Relayer.RLY.value)
+
+
+records = []
+
+
+def test_ibc(ibc):
+    # chainmain-1 relayer -> cronos_777-1 signer2
+    cli = ibc.cronos.cosmos_cli()
+    wait_for_new_blocks(cli, 1)
+    rly_transfer(ibc)
+    diff = 0.001
+    record = log_gas_records(cli)
+    if record:
+        records.append(record)
+    if len(records) == 2:
+        for e1, e2 in zip(*records):
+            res = e2 / e1
+            assert 1 - diff <= res <= 1 + diff, res
diff --git a/scripts/.env b/scripts/.env
index aa4225be27..8b76c2a2fd 100644
--- a/scripts/.env
+++ b/scripts/.env
@@ -1,6 +1,24 @@
 export PASSWORD='123456'
 export VALIDATOR1_MNEMONIC="visit craft resemble online window solution west chuckle music diesel vital settle comic tribe project blame bulb armed flower region sausage mercy arrive release"
 export VALIDATOR2_MNEMONIC="direct travel shrug hand twice agent sail sell jump phone velvet pilot mango charge usual multiply orient garment bleak virtual action mention panda vast"
+export VALIDATOR3_MNEMONIC="quit crush inherit magic tree rookie steel lemon junior need another immune brief genius series raccoon fringe immense view open bomb fancy hammer effort"
+export VALIDATOR4_MNEMONIC="topic elegant hero arena farm find step before clarify accident manage poem suffer actual winner legend gauge trap express problem obscure crucial crop knock"
+export VALIDATOR5_MNEMONIC="trip glory pet mention level mistake obey engage baby mountain culture lizard arrest rely bind liar honey host wink snow run artefact foot edit"
+export VALIDATOR6_MNEMONIC="mask ball border unaware much sketch feel cement neck impulse sun tower miss fetch shield horror shed blame bargain ride unlock weapon fold favorite"
+export VALIDATOR7_MNEMONIC="execute skull truth tattoo whale avoid proud print horse coin upgrade pig scatter federal token hour define verb inherit flee grit thunder town victory"
+export VALIDATOR8_MNEMONIC="fee endless venture glimpse fresh salad hard scrap magic state arrow color praise city noodle auto kind art promote rebel flat glove hard muffin"
+export VALIDATOR9_MNEMONIC="sign night wish check satoshi together husband boy gospel discover inch wealth magnet increase chalk mom begin deny found casino busy shiver letter either"
+export VALIDATOR10_MNEMONIC="this satoshi juice squirrel chair must shed useless pistol duty tray use annual frame game hour old sing anger discover arch mixed abuse few"
+export VALIDATOR11_MNEMONIC="portion found fancy solve team ill hidden scheme unaware next toward icon piano dinner hen access alter verb twin medal team dumb ball lamp"
+export VALIDATOR12_MNEMONIC="appear ship nation try twice smoke expose sand spirit burden bubble betray pulp coral receive civil case subway smoke foil rival horn dove myth"
+export VALIDATOR13_MNEMONIC="rebel fabric infant purpose toss boring crucial bone decorate input travel orphan whale rely holiday cloth split heavy soft flight unusual paddle play okay"
+export VALIDATOR14_MNEMONIC="keen solve version impulse wash coil mandate enrich devote one gaze cruise observe pass hospital empty stumble clip bench sock solid boost drama pluck"
+export VALIDATOR15_MNEMONIC="rather moon angry badge blast panic various couch roof loan infant bunker coin ahead junior hint rubber clever obvious tornado insect student trap case"
+export VALIDATOR16_MNEMONIC="meat crucial beauty build major shrimp tired example helmet heart account veteran innocent early gather audit wire dutch wisdom reward cube solar media canal"
+export VALIDATOR17_MNEMONIC="twenty author boil minor swap super once run push vibrant tower retire rain trigger indicate source armor trumpet long profit monkey bounce spell trend"
+export VALIDATOR18_MNEMONIC="sausage draw subway spike mix thumb begin pair inspire great squirrel tragic lazy slender bachelor pause oak celery glory feature shallow slide vendor lyrics"
+export VALIDATOR19_MNEMONIC="detect surprise oval quote unaware buyer ivory right maple cricket picnic unfair grab sting weather hair erosion course kiss wing ladder sure media season"
+export VALIDATOR20_MNEMONIC="dizzy patrol weird scatter rally furnace scatter pear smart clutch domain can tuition faculty clock friend build doctor emotion milk urge can message mix"
 export COMMUNITY_MNEMONIC="notable error gospel wave pair ugly measure elite toddler cost various fly make eye ketchup despair slab throw tribe swarm word fruit into inmate"
 export SIGNER1_MNEMONIC="shed crumble dismiss loyal latin million oblige gesture shrug still oxygen custom remove ribbon disorder palace addict again blanket sad flock consider obey popular"
 export SIGNER2_MNEMONIC="night renew tonight dinner shaft scheme domain oppose echo summer broccoli agent face guitar surface belt veteran siren poem alcohol menu custom crunch index"
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index e0d363d539..72d62d59f7 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -3,13 +3,14 @@ package precompiles
 import (
 	"errors"
 
-	storetypes "github.com/cosmos/cosmos-sdk/store/types"
-
+	"github.com/cometbft/cometbft/libs/log"
 	"github.com/cosmos/cosmos-sdk/codec"
 	"github.com/ethereum/go-ethereum/accounts/abi"
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/vm"
 
+	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 	cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer"
 	"github.com/crypto-org-chain/cronos/v2/x/cronos/types"
@@ -18,6 +19,7 @@ import (
 var (
 	irelayerABI                abi.ABI
 	relayerContractAddress     = common.BytesToAddress([]byte{101})
+	relayerMethodNamedByMethod = map[[4]byte]string{}
 	relayerGasRequiredByMethod = map[[4]byte]uint64{}
 )
 
@@ -61,31 +63,39 @@ func init() {
 		copy(methodID[:], irelayerABI.Methods[methodName].ID[:4])
 		switch methodName {
 		case CreateClient:
-			relayerGasRequiredByMethod[methodID] = 200000
-		case RecvPacket, Acknowledgement:
-			relayerGasRequiredByMethod[methodID] = 250000
-		case UpdateClient, UpgradeClient:
-			relayerGasRequiredByMethod[methodID] = 400000
+			relayerGasRequiredByMethod[methodID] = 117462
+		case UpdateClientAndConnectionOpenTry:
+			relayerGasRequiredByMethod[methodID] = 150362
+		case UpdateClientAndConnectionOpenConfirm:
+			relayerGasRequiredByMethod[methodID] = 124820
+		case UpdateClientAndChannelOpenTry:
+			relayerGasRequiredByMethod[methodID] = 182676
+		case UpdateClientAndChannelOpenConfirm:
+			relayerGasRequiredByMethod[methodID] = 132734
+		case UpdateClientAndRecvPacket:
+			relayerGasRequiredByMethod[methodID] = 257120
 		default:
 			relayerGasRequiredByMethod[methodID] = 100000
 		}
+
+		relayerMethodNamedByMethod[methodID] = methodName
 	}
 }
 
 type RelayerContract struct {
 	BaseContract
 
-	cdc         codec.Codec
-	ibcKeeper   types.IbcKeeper
-	kvGasConfig storetypes.GasConfig
+	cdc       codec.Codec
+	ibcKeeper types.IbcKeeper
+	logger    log.Logger
 }
 
-func NewRelayerContract(ibcKeeper types.IbcKeeper, cdc codec.Codec, kvGasConfig storetypes.GasConfig) vm.PrecompiledContract {
+func NewRelayerContract(ibcKeeper types.IbcKeeper, cdc codec.Codec, logger log.Logger) vm.PrecompiledContract {
 	return &RelayerContract{
 		BaseContract: NewBaseContract(relayerContractAddress),
 		ibcKeeper:    ibcKeeper,
 		cdc:          cdc,
-		kvGasConfig:  kvGasConfig,
+		logger:       logger.With("precompiles", "relayer"),
 	}
 }
 
@@ -94,16 +104,32 @@ func (bc *RelayerContract) Address() common.Address {
 }
 
 // RequiredGas calculates the contract gas use
-func (bc *RelayerContract) RequiredGas(input []byte) uint64 {
+func (bc *RelayerContract) RequiredGas(input []byte) (gas uint64) {
+	inputLen := len(input)
+	if inputLen < 4 {
+		return 0
+	}
+	intrinsicGas, err := core.IntrinsicGas(input, nil, false, true, true)
+	if err != nil {
+		return 0
+	}
 	// base cost to prevent large input size
-	baseCost := uint64(len(input)) * bc.kvGasConfig.WriteCostPerByte
+	baseCost := uint64(inputLen) * authtypes.DefaultTxSizeCostPerByte
 	var methodID [4]byte
 	copy(methodID[:], input[:4])
 	requiredGas, ok := relayerGasRequiredByMethod[methodID]
-	if ok {
-		return requiredGas + baseCost
+	if !ok {
+		requiredGas = 0
+	}
+	defer func() {
+		method := relayerMethodNamedByMethod[methodID]
+		bc.logger.Debug("required", "gas", gas, "method", method, "len", inputLen, "intrinsic", intrinsicGas)
+	}()
+	total := requiredGas + baseCost
+	if total < intrinsicGas {
+		return 0
 	}
-	return baseCost
+	return total - intrinsicGas
 }
 
 func (bc *RelayerContract) IsStateful() bool {

From 36fdb8a714c15e2fca39aa31d658d35ec8ea20b6 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 30 Oct 2023 10:59:33 +0800
Subject: [PATCH 18/25] fix test

---
 integration_tests/ibc_utils.py    | 9 ++-------
 integration_tests/test_ibc_rly.py | 2 +-
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/integration_tests/ibc_utils.py b/integration_tests/ibc_utils.py
index 82d8ce018f..89bf1d56e2 100644
--- a/integration_tests/ibc_utils.py
+++ b/integration_tests/ibc_utils.py
@@ -665,10 +665,5 @@ def log_gas_records(cli):
     records = []
     for tx in txs:
         res = tx["tx_result"]
-        actions = []
-        for event in res["events"]:
-            for attribute in event["attributes"]:
-                if attribute["key"] == "action":
-                    actions.append(attribute["value"])
-        records.append(res["gas_used"])
-    print("records", records)
+        if res["gas_used"]:
+            records.append(res["gas_used"])
diff --git a/integration_tests/test_ibc_rly.py b/integration_tests/test_ibc_rly.py
index dd48f42b5c..3aa8e54b62 100644
--- a/integration_tests/test_ibc_rly.py
+++ b/integration_tests/test_ibc_rly.py
@@ -42,7 +42,7 @@
 @pytest.fixture(scope="module")
 def ibc(request, tmp_path_factory):
     "prepare-network"
-    name = "ibc_rly"
+    name = "ibc_rly_evm"
     path = tmp_path_factory.mktemp(name)
     yield from prepare_network(
         path,

From e2c560f9b8e900880644ed5d01e222739c8bf335 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 6 Nov 2023 14:30:45 +0800
Subject: [PATCH 19/25] add missing method

---
 x/cronos/keeper/precompiles/relayer.go | 31 ++++++++++++++++----------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index 7480a8cbac..acbaebe6e6 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -74,6 +74,18 @@ func init() {
 			relayerGasRequiredByMethod[methodID] = 132734
 		case UpdateClientAndRecvPacket:
 			relayerGasRequiredByMethod[methodID] = 257120
+		case UpdateClientAndConnectionOpenInit:
+			relayerGasRequiredByMethod[methodID] = 131649
+		case UpdateClientAndConnectionOpenAck:
+			relayerGasRequiredByMethod[methodID] = 141558
+		case UpdateClientAndChannelOpenInit:
+			relayerGasRequiredByMethod[methodID] = 180815
+		case UpdateClientAndChannelOpenAck:
+			relayerGasRequiredByMethod[methodID] = 133834
+		case UpdateClientAndTimeout:
+			relayerGasRequiredByMethod[methodID] = 230638
+		case UpdateClientAndAcknowledgement:
+			relayerGasRequiredByMethod[methodID] = 174785
 		default:
 			relayerGasRequiredByMethod[methodID] = 100000
 		}
@@ -103,27 +115,22 @@ func (bc *RelayerContract) Address() common.Address {
 }
 
 // RequiredGas calculates the contract gas use
+// `max(0, len(input) * DefaultTxSizeCostPerByte + requiredGasTable[methodPrefix] - intrinsicGas)`
 func (bc *RelayerContract) RequiredGas(input []byte) (gas uint64) {
-	inputLen := len(input)
-	if inputLen < 4 {
-		return 0
-	}
-	intrinsicGas, err := core.IntrinsicGas(input, nil, false, true, true)
-	if err != nil {
-		return 0
-	}
 	// base cost to prevent large input size
+	inputLen := len(input)
 	baseCost := uint64(inputLen) * authtypes.DefaultTxSizeCostPerByte
 	var methodID [4]byte
 	copy(methodID[:], input[:4])
 	requiredGas, ok := relayerGasRequiredByMethod[methodID]
+	intrinsicGas, _ := core.IntrinsicGas(input, nil, false, true, true)
+	defer func() {
+		methodName := relayerMethodNamedByMethod[methodID]
+		bc.logger.Debug("required", "gas", gas, "method", methodName, "len", inputLen, "intrinsic", intrinsicGas)
+	}()
 	if !ok {
 		requiredGas = 0
 	}
-	defer func() {
-		method := relayerMethodNamedByMethod[methodID]
-		bc.logger.Debug("required", "gas", gas, "method", method, "len", inputLen, "intrinsic", intrinsicGas)
-	}()
 	total := requiredGas + baseCost
 	if total < intrinsicGas {
 		return 0

From 136ced6078227e2230b5eb6b9c09dfad2d08cda9 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 6 Nov 2023 14:30:53 +0800
Subject: [PATCH 20/25] add missing channel close

---
 nix/sources.json                              |  6 +-
 .../relayer/i_relayer_functions.abigen.go     | 86 ++++++++++++++++++-
 .../events/bindings/src/RelayerFunctions.sol  |  4 +
 x/cronos/keeper/precompiles/relayer.go        | 14 +++
 4 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/nix/sources.json b/nix/sources.json
index d2a895f0e7..db43553c70 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -126,10 +126,10 @@
         "homepage": "https://github.com/mmsqe/relayer",
         "owner": "mmsqe",
         "repo": "relayer",
-        "rev": "54126405d4d9182ced43c1437dfd11887c955aa5",
-        "sha256": "1grhrzg6gphqayqhxapdp7y278xiw5iz8c2r40gjaqcwiqjnpkgp",
+        "rev": "bed7b1df8f215b07c52220b952d9e32ec45d7408",
+        "sha256": "0s0flgfagx561r0wfld7br24a5nfkbgwc8y9m3c63v3a75w6cll6",
         "type": "tarball",
-        "url": "https://github.com/mmsqe/relayer/archive/54126405d4d9182ced43c1437dfd11887c955aa5.tar.gz",
+        "url": "https://github.com/mmsqe/relayer/archive/bed7b1df8f215b07c52220b952d9e32ec45d7408.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     }
 }
diff --git a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
index ca5b2841ae..cb2702d0b8 100644
--- a/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
+++ b/x/cronos/events/bindings/cosmos/precompile/relayer/i_relayer_functions.abigen.go
@@ -30,7 +30,7 @@ var (
 
 // RelayerFunctionsMetaData contains all meta data concerning the RelayerFunctions contract.
 var RelayerFunctionsMetaData = &bind.MetaData{
-	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndAcknowledgement\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndTimeout\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
+	ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"acknowledgement\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelCloseConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelCloseInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"channelOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenAck\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenInit\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"connectionOpenTry\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"createClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"recvPacket\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"submitMisbehaviour\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeout\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"timeoutOnClose\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"updateClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndAcknowledgement\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelCloseConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelCloseInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndChannelOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenAck\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenConfirm\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndConnectionOpenTry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndRecvPacket\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data1\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data2\",\"type\":\"bytes\"}],\"name\":\"updateClientAndTimeout\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeClient\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]",
 }
 
 // RelayerFunctionsABI is the input ABI used to generate the binding from.
@@ -200,6 +200,48 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) Acknowledgement(data
 	return _RelayerFunctions.Contract.Acknowledgement(&_RelayerFunctions.TransactOpts, data)
 }
 
+// ChannelCloseConfirm is a paid mutator transaction binding the contract method 0xc9741674.
+//
+// Solidity: function channelCloseConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelCloseConfirm(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelCloseConfirm", data)
+}
+
+// ChannelCloseConfirm is a paid mutator transaction binding the contract method 0xc9741674.
+//
+// Solidity: function channelCloseConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelCloseConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelCloseConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelCloseConfirm is a paid mutator transaction binding the contract method 0xc9741674.
+//
+// Solidity: function channelCloseConfirm(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelCloseConfirm(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelCloseConfirm(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelCloseInit is a paid mutator transaction binding the contract method 0x44ba8a17.
+//
+// Solidity: function channelCloseInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactor) ChannelCloseInit(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "channelCloseInit", data)
+}
+
+// ChannelCloseInit is a paid mutator transaction binding the contract method 0x44ba8a17.
+//
+// Solidity: function channelCloseInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsSession) ChannelCloseInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelCloseInit(&_RelayerFunctions.TransactOpts, data)
+}
+
+// ChannelCloseInit is a paid mutator transaction binding the contract method 0x44ba8a17.
+//
+// Solidity: function channelCloseInit(bytes data) payable returns(bytes)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) ChannelCloseInit(data []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.ChannelCloseInit(&_RelayerFunctions.TransactOpts, data)
+}
+
 // ChannelOpenAck is a paid mutator transaction binding the contract method 0xd859b9f4.
 //
 // Solidity: function channelOpenAck(bytes data) payable returns(bytes)
@@ -515,6 +557,48 @@ func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndAckno
 	return _RelayerFunctions.Contract.UpdateClientAndAcknowledgement(&_RelayerFunctions.TransactOpts, data1, data2)
 }
 
+// UpdateClientAndChannelCloseConfirm is a paid mutator transaction binding the contract method 0x9bbcbfd2.
+//
+// Solidity: function updateClientAndChannelCloseConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelCloseConfirm(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelCloseConfirm", data1, data2)
+}
+
+// UpdateClientAndChannelCloseConfirm is a paid mutator transaction binding the contract method 0x9bbcbfd2.
+//
+// Solidity: function updateClientAndChannelCloseConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelCloseConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelCloseConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelCloseConfirm is a paid mutator transaction binding the contract method 0x9bbcbfd2.
+//
+// Solidity: function updateClientAndChannelCloseConfirm(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelCloseConfirm(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelCloseConfirm(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelCloseInit is a paid mutator transaction binding the contract method 0x5447448d.
+//
+// Solidity: function updateClientAndChannelCloseInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactor) UpdateClientAndChannelCloseInit(opts *bind.TransactOpts, data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.contract.Transact(opts, "updateClientAndChannelCloseInit", data1, data2)
+}
+
+// UpdateClientAndChannelCloseInit is a paid mutator transaction binding the contract method 0x5447448d.
+//
+// Solidity: function updateClientAndChannelCloseInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsSession) UpdateClientAndChannelCloseInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelCloseInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
+// UpdateClientAndChannelCloseInit is a paid mutator transaction binding the contract method 0x5447448d.
+//
+// Solidity: function updateClientAndChannelCloseInit(bytes data1, bytes data2) payable returns(bool)
+func (_RelayerFunctions *RelayerFunctionsTransactorSession) UpdateClientAndChannelCloseInit(data1 []byte, data2 []byte) (*types.Transaction, error) {
+	return _RelayerFunctions.Contract.UpdateClientAndChannelCloseInit(&_RelayerFunctions.TransactOpts, data1, data2)
+}
+
 // UpdateClientAndChannelOpenAck is a paid mutator transaction binding the contract method 0xc518ffc8.
 //
 // Solidity: function updateClientAndChannelOpenAck(bytes data1, bytes data2) payable returns(bool)
diff --git a/x/cronos/events/bindings/src/RelayerFunctions.sol b/x/cronos/events/bindings/src/RelayerFunctions.sol
index 30d91a4835..f580fe5ccb 100644
--- a/x/cronos/events/bindings/src/RelayerFunctions.sol
+++ b/x/cronos/events/bindings/src/RelayerFunctions.sol
@@ -14,6 +14,8 @@ interface IRelayerFunctions {
     function channelOpenTry(bytes calldata data) external payable returns (bytes calldata);
     function channelOpenAck(bytes calldata data) external payable returns (bytes calldata);
     function channelOpenConfirm(bytes calldata data) external payable returns (bytes calldata);
+    function channelCloseInit(bytes calldata data) external payable returns (bytes calldata);
+    function channelCloseConfirm(bytes calldata data) external payable returns (bytes calldata);
     function recvPacket(bytes calldata data) external payable returns (bytes calldata);
     function acknowledgement(bytes calldata data) external payable returns (bytes calldata);
     function timeout(bytes calldata data) external payable returns (bytes calldata);
@@ -29,4 +31,6 @@ interface IRelayerFunctions {
     function updateClientAndRecvPacket(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndAcknowledgement(bytes calldata data1, bytes calldata data2) external payable returns (bool);
     function updateClientAndTimeout(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelCloseInit(bytes calldata data1, bytes calldata data2) external payable returns (bool);
+    function updateClientAndChannelCloseConfirm(bytes calldata data1, bytes calldata data2) external payable returns (bool);
 }
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index acbaebe6e6..c0389a05ee 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -36,6 +36,8 @@ const (
 	ChannelOpenTry                       = "channelOpenTry"
 	ChannelOpenAck                       = "channelOpenAck"
 	ChannelOpenConfirm                   = "channelOpenConfirm"
+	ChannelCloseInit                     = "channelCloseInit"
+	ChannelCloseConfirm                  = "channelCloseConfirm"
 	RecvPacket                           = "recvPacket"
 	Acknowledgement                      = "acknowledgement"
 	Timeout                              = "timeout"
@@ -47,6 +49,8 @@ const (
 	UpdateClientAndChannelOpenInit       = "updateClientAndChannelOpenInit"
 	UpdateClientAndChannelOpenTry        = "updateClientAndChannelOpenTry"
 	UpdateClientAndChannelOpenAck        = "updateClientAndChannelOpenAck"
+	UpdateClientAndChannelCloseInit      = "updateClientAndChannelCloseInit"
+	UpdateClientAndChannelCloseConfirm   = "updateClientAndChannelCloseConfirm"
 	UpdateClientAndChannelOpenConfirm    = "updateClientAndChannelOpenConfirm"
 	UpdateClientAndRecvPacket            = "updateClientAndRecvPacket"
 	UpdateClientAndAcknowledgement       = "updateClientAndAcknowledgement"
@@ -82,6 +86,8 @@ func init() {
 			relayerGasRequiredByMethod[methodID] = 180815
 		case UpdateClientAndChannelOpenAck:
 			relayerGasRequiredByMethod[methodID] = 133834
+		case UpdateClientAndChannelCloseConfirm:
+			relayerGasRequiredByMethod[methodID] = 143366
 		case UpdateClientAndTimeout:
 			relayerGasRequiredByMethod[methodID] = 230638
 		case UpdateClientAndAcknowledgement:
@@ -198,6 +204,10 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		res, err = exec(e, bc.ibcKeeper.ChannelOpenAck)
 	case ChannelOpenConfirm:
 		res, err = exec(e, bc.ibcKeeper.ChannelOpenConfirm)
+	case ChannelCloseInit:
+		res, err = exec(e, bc.ibcKeeper.ChannelCloseInit)
+	case ChannelCloseConfirm:
+		res, err = exec(e, bc.ibcKeeper.ChannelCloseConfirm)
 	case RecvPacket:
 		res, err = exec(e, bc.ibcKeeper.RecvPacket)
 	case Acknowledgement:
@@ -218,6 +228,10 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenInit)
 	case UpdateClientAndChannelOpenTry:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenTry)
+	case UpdateClientAndChannelCloseInit:
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelCloseInit)
+	case UpdateClientAndChannelCloseConfirm:
+		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelCloseConfirm)
 	case UpdateClientAndChannelOpenAck:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.ChannelOpenAck)
 	case UpdateClientAndChannelOpenConfirm:

From 376d0ed5d74ce08e65250bf1c80eaae2e3356e23 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 6 Nov 2023 14:34:53 +0800
Subject: [PATCH 21/25] fix resolve

---
 x/cronos/keeper/precompiles/relayer.go | 28 ++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index c0389a05ee..d077f1d2fe 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -68,6 +68,34 @@ func init() {
 		switch methodName {
 		case CreateClient:
 			relayerGasRequiredByMethod[methodID] = 117462
+		case UpdateClient:
+			relayerGasRequiredByMethod[methodID] = 111894
+		case UpgradeClient:
+			relayerGasRequiredByMethod[methodID] = 400000
+		case ConnectionOpenInit:
+			relayerGasRequiredByMethod[methodID] = 19755
+		case ConnectionOpenTry:
+			relayerGasRequiredByMethod[methodID] = 38468
+		case ConnectionOpenAck:
+			relayerGasRequiredByMethod[methodID] = 29603
+		case ConnectionOpenConfirm:
+			relayerGasRequiredByMethod[methodID] = 12865
+		case ChannelOpenInit:
+			relayerGasRequiredByMethod[methodID] = 68701
+		case ChannelOpenTry:
+			relayerGasRequiredByMethod[methodID] = 70562
+		case ChannelOpenAck:
+			relayerGasRequiredByMethod[methodID] = 22127
+		case ChannelOpenConfirm:
+			relayerGasRequiredByMethod[methodID] = 21190
+		case ChannelCloseConfirm:
+			relayerGasRequiredByMethod[methodID] = 31199
+		case RecvPacket:
+			relayerGasRequiredByMethod[methodID] = 144025
+		case Acknowledgement:
+			relayerGasRequiredByMethod[methodID] = 61781
+		case Timeout:
+			relayerGasRequiredByMethod[methodID] = 104283
 		case UpdateClientAndConnectionOpenTry:
 			relayerGasRequiredByMethod[methodID] = 150362
 		case UpdateClientAndConnectionOpenConfirm:

From 1ae96380e03b3b45e510859a8ad8c1e5fc8267b9 Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 27 Nov 2023 18:04:44 +0800
Subject: [PATCH 22/25] fix test

---
 integration_tests/configs/ibc_rly.jsonnet | 2 +-
 integration_tests/ibc_utils.py            | 1 +
 integration_tests/test_ibc_rly_gas.py     | 4 ++--
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/integration_tests/configs/ibc_rly.jsonnet b/integration_tests/configs/ibc_rly.jsonnet
index db80c79b02..f8755a7d45 100644
--- a/integration_tests/configs/ibc_rly.jsonnet
+++ b/integration_tests/configs/ibc_rly.jsonnet
@@ -18,7 +18,7 @@ ibc {
   relayer+: {
     chains: [super.chains[0] {
       max_gas: 1000000,
-      gas_multiplier: 1.2,
+      gas_multiplier: 1.1,
     }] + super.chains[1:],
   },
 }
diff --git a/integration_tests/ibc_utils.py b/integration_tests/ibc_utils.py
index 7f077cca82..37ce3606b2 100644
--- a/integration_tests/ibc_utils.py
+++ b/integration_tests/ibc_utils.py
@@ -667,3 +667,4 @@ def log_gas_records(cli):
         res = tx["tx_result"]
         if res["gas_used"]:
             records.append(res["gas_used"])
+    return records
diff --git a/integration_tests/test_ibc_rly_gas.py b/integration_tests/test_ibc_rly_gas.py
index aae57db849..850b9d618f 100644
--- a/integration_tests/test_ibc_rly_gas.py
+++ b/integration_tests/test_ibc_rly_gas.py
@@ -21,11 +21,11 @@ def test_ibc(ibc):
     cli = ibc.cronos.cosmos_cli()
     wait_for_new_blocks(cli, 1)
     rly_transfer(ibc)
-    diff = 0.001
+    diff = 0.002
     record = log_gas_records(cli)
     if record:
         records.append(record)
     if len(records) == 2:
         for e1, e2 in zip(*records):
-            res = e2 / e1
+            res = int(e2) / int(e1)
             assert 1 - diff <= res <= 1 + diff, res

From 1baba1bb57c82109f818b44678814ee2d48ce09a Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 27 Nov 2023 18:58:32 +0800
Subject: [PATCH 23/25] cleanup

---
 scripts/.env | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/scripts/.env b/scripts/.env
index 8b76c2a2fd..aa4225be27 100644
--- a/scripts/.env
+++ b/scripts/.env
@@ -1,24 +1,6 @@
 export PASSWORD='123456'
 export VALIDATOR1_MNEMONIC="visit craft resemble online window solution west chuckle music diesel vital settle comic tribe project blame bulb armed flower region sausage mercy arrive release"
 export VALIDATOR2_MNEMONIC="direct travel shrug hand twice agent sail sell jump phone velvet pilot mango charge usual multiply orient garment bleak virtual action mention panda vast"
-export VALIDATOR3_MNEMONIC="quit crush inherit magic tree rookie steel lemon junior need another immune brief genius series raccoon fringe immense view open bomb fancy hammer effort"
-export VALIDATOR4_MNEMONIC="topic elegant hero arena farm find step before clarify accident manage poem suffer actual winner legend gauge trap express problem obscure crucial crop knock"
-export VALIDATOR5_MNEMONIC="trip glory pet mention level mistake obey engage baby mountain culture lizard arrest rely bind liar honey host wink snow run artefact foot edit"
-export VALIDATOR6_MNEMONIC="mask ball border unaware much sketch feel cement neck impulse sun tower miss fetch shield horror shed blame bargain ride unlock weapon fold favorite"
-export VALIDATOR7_MNEMONIC="execute skull truth tattoo whale avoid proud print horse coin upgrade pig scatter federal token hour define verb inherit flee grit thunder town victory"
-export VALIDATOR8_MNEMONIC="fee endless venture glimpse fresh salad hard scrap magic state arrow color praise city noodle auto kind art promote rebel flat glove hard muffin"
-export VALIDATOR9_MNEMONIC="sign night wish check satoshi together husband boy gospel discover inch wealth magnet increase chalk mom begin deny found casino busy shiver letter either"
-export VALIDATOR10_MNEMONIC="this satoshi juice squirrel chair must shed useless pistol duty tray use annual frame game hour old sing anger discover arch mixed abuse few"
-export VALIDATOR11_MNEMONIC="portion found fancy solve team ill hidden scheme unaware next toward icon piano dinner hen access alter verb twin medal team dumb ball lamp"
-export VALIDATOR12_MNEMONIC="appear ship nation try twice smoke expose sand spirit burden bubble betray pulp coral receive civil case subway smoke foil rival horn dove myth"
-export VALIDATOR13_MNEMONIC="rebel fabric infant purpose toss boring crucial bone decorate input travel orphan whale rely holiday cloth split heavy soft flight unusual paddle play okay"
-export VALIDATOR14_MNEMONIC="keen solve version impulse wash coil mandate enrich devote one gaze cruise observe pass hospital empty stumble clip bench sock solid boost drama pluck"
-export VALIDATOR15_MNEMONIC="rather moon angry badge blast panic various couch roof loan infant bunker coin ahead junior hint rubber clever obvious tornado insect student trap case"
-export VALIDATOR16_MNEMONIC="meat crucial beauty build major shrimp tired example helmet heart account veteran innocent early gather audit wire dutch wisdom reward cube solar media canal"
-export VALIDATOR17_MNEMONIC="twenty author boil minor swap super once run push vibrant tower retire rain trigger indicate source armor trumpet long profit monkey bounce spell trend"
-export VALIDATOR18_MNEMONIC="sausage draw subway spike mix thumb begin pair inspire great squirrel tragic lazy slender bachelor pause oak celery glory feature shallow slide vendor lyrics"
-export VALIDATOR19_MNEMONIC="detect surprise oval quote unaware buyer ivory right maple cricket picnic unfair grab sting weather hair erosion course kiss wing ladder sure media season"
-export VALIDATOR20_MNEMONIC="dizzy patrol weird scatter rally furnace scatter pear smart clutch domain can tuition faculty clock friend build doctor emotion milk urge can message mix"
 export COMMUNITY_MNEMONIC="notable error gospel wave pair ugly measure elite toddler cost various fly make eye ketchup despair slab throw tribe swarm word fruit into inmate"
 export SIGNER1_MNEMONIC="shed crumble dismiss loyal latin million oblige gesture shrug still oxygen custom remove ribbon disorder palace addict again blanket sad flock consider obey popular"
 export SIGNER2_MNEMONIC="night renew tonight dinner shaft scheme domain oppose echo summer broccoli agent face guitar surface belt veteran siren poem alcohol menu custom crunch index"

From 5e91c620791ffcd9d031eed5450f11acfe07642a Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Mon, 27 Nov 2023 18:58:38 +0800
Subject: [PATCH 24/25] more buffer

---
 integration_tests/test_ibc_rly_gas.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/integration_tests/test_ibc_rly_gas.py b/integration_tests/test_ibc_rly_gas.py
index 850b9d618f..849b0a03e1 100644
--- a/integration_tests/test_ibc_rly_gas.py
+++ b/integration_tests/test_ibc_rly_gas.py
@@ -21,7 +21,7 @@ def test_ibc(ibc):
     cli = ibc.cronos.cosmos_cli()
     wait_for_new_blocks(cli, 1)
     rly_transfer(ibc)
-    diff = 0.002
+    diff = 0.004
     record = log_gas_records(cli)
     if record:
         records.append(record)

From 2dea6f454bb9c3e8fba2f7a9bd2ebd406227bf2e Mon Sep 17 00:00:00 2001
From: mmsqe <mavis@crypto.com>
Date: Wed, 29 Nov 2023 12:46:08 +0800
Subject: [PATCH 25/25] Apply suggestions from code review

---
 integration_tests/test_ibc_rly_gas.py  |  2 +-
 x/cronos/keeper/precompiles/relayer.go |  6 +++++-
 x/cronos/keeper/precompiles/utils.go   | 13 +++++++++----
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/integration_tests/test_ibc_rly_gas.py b/integration_tests/test_ibc_rly_gas.py
index 849b0a03e1..1c96710fef 100644
--- a/integration_tests/test_ibc_rly_gas.py
+++ b/integration_tests/test_ibc_rly_gas.py
@@ -27,5 +27,5 @@ def test_ibc(ibc):
         records.append(record)
     if len(records) == 2:
         for e1, e2 in zip(*records):
-            res = int(e2) / int(e1)
+            res = float(e2) / float(e1)
             assert 1 - diff <= res <= 1 + diff, res
diff --git a/x/cronos/keeper/precompiles/relayer.go b/x/cronos/keeper/precompiles/relayer.go
index d077f1d2fe..21084950b4 100644
--- a/x/cronos/keeper/precompiles/relayer.go
+++ b/x/cronos/keeper/precompiles/relayer.go
@@ -2,6 +2,7 @@ package precompiles
 
 import (
 	"errors"
+	"fmt"
 
 	"github.com/cometbft/cometbft/libs/log"
 	"github.com/cosmos/cosmos-sdk/codec"
@@ -180,6 +181,9 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	if readonly {
 		return nil, errors.New("the method is not readonly")
 	}
+	if len(contract.Input) < 4 {
+		return nil, errors.New("input too short")
+	}
 	// parse input
 	methodID := contract.Input[:4]
 	method, err := irelayerABI.MethodById(methodID)
@@ -273,7 +277,7 @@ func (bc *RelayerContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool
 	case UpdateClientAndTimeoutOnClose:
 		res, err = execMultiple(e, bc.ibcKeeper.UpdateClient, bc.ibcKeeper.TimeoutOnClose)
 	default:
-		return nil, errors.New("unknown method")
+		return nil, fmt.Errorf("unknown method: %s", method.Name)
 	}
 	return res, err
 }
diff --git a/x/cronos/keeper/precompiles/utils.go b/x/cronos/keeper/precompiles/utils.go
index fc60b3d26a..6c18271abe 100644
--- a/x/cronos/keeper/precompiles/utils.go
+++ b/x/cronos/keeper/precompiles/utils.go
@@ -43,8 +43,9 @@ func exec[Req any, PReq interface {
 	if len(signers) != 1 {
 		return nil, errors.New("don't support multi-signers message")
 	}
-	if common.BytesToAddress(signers[0].Bytes()) != e.caller {
-		return nil, errors.New("caller is not authenticated")
+	caller := common.BytesToAddress(signers[0].Bytes())
+	if caller != e.caller {
+		return nil, fmt.Errorf("caller is not authenticated: expected %s, got %s", e.caller.Hex(), caller.Hex())
 	}
 
 	var res Resp
@@ -56,7 +57,11 @@ func exec[Req any, PReq interface {
 		return nil, err
 	}
 
-	return e.cdc.Marshal(res)
+	output, err := e.cdc.Marshal(res)
+	if err != nil {
+		return nil, fmt.Errorf("fail to Marshal %T %w", res, err)
+	}
+	return output, nil
 }
 
 func execMultipleWithHooks[Req any,
@@ -89,7 +94,7 @@ func execMultipleWithHooks[Req any,
 
 	signers := msg.GetSigners()
 	if len(signers) != 1 {
-		return nil, errors.New("don't support multi-signers message")
+		return nil, fmt.Errorf("expected 1 signer, got %d", len(signers))
 	}
 	if common.BytesToAddress(signers[0].Bytes()) != e.caller {
 		return nil, errors.New("caller is not authenticated")