diff --git a/CHANGELOG.md b/CHANGELOG.md index e515016f88..a7b1ea865d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [cronos#1163](https://github.com/crypto-org-chain/cronos/pull/1163) Support stateful precompiled contract for ica. - [cronos#837](https://github.com/crypto-org-chain/cronos/pull/837) Support stateful precompiled contract for bank. - [cronos#1184](https://github.com/crypto-org-chain/cronos/pull/1184) Update ibc-go to `v7.3.1`. +- [cronos#1185](https://github.com/crypto-org-chain/cronos/pull/1185) Support ibc callback. ### Bug Fixes diff --git a/app/app.go b/app/app.go index 37ae47cd2c..bb31601a37 100644 --- a/app/app.go +++ b/app/app.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/fs" + "math" "net/http" "os" "path/filepath" @@ -98,6 +99,7 @@ import ( upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + ibccallbacks "github.com/cosmos/ibc-go/modules/apps/callbacks" ibcfee "github.com/cosmos/ibc-go/v7/modules/apps/29-fee" ibcfeekeeper "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/keeper" ibcfeetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types" @@ -551,7 +553,7 @@ func New( []vm.PrecompiledContract{ cronosprecompiles.NewBankContract(app.BankKeeper, appCodec), cronosprecompiles.NewRelayerContract(app.IBCKeeper, appCodec), - cronosprecompiles.NewIcaContract(&app.ICAAuthKeeper, appCodec), + cronosprecompiles.NewIcaContract(&app.ICAAuthKeeper, &app.CronosKeeper, appCodec), }, allKeys, ) @@ -655,8 +657,13 @@ func New( icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper) - icaControllerIBCModule := icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper) - icaControllerStack := ibcfee.NewIBCMiddleware(icaControllerIBCModule, app.IBCFeeKeeper) + var icaControllerStack porttypes.IBCModule + icaControllerStack = icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper) + icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) + // Since the callbacks middleware itself is an ics4wrapper, it needs to be passed to the ica controller keeper + app.ICAControllerKeeper.WithICS4Wrapper(icaControllerStack.(porttypes.Middleware)) + // we don't limit gas usage here, because the cronos keeper will use network parameter to control it. + icaControllerStack = ibccallbacks.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper, app.CronosKeeper, math.MaxUint64) // Create static IBC router, add transfer route, then set and seal it ibcRouter := porttypes.NewRouter() diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index ead7dc06aa..d1a7de27d8 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -452,6 +452,9 @@ paths: title: the admin address who can update token mapping enable_auto_deployment: type: boolean + max_callback_gas: + type: string + format: uint64 description: >- QueryParamsResponse is the response type for the Query/Params RPC method. @@ -43648,6 +43651,9 @@ definitions: title: the admin address who can update token mapping enable_auto_deployment: type: boolean + max_callback_gas: + type: string + format: uint64 description: Params defines the parameters for the cronos module. cronos.QueryParamsResponse: type: object @@ -43666,6 +43672,9 @@ definitions: title: the admin address who can update token mapping enable_auto_deployment: type: boolean + max_callback_gas: + type: string + format: uint64 description: QueryParamsResponse is the response type for the Query/Params RPC method. cronos.QueryPermissionsResponse: type: object diff --git a/go.mod b/go.mod index f65581b887..972d569792 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-beta.2 github.com/cosmos/cosmos-sdk v0.47.5 github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/modules/apps/callbacks v0.1.1-0.20230831194909-17cf1260a9cd github.com/cosmos/ibc-go/v7 v7.3.1-0.20230920070810-c3261472c815 github.com/crypto-org-chain/cronos/store v0.0.4 github.com/crypto-org-chain/cronos/versiondb v0.0.0-00010101000000-000000000000 diff --git a/go.sum b/go.sum index 46b6476148..033ff091b1 100644 --- a/go.sum +++ b/go.sum @@ -452,6 +452,8 @@ github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoK github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= github.com/cosmos/iavl v0.21.0-alpha.1.0.20230904092046-df3db2d96583 h1:3Matt7/LjZiZkIBPalYazOZcw2B05Ch14dU5TJyqJEc= github.com/cosmos/iavl v0.21.0-alpha.1.0.20230904092046-df3db2d96583/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/ibc-go/modules/apps/callbacks v0.1.1-0.20230831194909-17cf1260a9cd h1:KVnAwC1d0b+LWrVi+U1rex0e9LlyGTZ17zYhU3S4il8= +github.com/cosmos/ibc-go/modules/apps/callbacks v0.1.1-0.20230831194909-17cf1260a9cd/go.mod h1:h+JtOsdOs/ikuntjZFXOAa8qnXUfgkTcRSHaTTcAM+M= github.com/cosmos/ibc-go/v7 v7.3.1-0.20230920070810-c3261472c815 h1:raSo7w7B3IXCb7DZozHWz8ajG7HLWZw9foiyCbEgInI= github.com/cosmos/ibc-go/v7 v7.3.1-0.20230920070810-c3261472c815/go.mod h1:wvx4pPBofe5ZdMNV3OFRxSI4auEP5Qfqf8JXLLNV04g= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= diff --git a/gomod2nix.toml b/gomod2nix.toml index f5bf557fb7..af1504ac59 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -154,6 +154,9 @@ schema = 3 [mod."github.com/cosmos/iavl"] version = "v0.21.0-alpha.1.0.20230904092046-df3db2d96583" hash = "sha256-3Va8Ljq63IXty0oHlRpqfsC6WsMut6TWZ2R+/nYtfTU=" + [mod."github.com/cosmos/ibc-go/modules/apps/callbacks"] + version = "v0.1.1-0.20230831194909-17cf1260a9cd" + hash = "sha256-kVvGNQt3A1H6pQs3YtMvx1t9nNcL6ClKnIfsR24OTi8=" [mod."github.com/cosmos/ibc-go/v7"] version = "v7.3.1-0.20230920070810-c3261472c815" hash = "sha256-x/D64hmU+aOc5sm8RzXMB+8y+530+CCEik/Zpj3Rf9A=" diff --git a/integration_tests/contracts/contracts/TestICA.sol b/integration_tests/contracts/contracts/TestICA.sol index c4c80ab023..c8c901fab4 100644 --- a/integration_tests/contracts/contracts/TestICA.sol +++ b/integration_tests/contracts/contracts/TestICA.sol @@ -7,7 +7,12 @@ contract TestICA { address constant icaContract = 0x0000000000000000000000000000000000000066; IICAModule ica = IICAModule(icaContract); address account; + // sha256('cronos-evm')[:20] + address constant module_address = 0x89A7EF2F08B1c018D5Cc88836249b84Dd5392905; uint64 lastAckSeq; + bool lastAck; + mapping (uint64 => bool) public acknowledgement; + event OnPacketResult(uint64 seq, bool ack); function encodeRegister(string memory connectionID, string memory version) internal view returns (bytes memory) { return abi.encodeWithSignature( @@ -92,4 +97,18 @@ contract TestICA { function getLastAckSeq() public view returns (uint256) { return lastAckSeq; } -} \ No newline at end of file + + function getLastAck() public view returns (bool) { + return lastAck; + } + + function onPacketResultCallback(uint64 seq, bool ack) external payable returns (bool) { + // To prevent called by arbitrary user + require(msg.sender == module_address); + lastAckSeq = seq; + lastAck = ack; + acknowledgement[seq] = ack; + emit OnPacketResult(seq, ack); + return true; + } +} diff --git a/integration_tests/test_gov_update_params.py b/integration_tests/test_gov_update_params.py index 14f31d12af..b6efb5f8b3 100644 --- a/integration_tests/test_gov_update_params.py +++ b/integration_tests/test_gov_update_params.py @@ -9,18 +9,20 @@ def test_gov_update_params(cronos, tmp_path): proposal = tmp_path / "proposal.json" # governance module account as signer signer = "crc10d07y265gmmuvt4z0w9aw880jnsr700jdufnyd" + params = { + "cronos_admin": "crc12luku6uxehhak02py4rcz65zu0swh7wjsrw0pp", + "enable_auto_deployment": False, + "ibc_cro_denom": "ibc/6411AE2ADA1E73DB59DB151" + "A8988F9B7D5E7E233D8414DB6817F8F1A01600000", + "ibc_timeout": "96400000000000", + "max_callback_gas": "400000", + } proposal_src = { "messages": [ { "@type": "/cronos.MsgUpdateParams", "authority": signer, - "params": { - "cronos_admin": "crc12luku6uxehhak02py4rcz65zu0swh7wjsrw0pp", - "enable_auto_deployment": False, - "ibc_cro_denom": "ibc/6411AE2ADA1E73DB59DB151" - "A8988F9B7D5E7E233D8414DB6817F8F1A01600000", - "ibc_timeout": "96400000000000", - }, + "params": params, } ], "deposit": "1basetcro", @@ -35,10 +37,4 @@ def test_gov_update_params(cronos, tmp_path): print("check params have been updated now") rsp = cli.query_params() print("params", rsp) - assert rsp == { - "cronos_admin": "crc12luku6uxehhak02py4rcz65zu0swh7wjsrw0pp", - "enable_auto_deployment": False, - "ibc_cro_denom": "ibc/6411AE2ADA1E73DB59DB151" - "A8988F9B7D5E7E233D8414DB6817F8F1A01600000", - "ibc_timeout": "96400000000000", - } + assert rsp == params diff --git a/integration_tests/test_ica_precompile.py b/integration_tests/test_ica_precompile.py index 7aa08e714c..51dab1cd8b 100644 --- a/integration_tests/test_ica_precompile.py +++ b/integration_tests/test_ica_precompile.py @@ -191,6 +191,8 @@ def submit_msgs_ro(func, str): submit_msgs_ro(tcontract.functions.staticSubmitMsgs, str) assert tcontract.caller.getLastAckSeq() == seq balance -= amt + ack = tcontract.caller.getLastAck() + assert ack == tcontract.caller.acknowledgement(seq), ack assert cli_host.balance(ica_address, denom=denom) == balance seq = 2 str = submit_msgs( @@ -206,3 +208,4 @@ def submit_msgs_ro(func, str): balance -= amt balance -= amt1 assert cli_host.balance(ica_address, denom=denom) == balance + assert ack == tcontract.caller.acknowledgement(seq), ack diff --git a/integration_tests/test_upgrade.py b/integration_tests/test_upgrade.py index 02f6100250..4513d141ab 100644 --- a/integration_tests/test_upgrade.py +++ b/integration_tests/test_upgrade.py @@ -186,6 +186,7 @@ def test_cosmovisor_upgrade(custom_cronos: Cronos, tmp_path_factory): rsp = cli.query_params("icaauth") assert rsp["params"]["min_timeout_duration"] == "3600s", rsp + assert cli.query_params()["max_callback_gas"] == "300000", rsp # migrate to sdk v0.47 custom_cronos.supervisorctl("stop", "all") diff --git a/proto/cronos/cronos.proto b/proto/cronos/cronos.proto index ccfbf53d1e..06172ad52b 100644 --- a/proto/cronos/cronos.proto +++ b/proto/cronos/cronos.proto @@ -13,6 +13,7 @@ message Params { // the admin address who can update token mapping string cronos_admin = 3; bool enable_auto_deployment = 4; + uint64 max_callback_gas = 5; } // TokenMappingChangeProposal defines a proposal to change one token mapping. diff --git a/scripts/gen-bindings-contracts b/scripts/gen-bindings-contracts index 52d629244b..4c55e25c2b 100755 --- a/scripts/gen-bindings-contracts +++ b/scripts/gen-bindings-contracts @@ -4,9 +4,11 @@ solc08 --abi --bin x/cronos/events/bindings/src/CosmosTypes.sol -o build --overw solc08 --abi --bin x/cronos/events/bindings/src/Relayer.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 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 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/icacallback/i_ica_callback.abigen.go b/x/cronos/events/bindings/cosmos/precompile/icacallback/i_ica_callback.abigen.go new file mode 100644 index 0000000000..239ef1503a --- /dev/null +++ b/x/cronos/events/bindings/cosmos/precompile/icacallback/i_ica_callback.abigen.go @@ -0,0 +1,201 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package icacallback + +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 +) + +// ICACallbackMetaData contains all meta data concerning the ICACallback contract. +var ICACallbackMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"seq\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"ack\",\"type\":\"bool\"}],\"name\":\"onPacketResultCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", +} + +// ICACallbackABI is the input ABI used to generate the binding from. +// Deprecated: Use ICACallbackMetaData.ABI instead. +var ICACallbackABI = ICACallbackMetaData.ABI + +// ICACallback is an auto generated Go binding around an Ethereum contract. +type ICACallback struct { + ICACallbackCaller // Read-only binding to the contract + ICACallbackTransactor // Write-only binding to the contract + ICACallbackFilterer // Log filterer for contract events +} + +// ICACallbackCaller is an auto generated read-only Go binding around an Ethereum contract. +type ICACallbackCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ICACallbackTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ICACallbackTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ICACallbackFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ICACallbackFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ICACallbackSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ICACallbackSession struct { + Contract *ICACallback // 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 +} + +// ICACallbackCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ICACallbackCallerSession struct { + Contract *ICACallbackCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ICACallbackTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ICACallbackTransactorSession struct { + Contract *ICACallbackTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ICACallbackRaw is an auto generated low-level Go binding around an Ethereum contract. +type ICACallbackRaw struct { + Contract *ICACallback // Generic contract binding to access the raw methods on +} + +// ICACallbackCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ICACallbackCallerRaw struct { + Contract *ICACallbackCaller // Generic read-only contract binding to access the raw methods on +} + +// ICACallbackTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ICACallbackTransactorRaw struct { + Contract *ICACallbackTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewICACallback creates a new instance of ICACallback, bound to a specific deployed contract. +func NewICACallback(address common.Address, backend bind.ContractBackend) (*ICACallback, error) { + contract, err := bindICACallback(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ICACallback{ICACallbackCaller: ICACallbackCaller{contract: contract}, ICACallbackTransactor: ICACallbackTransactor{contract: contract}, ICACallbackFilterer: ICACallbackFilterer{contract: contract}}, nil +} + +// NewICACallbackCaller creates a new read-only instance of ICACallback, bound to a specific deployed contract. +func NewICACallbackCaller(address common.Address, caller bind.ContractCaller) (*ICACallbackCaller, error) { + contract, err := bindICACallback(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ICACallbackCaller{contract: contract}, nil +} + +// NewICACallbackTransactor creates a new write-only instance of ICACallback, bound to a specific deployed contract. +func NewICACallbackTransactor(address common.Address, transactor bind.ContractTransactor) (*ICACallbackTransactor, error) { + contract, err := bindICACallback(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ICACallbackTransactor{contract: contract}, nil +} + +// NewICACallbackFilterer creates a new log filterer instance of ICACallback, bound to a specific deployed contract. +func NewICACallbackFilterer(address common.Address, filterer bind.ContractFilterer) (*ICACallbackFilterer, error) { + contract, err := bindICACallback(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ICACallbackFilterer{contract: contract}, nil +} + +// bindICACallback binds a generic wrapper to an already deployed contract. +func bindICACallback(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ICACallbackABI)) + 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 (_ICACallback *ICACallbackRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ICACallback.Contract.ICACallbackCaller.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 (_ICACallback *ICACallbackRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ICACallback.Contract.ICACallbackTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ICACallback *ICACallbackRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ICACallback.Contract.ICACallbackTransactor.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 (_ICACallback *ICACallbackCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ICACallback.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 (_ICACallback *ICACallbackTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ICACallback.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ICACallback *ICACallbackTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ICACallback.Contract.contract.Transact(opts, method, params...) +} + +// OnPacketResultCallback is a paid mutator transaction binding the contract method 0x74fb6019. +// +// Solidity: function onPacketResultCallback(uint64 seq, bool ack) payable returns(bool) +func (_ICACallback *ICACallbackTransactor) OnPacketResultCallback(opts *bind.TransactOpts, seq uint64, ack bool) (*types.Transaction, error) { + return _ICACallback.contract.Transact(opts, "onPacketResultCallback", seq, ack) +} + +// OnPacketResultCallback is a paid mutator transaction binding the contract method 0x74fb6019. +// +// Solidity: function onPacketResultCallback(uint64 seq, bool ack) payable returns(bool) +func (_ICACallback *ICACallbackSession) OnPacketResultCallback(seq uint64, ack bool) (*types.Transaction, error) { + return _ICACallback.Contract.OnPacketResultCallback(&_ICACallback.TransactOpts, seq, ack) +} + +// OnPacketResultCallback is a paid mutator transaction binding the contract method 0x74fb6019. +// +// Solidity: function onPacketResultCallback(uint64 seq, bool ack) payable returns(bool) +func (_ICACallback *ICACallbackTransactorSession) OnPacketResultCallback(seq uint64, ack bool) (*types.Transaction, error) { + return _ICACallback.Contract.OnPacketResultCallback(&_ICACallback.TransactOpts, seq, ack) +} diff --git a/x/cronos/events/bindings/src/ICACallback.sol b/x/cronos/events/bindings/src/ICACallback.sol new file mode 100644 index 0000000000..aa3a779513 --- /dev/null +++ b/x/cronos/events/bindings/src/ICACallback.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +interface IICACallback { + function onPacketResultCallback(uint64 seq, bool ack) external payable returns (bool); +} diff --git a/x/cronos/events/events.go b/x/cronos/events/events.go index 57da3426ff..d4b0a98be4 100644 --- a/x/cronos/events/events.go +++ b/x/cronos/events/events.go @@ -35,9 +35,7 @@ var ( transfertypes.AttributeKeyDenom: ReturnStringAsIs, } IcaValueDecoders = ValueDecoders{ - channeltypes.AttributeKeyChannelID: ReturnStringAsIs, - channeltypes.AttributeKeyPortID: ReturnStringAsIs, - cronoseventstypes.AttributeKeySeq: ConvertUint64, + cronoseventstypes.AttributeKeySeq: ConvertUint64, } ) diff --git a/x/cronos/exported/exported.go b/x/cronos/exported/exported.go index 000114e619..64dc23a561 100644 --- a/x/cronos/exported/exported.go +++ b/x/cronos/exported/exported.go @@ -13,6 +13,6 @@ type ( // // NOTE: This is used solely for migration of x/params managed parameters. Subspace interface { - GetParamSet(ctx sdk.Context, ps ParamSet) + GetParamSetIfExists(ctx sdk.Context, ps ParamSet) } ) diff --git a/x/cronos/keeper/evm.go b/x/cronos/keeper/evm.go index b5b1cfe42d..3b17abb73b 100644 --- a/x/cronos/keeper/evm.go +++ b/x/cronos/keeper/evm.go @@ -18,20 +18,19 @@ import ( const DefaultGasCap uint64 = 25000000 // CallEVM execute an evm message from native module -func (k Keeper) CallEVM(ctx sdk.Context, to *common.Address, data []byte, value *big.Int) (*ethtypes.Message, *evmtypes.MsgEthereumTxResponse, error) { +func (k Keeper) CallEVM(ctx sdk.Context, to *common.Address, data []byte, value *big.Int, gasLimit uint64) (*ethtypes.Message, *evmtypes.MsgEthereumTxResponse, error) { nonce := k.evmKeeper.GetNonce(ctx, types.EVMModuleAddress) msg := ethtypes.NewMessage( types.EVMModuleAddress, to, nonce, value, // amount - DefaultGasCap, + gasLimit, big.NewInt(0), nil, nil, // gasPrice data, nil, // accessList false, // isFake ) - ret, err := k.evmKeeper.ApplyMessage(ctx, msg, nil, true) if err != nil { return nil, nil, err @@ -45,7 +44,7 @@ func (k Keeper) CallModuleCRC21(ctx sdk.Context, contract common.Address, method if err != nil { return nil, err } - _, res, err := k.CallEVM(ctx, &contract, data, big.NewInt(0)) + _, res, err := k.CallEVM(ctx, &contract, data, big.NewInt(0), DefaultGasCap) if err != nil { return nil, err } @@ -64,7 +63,7 @@ func (k Keeper) DeployModuleCRC21(ctx sdk.Context, denom string) (common.Address data := types.ModuleCRC21Contract.Bin data = append(data, ctor...) - msg, res, err := k.CallEVM(ctx, nil, data, big.NewInt(0)) + msg, res, err := k.CallEVM(ctx, nil, data, big.NewInt(0), DefaultGasCap) if err != nil { return common.Address{}, err } diff --git a/x/cronos/keeper/keeper.go b/x/cronos/keeper/keeper.go index d59b2005a6..8a013756a4 100644 --- a/x/cronos/keeper/keeper.go +++ b/x/cronos/keeper/keeper.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "math/big" "strings" "cosmossdk.io/errors" @@ -15,6 +16,11 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ibcfeetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/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" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + cronosprecompiles "github.com/crypto-org-chain/cronos/v2/x/cronos/keeper/precompiles" "github.com/crypto-org-chain/cronos/v2/x/cronos/types" "github.com/ethereum/go-ethereum/common" // this line is used by starport scaffolding # ibc/keeper/import @@ -276,3 +282,74 @@ func (k Keeper) RegisterOrUpdateTokenMapping(ctx sdk.Context, msg *types.MsgUpda return nil } + +func (k Keeper) onPacketResult( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement bool, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, +) error { + contractAddr := common.HexToAddress(contractAddress) + + data, err := cronosprecompiles.OnPacketResultCallback(packet.Sequence, acknowledgement) + if err != nil { + return err + } + gasLimit := k.GetParams(ctx).MaxCallbackGas + _, _, err = k.CallEVM(ctx, &contractAddr, data, big.NewInt(0), gasLimit) + return err +} + +func (k Keeper) IBCOnAcknowledgementPacketCallback( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, +) error { + // the ack is wrapped by fee middleware + var ack ibcfeetypes.IncentivizedAcknowledgement + if err := k.cdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + return err + } + var res channeltypes.Acknowledgement + if err := k.cdc.UnmarshalJSON(ack.AppAcknowledgement, &res); err != nil { + return err + } + return k.onPacketResult(ctx, packet, res.Success(), relayer, contractAddress, packetSenderAddress) +} + +func (k Keeper) IBCOnTimeoutPacketCallback( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, +) error { + return k.onPacketResult(ctx, packet, false, relayer, contractAddress, packetSenderAddress) +} + +func (k Keeper) IBCReceivePacketCallback( + ctx sdk.Context, + packet ibcexported.PacketI, + ack ibcexported.Acknowledgement, + contractAddress string, +) error { + return nil +} + +func (k Keeper) IBCSendPacketCallback( + ctx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + packetData []byte, + contractAddress, + packetSenderAddress string, +) error { + return nil +} diff --git a/x/cronos/keeper/precompiles/ica.go b/x/cronos/keeper/precompiles/ica.go index 077627acb1..838de825fb 100644 --- a/x/cronos/keeper/precompiles/ica.go +++ b/x/cronos/keeper/precompiles/ica.go @@ -11,9 +11,11 @@ import ( icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/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/ica" + "github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/icacallback" cronoseventstypes "github.com/crypto-org-chain/cronos/v2/x/cronos/events/types" - icaauthkeeper "github.com/crypto-org-chain/cronos/v2/x/icaauth/keeper" - "github.com/crypto-org-chain/cronos/v2/x/icaauth/types" + "github.com/crypto-org-chain/cronos/v2/x/cronos/types" + + icaauthtypes "github.com/crypto-org-chain/cronos/v2/x/icaauth/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -24,6 +26,7 @@ const ICAContractRequiredGas = 10000 var ( icaABI abi.ABI + icaCallbackABI abi.ABI icaContractAddress = common.BytesToAddress([]byte{102}) ) @@ -31,20 +34,29 @@ func init() { if err := icaABI.UnmarshalJSON([]byte(ica.ICAModuleMetaData.ABI)); err != nil { panic(err) } + if err := icaCallbackABI.UnmarshalJSON([]byte(icacallback.ICACallbackMetaData.ABI)); err != nil { + panic(err) + } +} + +func OnPacketResultCallback(args ...interface{}) ([]byte, error) { + return icaCallbackABI.Pack("onPacketResultCallback", args...) } type IcaContract struct { BaseContract cdc codec.Codec - icaauthKeeper *icaauthkeeper.Keeper + icaauthKeeper types.Icaauthkeeper + cronosKeeper types.CronosKeeper } -func NewIcaContract(icaauthKeeper *icaauthkeeper.Keeper, cdc codec.Codec) vm.PrecompiledContract { +func NewIcaContract(icaauthKeeper types.Icaauthkeeper, cronosKeeper types.CronosKeeper, cdc codec.Codec) vm.PrecompiledContract { return &IcaContract{ BaseContract: NewBaseContract(icaContractAddress), cdc: cdc, icaauthKeeper: icaauthKeeper, + cronosKeeper: cronosKeeper, } } @@ -68,7 +80,6 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ if err != nil { return nil, err } - stateDB := evm.StateDB.(ExtStateDB) precompileAddr := ic.Address() caller := contract.CallerAddress @@ -87,7 +98,7 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ connectionID := args[0].(string) version := args[1].(string) execErr = stateDB.ExecuteNativeAction(precompileAddr, converter, func(ctx sdk.Context) error { - _, err := ic.icaauthKeeper.RegisterAccount(ctx, &types.MsgRegisterAccount{ + _, err := ic.icaauthKeeper.RegisterAccount(ctx, &icaauthtypes.MsgRegisterAccount{ Owner: owner, ConnectionId: connectionID, Version: version, @@ -109,7 +120,7 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ icaAddress := "" response, err := ic.icaauthKeeper.InterchainAccountAddress( stateDB.CacheContext(), - &types.QueryInterchainAccountAddressRequest{ + &icaauthtypes.QueryInterchainAccountAddressRequest{ Owner: owner, ConnectionId: connectionID, }) @@ -134,6 +145,7 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ icaMsgData := icatypes.InterchainAccountPacketData{ Type: icatypes.EXECUTE_TX, Data: data, + Memo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, caller.String()), } timeoutDuration := time.Duration(timeout.Uint64()) seq := uint64(0) diff --git a/x/cronos/migrations/v2/migrate.go b/x/cronos/migrations/v2/migrate.go index 438bca6a14..2f0a383a4c 100644 --- a/x/cronos/migrations/v2/migrate.go +++ b/x/cronos/migrations/v2/migrate.go @@ -13,12 +13,14 @@ import ( // module state. func Migrate(ctx sdk.Context, store sdk.KVStore, legacySubspace exported.Subspace, cdc codec.BinaryCodec) error { var currParams types.Params - legacySubspace.GetParamSet(ctx, &currParams) + legacySubspace.GetParamSetIfExists(ctx, &currParams) if err := currParams.Validate(); err != nil { return err } - + if currParams.GetMaxCallbackGas() == 0 { + currParams.MaxCallbackGas = types.MaxCallbackGasDefaultValue + } bz := cdc.MustMarshal(&currParams) store.Set(types.ParamsKey, bz) diff --git a/x/cronos/migrations/v2/migrate_test.go b/x/cronos/migrations/v2/migrate_test.go index aff338f375..5240f3f2fa 100644 --- a/x/cronos/migrations/v2/migrate_test.go +++ b/x/cronos/migrations/v2/migrate_test.go @@ -20,7 +20,7 @@ func newMockSubspace(ps types.Params) mockSubspace { return mockSubspace{ps: ps} } -func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) { +func (ms mockSubspace) GetParamSetIfExists(ctx sdk.Context, ps exported.ParamSet) { *ps.(*types.Params) = ms.ps } diff --git a/x/cronos/simulation/genesis.go b/x/cronos/simulation/genesis.go index 413f8f63a1..a63467f277 100644 --- a/x/cronos/simulation/genesis.go +++ b/x/cronos/simulation/genesis.go @@ -17,6 +17,7 @@ const ( ibcTimeoutKey = "ibc_timeout" cronosAdminKey = "cronos_admin" enableAutoDeploymentKey = "enable_auto_deployment" + maxCallbackGasKey = "max_callback_gas" ) func GenIbcCroDenom(r *rand.Rand) string { @@ -39,6 +40,11 @@ func GenEnableAutoDeployment(r *rand.Rand) bool { return r.Intn(2) > 0 } +func GenMaxCallbackGas(r *rand.Rand) uint64 { + maxCallbackGas := r.Uint64() + return maxCallbackGas +} + // RandomizedGenState generates a random GenesisState for the cronos module func RandomizedGenState(simState *module.SimulationState) { // cronos params @@ -47,6 +53,7 @@ func RandomizedGenState(simState *module.SimulationState) { ibcTimeout uint64 cronosAdmin string enableAutoDeployment bool + maxCallbackGas uint64 ) simState.AppParams.GetOrGenerate( @@ -69,7 +76,12 @@ func RandomizedGenState(simState *module.SimulationState) { func(r *rand.Rand) { enableAutoDeployment = GenEnableAutoDeployment(r) }, ) - params := types.NewParams(ibcCroDenom, ibcTimeout, cronosAdmin, enableAutoDeployment) + simState.AppParams.GetOrGenerate( + simState.Cdc, maxCallbackGasKey, &ibcTimeout, simState.Rand, + func(r *rand.Rand) { maxCallbackGas = GenIbcTimeout(r) }, + ) + + params := types.NewParams(ibcCroDenom, ibcTimeout, cronosAdmin, enableAutoDeployment, maxCallbackGas) cronosGenesis := &types.GenesisState{ Params: params, ExternalContracts: nil, diff --git a/x/cronos/types/cronos.pb.go b/x/cronos/types/cronos.pb.go index fbafdecb6c..12324030f2 100644 --- a/x/cronos/types/cronos.pb.go +++ b/x/cronos/types/cronos.pb.go @@ -30,6 +30,7 @@ type Params struct { // the admin address who can update token mapping CronosAdmin string `protobuf:"bytes,3,opt,name=cronos_admin,json=cronosAdmin,proto3" json:"cronos_admin,omitempty"` EnableAutoDeployment bool `protobuf:"varint,4,opt,name=enable_auto_deployment,json=enableAutoDeployment,proto3" json:"enable_auto_deployment,omitempty"` + MaxCallbackGas uint64 `protobuf:"varint,5,opt,name=max_callback_gas,json=maxCallbackGas,proto3" json:"max_callback_gas,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -92,6 +93,13 @@ func (m *Params) GetEnableAutoDeployment() bool { return false } +func (m *Params) GetMaxCallbackGas() uint64 { + if m != nil { + return m.MaxCallbackGas + } + return 0 +} + // TokenMappingChangeProposal defines a proposal to change one token mapping. type TokenMappingChangeProposal struct { Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` @@ -197,34 +205,36 @@ func init() { func init() { proto.RegisterFile("cronos/cronos.proto", fileDescriptor_8bc54992a93db2d2) } var fileDescriptor_8bc54992a93db2d2 = []byte{ - // 422 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xbd, 0x6e, 0xdb, 0x30, - 0x14, 0x85, 0xc5, 0xd4, 0x51, 0x6d, 0x3a, 0x59, 0x58, 0x23, 0x10, 0x3c, 0xc8, 0xaa, 0x26, 0x0f, - 0x4d, 0x04, 0xb4, 0x99, 0x3c, 0x35, 0x3f, 0xe8, 0xd6, 0x22, 0x20, 0x32, 0x75, 0x11, 0x28, 0x8a, - 0x90, 0x89, 0x8a, 0xbc, 0x04, 0x45, 0x15, 0xd5, 0x1b, 0x74, 0xec, 0xd8, 0x31, 0xcf, 0xd2, 0xa9, - 0xa3, 0xc7, 0x4e, 0x45, 0x61, 0xbf, 0x41, 0x9f, 0xa0, 0x90, 0x98, 0xa4, 0xc9, 0x90, 0x49, 0xf7, - 0x3b, 0x07, 0xc2, 0x39, 0x97, 0xb8, 0xf8, 0x05, 0xb7, 0xa0, 0xa1, 0xc9, 0xfc, 0xe7, 0xc4, 0x58, - 0x70, 0x40, 0x42, 0x4f, 0xf3, 0x59, 0x05, 0x15, 0x0c, 0x52, 0xd6, 0x4f, 0xde, 0x4d, 0x37, 0x08, - 0x87, 0x57, 0xcc, 0x32, 0xd5, 0x90, 0x77, 0xf8, 0x50, 0x16, 0x3c, 0xe7, 0x16, 0xf2, 0x52, 0x68, - 0x50, 0x11, 0x4a, 0xd0, 0x72, 0x72, 0x9e, 0xfe, 0xfd, 0xbd, 0x88, 0x3b, 0xa6, 0xea, 0x55, 0xfa, - 0xc8, 0x7e, 0x05, 0x4a, 0x3a, 0xa1, 0x8c, 0xeb, 0x52, 0x3a, 0x95, 0x05, 0xbf, 0xb0, 0x70, 0xd9, - 0xeb, 0x64, 0x81, 0x7b, 0xcc, 0x9d, 0x54, 0x02, 0x5a, 0x17, 0xed, 0x25, 0x68, 0x39, 0xa2, 0x58, - 0x16, 0xfc, 0xda, 0x2b, 0xe4, 0x25, 0x3e, 0xf0, 0x9d, 0x72, 0x56, 0x2a, 0xa9, 0xa3, 0x67, 0x7d, - 0x0e, 0x9d, 0x7a, 0xed, 0xac, 0x97, 0xc8, 0x29, 0x3e, 0x12, 0x9a, 0x15, 0xb5, 0xc8, 0x59, 0xeb, - 0xfa, 0x40, 0x53, 0x43, 0xa7, 0x84, 0x76, 0xd1, 0x28, 0x41, 0xcb, 0x31, 0x9d, 0x79, 0xf7, 0xac, - 0x75, 0x70, 0x79, 0xef, 0xad, 0x46, 0xdf, 0x6f, 0x16, 0x41, 0xfa, 0x03, 0xe1, 0xf9, 0x35, 0x7c, - 0x12, 0xfa, 0x3d, 0x33, 0x46, 0xea, 0xea, 0x62, 0xcd, 0x74, 0x25, 0xae, 0x2c, 0x18, 0x68, 0x58, - 0x4d, 0x66, 0x78, 0xdf, 0x49, 0x57, 0x0b, 0xbf, 0x1e, 0xf5, 0x40, 0x12, 0x3c, 0x2d, 0x45, 0xc3, - 0xad, 0x34, 0x4e, 0x82, 0x1e, 0x4a, 0x4f, 0xe8, 0x43, 0xa9, 0xff, 0xcf, 0x3f, 0x8b, 0xaf, 0xeb, - 0x81, 0xcc, 0xf1, 0x98, 0x83, 0x76, 0x96, 0x71, 0x5f, 0x6d, 0x42, 0xef, 0x99, 0x1c, 0xe1, 0xb0, - 0xe9, 0x54, 0x01, 0x75, 0xb4, 0x3f, 0x38, 0xb7, 0x44, 0x22, 0xfc, 0xbc, 0x14, 0x5c, 0x2a, 0x56, - 0x47, 0x61, 0x82, 0x96, 0x87, 0xf4, 0x0e, 0x57, 0xe3, 0xaf, 0x37, 0x8b, 0x60, 0x58, 0xe2, 0x2d, - 0x3e, 0x78, 0xb8, 0xc3, 0xff, 0x74, 0xf4, 0x54, 0xfa, 0xde, 0xe3, 0xf4, 0xf3, 0x0f, 0x3f, 0xb7, - 0x31, 0xda, 0x6c, 0x63, 0xf4, 0x67, 0x1b, 0xa3, 0x6f, 0xbb, 0x38, 0xd8, 0xec, 0xe2, 0xe0, 0xd7, - 0x2e, 0x0e, 0x3e, 0x9e, 0x56, 0xd2, 0xad, 0xdb, 0xe2, 0x84, 0x83, 0xca, 0xb8, 0xed, 0x8c, 0x83, - 0x63, 0xb0, 0xd5, 0x31, 0x5f, 0x33, 0xa9, 0x6f, 0x6f, 0x27, 0xfb, 0xfc, 0x3a, 0xfb, 0x72, 0x37, - 0xbb, 0xce, 0x88, 0xa6, 0x08, 0x87, 0x83, 0x79, 0xf3, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x3d, 0x74, - 0x94, 0x69, 0x65, 0x02, 0x00, 0x00, + // 451 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xb1, 0x6f, 0xd3, 0x40, + 0x14, 0xc6, 0x7d, 0x25, 0x35, 0xc9, 0xa5, 0x45, 0xe8, 0x88, 0x2a, 0x2b, 0x83, 0x63, 0x3c, 0x79, + 0xa0, 0xb5, 0x04, 0x9d, 0x32, 0xd1, 0xa6, 0x82, 0x09, 0x54, 0x59, 0x9d, 0x58, 0xac, 0xf3, 0xe5, + 0xe4, 0x9c, 0xea, 0xbb, 0x77, 0x3a, 0x5f, 0x50, 0xfc, 0x1f, 0x30, 0x32, 0x32, 0xf6, 0x6f, 0x61, + 0x62, 0xec, 0xc8, 0x84, 0x50, 0xf2, 0x1f, 0x30, 0x32, 0x21, 0xfb, 0xd2, 0xd2, 0x0c, 0x9d, 0x7c, + 0xdf, 0xef, 0x93, 0xf5, 0xbd, 0xef, 0xe9, 0xe1, 0x17, 0xcc, 0x80, 0x82, 0x3a, 0x75, 0x9f, 0x13, + 0x6d, 0xc0, 0x02, 0xf1, 0x9d, 0x1a, 0x8f, 0x4a, 0x28, 0xa1, 0x43, 0x69, 0xfb, 0x72, 0x6e, 0xfc, + 0x17, 0x61, 0xff, 0x92, 0x1a, 0x2a, 0x6b, 0xf2, 0x0e, 0x1f, 0x8a, 0x82, 0xe5, 0xcc, 0x40, 0x3e, + 0xe7, 0x0a, 0x64, 0x80, 0x22, 0x94, 0x0c, 0xce, 0xe3, 0x3f, 0xbf, 0x26, 0x61, 0x43, 0x65, 0x35, + 0x8d, 0x77, 0xec, 0x57, 0x20, 0x85, 0xe5, 0x52, 0xdb, 0x26, 0xce, 0x86, 0xa2, 0x60, 0x33, 0x03, + 0x17, 0x2d, 0x27, 0x13, 0xdc, 0xca, 0xdc, 0x0a, 0xc9, 0x61, 0x69, 0x83, 0xbd, 0x08, 0x25, 0xbd, + 0x0c, 0x8b, 0x82, 0x5d, 0x39, 0x42, 0x5e, 0xe2, 0x03, 0x37, 0x53, 0x4e, 0xe7, 0x52, 0xa8, 0xe0, + 0x49, 0x9b, 0x93, 0x0d, 0x1d, 0x3b, 0x6b, 0x11, 0x39, 0xc5, 0x47, 0x5c, 0xd1, 0xa2, 0xe2, 0x39, + 0x5d, 0xda, 0x36, 0x50, 0x57, 0xd0, 0x48, 0xae, 0x6c, 0xd0, 0x8b, 0x50, 0xd2, 0xcf, 0x46, 0xce, + 0x3d, 0x5b, 0x5a, 0xb8, 0xb8, 0xf7, 0x48, 0x82, 0x9f, 0x4b, 0xba, 0xca, 0x19, 0xad, 0xaa, 0x82, + 0xb2, 0xeb, 0xbc, 0xa4, 0x75, 0xb0, 0xdf, 0xc5, 0x3f, 0x93, 0x74, 0x35, 0xdb, 0xe2, 0xf7, 0xb4, + 0x9e, 0xf6, 0xbe, 0xdd, 0x4c, 0xbc, 0xf8, 0x3b, 0xc2, 0xe3, 0x2b, 0xb8, 0xe6, 0xea, 0x03, 0xd5, + 0x5a, 0xa8, 0x72, 0xb6, 0xa0, 0xaa, 0xe4, 0x97, 0x06, 0x34, 0xd4, 0xb4, 0x22, 0x23, 0xbc, 0x6f, + 0x85, 0xad, 0xb8, 0x5b, 0x44, 0xe6, 0x04, 0x89, 0xf0, 0x70, 0xce, 0x6b, 0x66, 0x84, 0xb6, 0x02, + 0x54, 0x57, 0x6f, 0x90, 0x3d, 0x44, 0xed, 0x7f, 0x6e, 0x81, 0xae, 0x98, 0x13, 0x64, 0x8c, 0xfb, + 0x0c, 0x94, 0x35, 0x94, 0xb9, 0x12, 0x83, 0xec, 0x5e, 0x93, 0x23, 0xec, 0xd7, 0x8d, 0x2c, 0xa0, + 0xea, 0xc6, 0x1d, 0x64, 0x5b, 0x45, 0x02, 0xfc, 0x74, 0xce, 0x99, 0x90, 0xb4, 0x0a, 0xfc, 0x08, + 0x25, 0x87, 0xd9, 0x9d, 0x9c, 0xf6, 0xbf, 0xdc, 0x4c, 0xbc, 0xae, 0xc4, 0x5b, 0x7c, 0xf0, 0xb0, + 0xc3, 0xff, 0x74, 0xf4, 0x58, 0xfa, 0xde, 0x6e, 0xfa, 0xf9, 0xc7, 0x1f, 0xeb, 0x10, 0xdd, 0xae, + 0x43, 0xf4, 0x7b, 0x1d, 0xa2, 0xaf, 0x9b, 0xd0, 0xbb, 0xdd, 0x84, 0xde, 0xcf, 0x4d, 0xe8, 0x7d, + 0x3a, 0x2d, 0x85, 0x5d, 0x2c, 0x8b, 0x13, 0x06, 0x32, 0x65, 0xa6, 0xd1, 0x16, 0x8e, 0xc1, 0x94, + 0xc7, 0x6c, 0x41, 0x85, 0xda, 0x5e, 0x59, 0xfa, 0xf9, 0x75, 0xba, 0xba, 0x7b, 0xdb, 0x46, 0xf3, + 0xba, 0xf0, 0xbb, 0xd3, 0x7a, 0xf3, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xad, 0x72, 0x13, 0x5e, 0x8f, + 0x02, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -247,6 +257,11 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.MaxCallbackGas != 0 { + i = encodeVarintCronos(dAtA, i, uint64(m.MaxCallbackGas)) + i-- + dAtA[i] = 0x28 + } if m.EnableAutoDeployment { i-- if m.EnableAutoDeployment { @@ -410,6 +425,9 @@ func (m *Params) Size() (n int) { if m.EnableAutoDeployment { n += 2 } + if m.MaxCallbackGas != 0 { + n += 1 + sovCronos(uint64(m.MaxCallbackGas)) + } return n } @@ -600,6 +618,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { } } m.EnableAutoDeployment = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxCallbackGas", wireType) + } + m.MaxCallbackGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCronos + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxCallbackGas |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipCronos(dAtA[iNdEx:]) diff --git a/x/cronos/types/interfaces.go b/x/cronos/types/interfaces.go index a630a74911..37beaf900d 100644 --- a/x/cronos/types/interfaces.go +++ b/x/cronos/types/interfaces.go @@ -3,15 +3,19 @@ package types import ( context "context" "math/big" + time "time" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" tmbytes "github.com/cometbft/cometbft/libs/bytes" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + icaauthtypes "github.com/crypto-org-chain/cronos/v2/x/icaauth/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" evmtypes "github.com/evmos/ethermint/x/evm/types" @@ -74,3 +78,15 @@ type EvmKeeper interface { DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error ChainID() *big.Int } + +// Icaauthkeeper defines the interface for icaauth keeper +type Icaauthkeeper interface { + RegisterAccount(goCtx context.Context, msg *icaauthtypes.MsgRegisterAccount) (*icaauthtypes.MsgRegisterAccountResponse, error) + InterchainAccountAddress(goCtx context.Context, req *icaauthtypes.QueryInterchainAccountAddressRequest) (*icaauthtypes.QueryInterchainAccountAddressResponse, error) + SubmitTxWithArgs(goCtx context.Context, owner, connectionId string, timeoutDuration time.Duration, packetData icatypes.InterchainAccountPacketData) (*icaauthtypes.MsgSubmitTxResponse, error) +} + +// CronosKeeper defines the interface for cronos keeper +type CronosKeeper interface { + CallEVM(ctx sdk.Context, to *common.Address, data []byte, value *big.Int, gasLimit uint64) (*ethtypes.Message, *evmtypes.MsgEthereumTxResponse, error) +} diff --git a/x/cronos/types/params.go b/x/cronos/types/params.go index c99ff0dbc1..fe88d43bc6 100644 --- a/x/cronos/types/params.go +++ b/x/cronos/types/params.go @@ -18,11 +18,14 @@ var ( KeyCronosAdmin = []byte("CronosAdmin") // KeyEnableAutoDeployment is store's key for the EnableAutoDeployment KeyEnableAutoDeployment = []byte("EnableAutoDeployment") + // KeyMaxCallbackGas is store's key for the MaxCallbackGas + KeyMaxCallbackGas = []byte("MaxCallbackGas") ) const ( - IbcCroDenomDefaultValue = "ibc/6B5A664BF0AF4F71B2F0BAA33141E2F1321242FBD5D19762F541EC971ACB0865" - IbcTimeoutDefaultValue = uint64(86400000000000) // 1 day + IbcCroDenomDefaultValue = "ibc/6B5A664BF0AF4F71B2F0BAA33141E2F1321242FBD5D19762F541EC971ACB0865" + IbcTimeoutDefaultValue = uint64(86400000000000) // 1 day + MaxCallbackGasDefaultValue = uint64(300000) ) // ParamKeyTable returns the parameter key table. @@ -31,12 +34,13 @@ func ParamKeyTable() paramtypes.KeyTable { } // NewParams creates a new parameter configuration for the cronos module -func NewParams(ibcCroDenom string, ibcTimeout uint64, cronosAdmin string, enableAutoDeployment bool) Params { +func NewParams(ibcCroDenom string, ibcTimeout uint64, cronosAdmin string, enableAutoDeployment bool, maxCallbackGas uint64) Params { return Params{ IbcCroDenom: ibcCroDenom, IbcTimeout: ibcTimeout, CronosAdmin: cronosAdmin, EnableAutoDeployment: enableAutoDeployment, + MaxCallbackGas: maxCallbackGas, } } @@ -47,6 +51,7 @@ func DefaultParams() Params { IbcTimeout: IbcTimeoutDefaultValue, CronosAdmin: "", EnableAutoDeployment: false, + MaxCallbackGas: MaxCallbackGasDefaultValue, } } @@ -63,6 +68,9 @@ func (p Params) Validate() error { return err } } + if err := validateIsUint64(p.MaxCallbackGas); err != nil { + return err + } return nil } @@ -79,6 +87,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeyIbcTimeout, &p.IbcTimeout, validateIsUint64), paramtypes.NewParamSetPair(KeyCronosAdmin, &p.CronosAdmin, validateIsAddress), paramtypes.NewParamSetPair(KeyEnableAutoDeployment, &p.EnableAutoDeployment, validateIsBool), + paramtypes.NewParamSetPair(KeyMaxCallbackGas, &p.MaxCallbackGas, validateIsUint64), } }