diff --git a/nix/gen-binding-shell.nix b/nix/gen-binding-shell.nix index b469a08a56..2ac5711a47 100644 --- a/nix/gen-binding-shell.nix +++ b/nix/gen-binding-shell.nix @@ -5,6 +5,7 @@ in pkgs.mkShell { buildInputs = [ pkgs.go-ethereum + (renameExe pkgs.solc-static-versions.solc_0_6_8 "solc-0.6.8" "solc06") (renameExe pkgs.solc-static-versions.solc_0_8_21 "solc-0.8.21" "solc08") ]; } diff --git a/scripts/gen-bindings-contracts b/scripts/gen-bindings-contracts index 99e4f5c241..a7b40edab3 100755 --- a/scripts/gen-bindings-contracts +++ b/scripts/gen-bindings-contracts @@ -2,7 +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/ICA.sol -o build --overwrite +solc06 --abi --bin x/cronos/events/bindings/src/ICA.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 diff --git a/x/cronos/events/bindings/cosmos/precompile/ica/i_ica_module.abigen.go b/x/cronos/events/bindings/cosmos/precompile/ica/i_ica_module.abigen.go index 25a56ae5b1..4698407835 100644 --- a/x/cronos/events/bindings/cosmos/precompile/ica/i_ica_module.abigen.go +++ b/x/cronos/events/bindings/cosmos/precompile/ica/i_ica_module.abigen.go @@ -30,7 +30,7 @@ var ( // ICAModuleMetaData contains all meta data concerning the ICAModule contract. var ICAModuleMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"controllerChannelId\",\"type\":\"string\"}],\"name\":\"Ics27Packet\",\"type\":\"event\"}]", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"channelId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"portId\",\"type\":\"string\"}],\"name\":\"RegisterAccountResult\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"seq\",\"type\":\"string\"}],\"name\":\"SubmitMsgsResult\",\"type\":\"event\"}]", } // ICAModuleABI is the input ABI used to generate the binding from. @@ -179,9 +179,9 @@ func (_ICAModule *ICAModuleTransactorRaw) Transact(opts *bind.TransactOpts, meth return _ICAModule.Contract.contract.Transact(opts, method, params...) } -// ICAModuleIcs27PacketIterator is returned from FilterIcs27Packet and is used to iterate over the raw logs and unpacked data for Ics27Packet events raised by the ICAModule contract. -type ICAModuleIcs27PacketIterator struct { - Event *ICAModuleIcs27Packet // Event containing the contract specifics and raw log +// ICAModuleRegisterAccountResultIterator is returned from FilterRegisterAccountResult and is used to iterate over the raw logs and unpacked data for RegisterAccountResult events raised by the ICAModule contract. +type ICAModuleRegisterAccountResultIterator struct { + Event *ICAModuleRegisterAccountResult // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -195,7 +195,7 @@ type ICAModuleIcs27PacketIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *ICAModuleIcs27PacketIterator) Next() bool { +func (it *ICAModuleRegisterAccountResultIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -204,7 +204,7 @@ func (it *ICAModuleIcs27PacketIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(ICAModuleIcs27Packet) + it.Event = new(ICAModuleRegisterAccountResult) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -219,7 +219,7 @@ func (it *ICAModuleIcs27PacketIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(ICAModuleIcs27Packet) + it.Event = new(ICAModuleRegisterAccountResult) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -235,51 +235,176 @@ func (it *ICAModuleIcs27PacketIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *ICAModuleIcs27PacketIterator) Error() error { +func (it *ICAModuleRegisterAccountResultIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *ICAModuleIcs27PacketIterator) Close() error { +func (it *ICAModuleRegisterAccountResultIterator) Close() error { it.sub.Unsubscribe() return nil } -// ICAModuleIcs27Packet represents a Ics27Packet event raised by the ICAModule contract. -type ICAModuleIcs27Packet struct { - ControllerChannelId common.Hash - Raw types.Log // Blockchain specific contextual infos +// ICAModuleRegisterAccountResult represents a RegisterAccountResult event raised by the ICAModule contract. +type ICAModuleRegisterAccountResult struct { + ChannelId string + PortId string + Raw types.Log // Blockchain specific contextual infos } -// FilterIcs27Packet is a free log retrieval operation binding the contract event 0x43ea9083e980b3f6c315fe255d8179445962f23846010c7e83557d1aff161a28. +// FilterRegisterAccountResult is a free log retrieval operation binding the contract event 0x376fa4e62b5134e1fee2de3178039dea978d2aba39c3141ccb06dd32fcc30cb0. // -// Solidity: event Ics27Packet(string indexed controllerChannelId) -func (_ICAModule *ICAModuleFilterer) FilterIcs27Packet(opts *bind.FilterOpts, controllerChannelId []string) (*ICAModuleIcs27PacketIterator, error) { +// Solidity: event RegisterAccountResult(string channelId, string portId) +func (_ICAModule *ICAModuleFilterer) FilterRegisterAccountResult(opts *bind.FilterOpts) (*ICAModuleRegisterAccountResultIterator, error) { - var controllerChannelIdRule []interface{} - for _, controllerChannelIdItem := range controllerChannelId { - controllerChannelIdRule = append(controllerChannelIdRule, controllerChannelIdItem) + logs, sub, err := _ICAModule.contract.FilterLogs(opts, "RegisterAccountResult") + if err != nil { + return nil, err } + return &ICAModuleRegisterAccountResultIterator{contract: _ICAModule.contract, event: "RegisterAccountResult", logs: logs, sub: sub}, nil +} - logs, sub, err := _ICAModule.contract.FilterLogs(opts, "Ics27Packet", controllerChannelIdRule) +// WatchRegisterAccountResult is a free log subscription operation binding the contract event 0x376fa4e62b5134e1fee2de3178039dea978d2aba39c3141ccb06dd32fcc30cb0. +// +// Solidity: event RegisterAccountResult(string channelId, string portId) +func (_ICAModule *ICAModuleFilterer) WatchRegisterAccountResult(opts *bind.WatchOpts, sink chan<- *ICAModuleRegisterAccountResult) (event.Subscription, error) { + + logs, sub, err := _ICAModule.contract.WatchLogs(opts, "RegisterAccountResult") if err != nil { return nil, err } - return &ICAModuleIcs27PacketIterator{contract: _ICAModule.contract, event: "Ics27Packet", logs: logs, sub: sub}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ICAModuleRegisterAccountResult) + if err := _ICAModule.contract.UnpackLog(event, "RegisterAccountResult", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRegisterAccountResult is a log parse operation binding the contract event 0x376fa4e62b5134e1fee2de3178039dea978d2aba39c3141ccb06dd32fcc30cb0. +// +// Solidity: event RegisterAccountResult(string channelId, string portId) +func (_ICAModule *ICAModuleFilterer) ParseRegisterAccountResult(log types.Log) (*ICAModuleRegisterAccountResult, error) { + event := new(ICAModuleRegisterAccountResult) + if err := _ICAModule.contract.UnpackLog(event, "RegisterAccountResult", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ICAModuleSubmitMsgsResultIterator is returned from FilterSubmitMsgsResult and is used to iterate over the raw logs and unpacked data for SubmitMsgsResult events raised by the ICAModule contract. +type ICAModuleSubmitMsgsResultIterator struct { + Event *ICAModuleSubmitMsgsResult // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ICAModuleSubmitMsgsResultIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ICAModuleSubmitMsgsResult) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ICAModuleSubmitMsgsResult) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ICAModuleSubmitMsgsResultIterator) Error() error { + return it.fail } -// WatchIcs27Packet is a free log subscription operation binding the contract event 0x43ea9083e980b3f6c315fe255d8179445962f23846010c7e83557d1aff161a28. +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ICAModuleSubmitMsgsResultIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ICAModuleSubmitMsgsResult represents a SubmitMsgsResult event raised by the ICAModule contract. +type ICAModuleSubmitMsgsResult struct { + Seq string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSubmitMsgsResult is a free log retrieval operation binding the contract event 0xa3e95b27e18d059901cec72b253b0fb29054cf697ac76ea3cd4bb1eee64845dd. // -// Solidity: event Ics27Packet(string indexed controllerChannelId) -func (_ICAModule *ICAModuleFilterer) WatchIcs27Packet(opts *bind.WatchOpts, sink chan<- *ICAModuleIcs27Packet, controllerChannelId []string) (event.Subscription, error) { +// Solidity: event SubmitMsgsResult(string seq) +func (_ICAModule *ICAModuleFilterer) FilterSubmitMsgsResult(opts *bind.FilterOpts) (*ICAModuleSubmitMsgsResultIterator, error) { - var controllerChannelIdRule []interface{} - for _, controllerChannelIdItem := range controllerChannelId { - controllerChannelIdRule = append(controllerChannelIdRule, controllerChannelIdItem) + logs, sub, err := _ICAModule.contract.FilterLogs(opts, "SubmitMsgsResult") + if err != nil { + return nil, err } + return &ICAModuleSubmitMsgsResultIterator{contract: _ICAModule.contract, event: "SubmitMsgsResult", logs: logs, sub: sub}, nil +} + +// WatchSubmitMsgsResult is a free log subscription operation binding the contract event 0xa3e95b27e18d059901cec72b253b0fb29054cf697ac76ea3cd4bb1eee64845dd. +// +// Solidity: event SubmitMsgsResult(string seq) +func (_ICAModule *ICAModuleFilterer) WatchSubmitMsgsResult(opts *bind.WatchOpts, sink chan<- *ICAModuleSubmitMsgsResult) (event.Subscription, error) { - logs, sub, err := _ICAModule.contract.WatchLogs(opts, "Ics27Packet", controllerChannelIdRule) + logs, sub, err := _ICAModule.contract.WatchLogs(opts, "SubmitMsgsResult") if err != nil { return nil, err } @@ -289,8 +414,8 @@ func (_ICAModule *ICAModuleFilterer) WatchIcs27Packet(opts *bind.WatchOpts, sink select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(ICAModuleIcs27Packet) - if err := _ICAModule.contract.UnpackLog(event, "Ics27Packet", log); err != nil { + event := new(ICAModuleSubmitMsgsResult) + if err := _ICAModule.contract.UnpackLog(event, "SubmitMsgsResult", log); err != nil { return err } event.Raw = log @@ -311,12 +436,12 @@ func (_ICAModule *ICAModuleFilterer) WatchIcs27Packet(opts *bind.WatchOpts, sink }), nil } -// ParseIcs27Packet is a log parse operation binding the contract event 0x43ea9083e980b3f6c315fe255d8179445962f23846010c7e83557d1aff161a28. +// ParseSubmitMsgsResult is a log parse operation binding the contract event 0xa3e95b27e18d059901cec72b253b0fb29054cf697ac76ea3cd4bb1eee64845dd. // -// Solidity: event Ics27Packet(string indexed controllerChannelId) -func (_ICAModule *ICAModuleFilterer) ParseIcs27Packet(log types.Log) (*ICAModuleIcs27Packet, error) { - event := new(ICAModuleIcs27Packet) - if err := _ICAModule.contract.UnpackLog(event, "Ics27Packet", log); err != nil { +// Solidity: event SubmitMsgsResult(string seq) +func (_ICAModule *ICAModuleFilterer) ParseSubmitMsgsResult(log types.Log) (*ICAModuleSubmitMsgsResult, error) { + event := new(ICAModuleSubmitMsgsResult) + if err := _ICAModule.contract.UnpackLog(event, "SubmitMsgsResult", log); err != nil { return nil, err } event.Raw = log diff --git a/x/cronos/events/bindings/src/ICA.sol b/x/cronos/events/bindings/src/ICA.sol index c1b799a380..9968afd181 100644 --- a/x/cronos/events/bindings/src/ICA.sol +++ b/x/cronos/events/bindings/src/ICA.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; +pragma solidity ^0.6.6; interface IICAModule { - // ICS27 Interchain Accounts events - event Ics27Packet(string indexed controllerChannelId); + event RegisterAccountResult(string channelId, string portId); + event SubmitMsgsResult(string seq); } diff --git a/x/cronos/events/events.go b/x/cronos/events/events.go index 121cdc3c70..f881236987 100644 --- a/x/cronos/events/events.go +++ b/x/cronos/events/events.go @@ -4,9 +4,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ibctypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ica "github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/ica" relayer "github.com/crypto-org-chain/cronos/v2/x/cronos/events/bindings/cosmos/precompile/relayer" + cronoseventstypes "github.com/crypto-org-chain/cronos/v2/x/cronos/events/types" "github.com/ethereum/go-ethereum/accounts/abi" ethtypes "github.com/ethereum/go-ethereum/core/types" ) @@ -24,6 +26,11 @@ var ( banktypes.AttributeKeyMinter: ConvertAccAddressFromBech32, banktypes.AttributeKeyBurner: ConvertAccAddressFromBech32, } + IcaValueDecoders = ValueDecoders{ + channeltypes.AttributeKeyChannelID: ReturnStringAsIs, + channeltypes.AttributeKeyPortID: ReturnStringAsIs, + cronoseventstypes.AttributeKeySeq: ReturnStringAsIs, + } ) func init() { @@ -59,5 +66,5 @@ func IcaConvertEvent(event sdk.Event) (*ethtypes.Log, error) { if !ok { return nil, nil } - return desc.ConvertEvent(event.Attributes, ValueDecoders{}) + return desc.ConvertEvent(event.Attributes, IcaValueDecoders) } diff --git a/x/cronos/events/types/types.go b/x/cronos/events/types/types.go new file mode 100644 index 0000000000..b764b9ec01 --- /dev/null +++ b/x/cronos/events/types/types.go @@ -0,0 +1,7 @@ +package types + +const ( + EventTypeRegisterAccountResult = "register_account_result" + EventTypeSubmitMsgsResult = "submit_msgs_result" + AttributeKeySeq = "seq" +) diff --git a/x/cronos/keeper/precompiles/ica.go b/x/cronos/keeper/precompiles/ica.go index c5e730be58..060d13b69e 100644 --- a/x/cronos/keeper/precompiles/ica.go +++ b/x/cronos/keeper/precompiles/ica.go @@ -3,6 +3,7 @@ package precompiles import ( "bytes" "errors" + "fmt" "math/big" "github.com/cosmos/cosmos-sdk/codec" @@ -11,7 +12,9 @@ import ( icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" ibcchannelkeeper "github.com/cosmos/ibc-go/v7/modules/core/04-channel/keeper" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events" + cronoseventstypes "github.com/crypto-org-chain/cronos/v2/x/cronos/events/types" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -137,12 +140,23 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ if !isSameAddress(account, contract.CallerAddress) && !isSameAddress(account, txSender) { return nil, errors.New("unauthorized account registration") } + owner := sdk.AccAddress(account.Bytes()).String() err = stateDB.ExecuteNativeAction(precompileAddr, converter, func(ctx sdk.Context) error { - res, err = ic.icaControllerKeeper.RegisterInterchainAccount(ctx, &icacontrollertypes.MsgRegisterInterchainAccount{ - Owner: sdk.AccAddress(account.Bytes()).String(), + response, err := ic.icaControllerKeeper.RegisterInterchainAccount(ctx, &icacontrollertypes.MsgRegisterInterchainAccount{ + Owner: owner, ConnectionId: connectionID, Version: version, }) + res = response + if err == nil && response != nil { + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + cronoseventstypes.EventTypeRegisterAccountResult, + sdk.NewAttribute(channeltypes.AttributeKeyChannelID, response.ChannelId), + sdk.NewAttribute(channeltypes.AttributeKeyPortID, response.PortId), + ), + }) + } return err }) case string(QueryAccountMethod.ID): @@ -175,19 +189,28 @@ func (ic *IcaContract) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([ if !isSameAddress(account, contract.CallerAddress) && !isSameAddress(account, txSender) { return nil, errors.New("unauthorized send tx") } - var icaMsgData icatypes.InterchainAccountPacketData err = ic.cdc.UnmarshalJSON([]byte(data), &icaMsgData) if err != nil { panic(err) } + owner := sdk.AccAddress(account.Bytes()).String() err = stateDB.ExecuteNativeAction(precompileAddr, converter, func(ctx sdk.Context) error { - res, err = ic.icaControllerKeeper.SendTx(ctx, &icacontrollertypes.MsgSendTx{ //nolint:staticcheck - Owner: sdk.AccAddress(account.Bytes()).String(), + response, err := ic.icaControllerKeeper.SendTx(ctx, &icacontrollertypes.MsgSendTx{ //nolint:staticcheck + Owner: owner, ConnectionId: connectionID, PacketData: icaMsgData, RelativeTimeout: timeout.Uint64(), }) + res = response + if err == nil && response != nil { + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + cronoseventstypes.EventTypeSubmitMsgsResult, + sdk.NewAttribute(cronoseventstypes.AttributeKeySeq, fmt.Sprintf("%d", response.Sequence)), + ), + }) + } return err }) default: