From 76bdaaabbf172057f18b5e9f9de641c6b033ebd0 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Tue, 9 Jul 2024 18:21:53 +0400 Subject: [PATCH] feat(evm): msg to send bank coin to erc20 (#1956) * refactor(e2e-evm): unused vars and better type hint Squashed commit of the following: commit 51071dad60c12e02093d92d1311d33b70b81304f Author: Unique-Divine Date: Mon Jun 10 12:32:00 2024 -0500 refactor(e2e-evm): unused vars and better type hint commit 6729b97643395ed11f4cec15f7885dc0c6e88e56 Author: Unique-Divine Date: Fri Jun 7 22:46:14 2024 -0500 test(e2e-evm): more type safety commit 25c1557dda67fa19127f83d1dcdc2c38116fbde7 Author: Unique-Divine Date: Fri Jun 7 22:01:21 2024 -0500 Squashed commit of the following: commit 021d161d176112cf24e28780ad64f61155f70ea2 Author: Unique-Divine Date: Fri Jun 7 22:00:10 2024 -0500 test(e2e): (1) Generated smart contract types for ethers. (2) TypeScript support. (3) Formatter commit af7e7b30908a0e189c9435ed29ecf79b98f4e31c Author: Unique-Divine Date: Fri Jun 7 16:11:45 2024 -0500 chore: another issue ticket commit 36745fde9d0228252e961f64d728ad8e51ff1ca6 Author: Unique-Divine Date: Fri Jun 7 16:07:20 2024 -0500 chore: add issue number for TODO comment commit 8a76c0eded70859254fcefea6982550c2e2a3bc5 Author: Unique-Divine Date: Fri Jun 7 15:54:07 2024 -0500 refactor(evm): Remove dead code and document non-EVM ante handler commit e4e11dfd6ad075620683cb703125f29b9d1b574a Author: Unique-Divine Date: Fri Jun 7 15:52:38 2024 -0500 refactor: remove dead code commit cad00c03648a01ac678b248751624f35f909cc83 Merge: dc5f4dd8 359e310f Author: Unique-Divine Date: Fri Jun 7 15:41:53 2024 -0500 Merge branch 'main' into ud/ante-test commit dc5f4dd84d9049dc3069fc6f0e65936b04f7dbce Author: Unique-Divine Date: Fri Jun 7 15:28:53 2024 -0500 refactor: ante handler and evm cleanup commit f73cdc3e75318e0a66f6f77cb117984bc09c90f1 Merge: d3a6ea95 290c3724 Author: Unique-Divine Date: Wed Jun 5 20:59:39 2024 -0500 Merge branch 'test/evm-grpc-query' of https://github.com/NibiruChain/nibiru into test/evm-grpc-query commit d3a6ea956f71d3042e0ef14ee149d502c3ccbbdf Merge: 376596d6 70ee1bfe Author: Unique-Divine Date: Wed Jun 5 20:59:30 2024 -0500 Merge branch 'main' into test/evm-grpc-query commit 376596d61b44856cf0866486f7984d561ffe820c Author: Unique-Divine Date: Wed Jun 5 20:58:40 2024 -0500 Squashed commit of the following: commit b5687130ff5f3d020a3b14d219fec3a816579c30 Author: Unique-Divine Date: Wed Jun 5 20:57:44 2024 -0500 chore: run tidy commit 1f1f9385952c4a170f744726bed8a3ee7c376028 Merge: 3e3cc837 bbcc6f8c Author: Unique-Divine Date: Wed Jun 5 19:16:30 2024 -0500 Merge branch 'main' into ud/fix-race-condition commit 3e3cc837b204971c58c775fe25d28fd01bce4021 Author: Unique-Divine Date: Wed Jun 5 19:15:40 2024 -0500 chore: changelog commit 3876ccb431aac5c9991a3540d764061cb52a0857 Author: Unique-Divine Date: Wed Jun 5 19:04:00 2024 -0500 refactor: more consistent test names commit aaa0a19f103a12c60f226a5057779a74d680e61c Author: Unique-Divine Date: Wed Jun 5 18:53:09 2024 -0500 test(oracle): Fix missing tear down step for oracle integration test commit 8c3c35eafc41d29becba1379d1f9ca5e984d8d9a Author: Unique-Divine Date: Wed Jun 5 17:55:56 2024 -0500 chore: add test comands to justfile commit 4916282353300b2dbf639e599cfbc3685cda01f6 Merge: 64ed0a29 e7e708d7 Author: Unique-Divine Date: Fri May 31 09:35:33 2024 -0500 Merge branch 'main' into ud/fix-race-condition commit 64ed0a29c918c4c1402eceddc13998ed4a156712 Author: Unique-Divine Date: Fri May 31 01:44:55 2024 -0500 fix(gosdk): tests parallel race condition commit 290c3724c2fc3804e5b2c8b509a2707c2e9ea101 Merge: 0d1c8942 70ee1bfe Author: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Wed Jun 5 20:05:19 2024 -0500 Merge branch 'main' into test/evm-grpc-query commit 0d1c8942c6453d2f2fa22dff0e5af8ea11e1fa53 Merge: 91708355 ad173e9b Author: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Wed Jun 5 19:34:38 2024 -0500 Merge branch 'main' into test/evm-grpc-query commit 917083558b04e67f563dd0f12c4918e2b43ecf7c Author: Oleg Nikonychev Date: Wed Jun 5 13:55:14 2024 +0400 fix: removed hardcoded gas value in grpc_query test commit 43378584dfec2f207afdc619f2d27df35816c304 Author: Oleg Nikonychev Date: Wed Jun 5 13:14:34 2024 +0400 chore: refactored eth util methods commit 7df84e26d481013d30f67710e69dcaca02affcfa Merge: 8918498b bbcc6f8c Author: Oleg Nikonychev Date: Wed Jun 5 12:23:51 2024 +0400 chore: resolve conflicts commit 8918498b83925f1b70678ecf70250906b9a3038d Merge: 3fd45ce3 e7e708d7 Author: Oleg Nikonychev Date: Mon Jun 3 21:56:39 2024 +0400 Merge branch 'main' into test/evm-grpc-query commit 3fd45ce323c97f999d6754ef454e51077854a918 Author: Oleg Nikonychev Date: Mon Jun 3 21:56:23 2024 +0400 chore: changelog update commit 3348876f46c66c9502d16793bb61b729559ecc91 Author: Oleg Nikonychev Date: Mon Jun 3 21:53:54 2024 +0400 test(evm): grpc_query full coverage * wip!: save progress * chore: changelog * chore: linter * feat(eth): finish todos for hex.go * feat(eth): finalize protobuf impl for eth.HexAddr * chore: small typos in comments * feat(evm): contract embeds, create fun token from ERC20 * chore: merge conflict * chore: clean TODOs * fix: TestModuleAccountEVM * feat(evm): impl CreateFunTokenFromCoin * fix: made from_erc20 nullable in MsgCreateFunToken * test: fix cleanup by increasing timeout for race condition prevention * chore: rn * feat(evm): msg to send bank coin to erc20 * feat(evm): msg to send bank coin to erc20 * fix: lint * fix: evm module account creation in genesis * test(evm): coverage for send coin to erc20 * fix: comment typo --------- Co-authored-by: Unique-Divine Co-authored-by: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> --- CHANGELOG.md | 1 + proto/eth/evm/v1/events.proto | 21 + proto/eth/evm/v1/tx.proto | 27 +- x/evm/cli/cli.go | 80 +++- x/evm/deps.go | 1 + x/evm/events.pb.go | 662 ++++++++++++++++++++++++++- x/evm/evmmodule/genesis.go | 4 +- x/evm/evmtest/erc20.go | 53 +++ x/evm/evmtest/eth_test.go | 23 +- x/evm/evmtest/smart_contract_test.go | 4 +- x/evm/keeper/erc20.go | 7 +- x/evm/keeper/erc20_test.go | 223 ++++++++- x/evm/keeper/msg_server.go | 76 ++- x/evm/msg.go | 30 +- x/evm/precompile/funtoken.go | 4 +- x/evm/precompile/funtoken_test.go | 148 +++--- x/evm/tx.pb.go | 611 ++++++++++++++++++++---- 17 files changed, 1751 insertions(+), 224 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f608dd7f..271dbe631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#1947](https://github.com/NibiruChain/nibiru/pull/1947) - fix(evm): fix FunToken state marshalling - [#1949](https://github.com/NibiruChain/nibiru/pull/1949) - feat(evm): add fungible token mapping queries - [#1950](https://github.com/NibiruChain/nibiru/pull/1950) - feat(evm): Tx to create FunToken mapping from ERC20, contract embeds, and ERC20 queries. +- [#1956](https://github.com/NibiruChain/nibiru/pull/1956) - feat(evm): msg to send bank coin to erc20 - [#1958](https://github.com/NibiruChain/nibiru/pull/1958) - chore(evm): wiped deprecated evm apis: miner, personal - [#1959](https://github.com/NibiruChain/nibiru/pull/1959) - feat(evm): Add precompile to the EVM that enables trasnfers of ERC20 tokens to "nibi" accounts as regular Ethereum transactions diff --git a/proto/eth/evm/v1/events.proto b/proto/eth/evm/v1/events.proto index 853c3eaf8..e951ca8f8 100644 --- a/proto/eth/evm/v1/events.proto +++ b/proto/eth/evm/v1/events.proto @@ -2,6 +2,9 @@ syntax = "proto3"; package eth.evm.v1; +import "cosmos/base/v1beta1/coin.proto"; +import "gogoproto/gogo.proto"; + option go_package = "github.com/NibiruChain/nibiru/x/evm"; // EventEthereumTx defines the event for an Ethereum transaction @@ -43,3 +46,21 @@ message EventBlockBloom { // bloom is the bloom filter of the block string bloom = 1; } + +// EventFunTokenFromBankCoin defines a fun token creation from the bank coin event. +message EventFunTokenFromBankCoin { + string bank_denom = 1; + string erc20_contract_address = 2; + string creator = 3; +} + +// SendFunTokenToEvm defines sending fun token to erc20 event. +message EventSendFunTokenToEvm { + string sender = 1; + string erc20_contract_address = 2; + string to_eth_addr = 3; + cosmos.base.v1beta1.Coin bank_coin = 4 [ + (gogoproto.moretags) = "yaml:\"bank_coin\"", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/eth/evm/v1/tx.proto b/proto/eth/evm/v1/tx.proto index 2e393a929..d3b3160d7 100644 --- a/proto/eth/evm/v1/tx.proto +++ b/proto/eth/evm/v1/tx.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package eth.evm.v1; import "cosmos/msg/v1/msg.proto"; +import "cosmos/base/v1beta1/coin.proto"; import "cosmos_proto/cosmos.proto"; import "eth/evm/v1/evm.proto"; import "gogoproto/gogo.proto"; @@ -25,6 +26,11 @@ service Msg { // address can be given to create the mapping to a bank coin, or the // denomination for a bank coin can be given to create the mapping to an ERC20. rpc CreateFunToken(MsgCreateFunToken) returns (MsgCreateFunTokenResponse); + + // SendFunTokenToEvm: Sends a coin with a valid "FunToken" mapping to the + // given recipient address ("to_eth_addr") in the corresponding ERC20 + // representation. + rpc SendFunTokenToEvm(MsgSendFunTokenToEvm) returns (MsgSendFunTokenToEvmResponse); } // MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. @@ -189,7 +195,7 @@ message MsgCreateFunToken { // Hexadecimal address of the ERC20 token to which the `FunToken` maps string from_erc20 = 1 [ (gogoproto.customtype) = "github.com/NibiruChain/nibiru/eth.HexAddr", - (gogoproto.nullable) = false + (gogoproto.nullable) = true ]; // Coin denomination in the Bank Module. @@ -203,3 +209,22 @@ message MsgCreateFunTokenResponse { // Fungible token mapping corresponding to ERC20 tokens. eth.evm.v1.FunToken funtoken_mapping = 1 [(gogoproto.nullable) = false]; } + +// MsgSendFunTokenToEvm: Arguments to send a bank coin to ERC-20 representation +message MsgSendFunTokenToEvm { + // Hexadecimal address of the ERC20 token to which the `FunToken` maps + string to_eth_addr = 1 [ + (gogoproto.customtype) = "github.com/NibiruChain/nibiru/eth.HexAddr", + (gogoproto.nullable) = false + ]; + + // Sender: Address for the signer of the transaction. + string sender = 2; + + // Bank coin to get converted to ERC20 + cosmos.base.v1beta1.Coin bank_coin = 3 [ + (gogoproto.moretags) = "yaml:\"bank_coin\"", + (gogoproto.nullable) = false + ]; +} +message MsgSendFunTokenToEvmResponse {} diff --git a/x/evm/cli/cli.go b/x/evm/cli/cli.go index 2fe7b80b8..54c8f36d9 100644 --- a/x/evm/cli/cli.go +++ b/x/evm/cli/cli.go @@ -3,11 +3,15 @@ package cli import ( "fmt" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/eth" "github.com/NibiruChain/nibiru/x/evm" "github.com/NibiruChain/nibiru/x/sudo/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/spf13/cobra" ) @@ -21,7 +25,10 @@ func GetTxCmd() *cobra.Command { RunE: client.ValidateCmd, } - cmds := []*cobra.Command{} + cmds := []*cobra.Command{ + CmdCreateFunTokenFromBankCoin(), + SendFunTokenToEvm(), + } for _, cmd := range cmds { txCmd.AddCommand(cmd) } @@ -45,6 +52,71 @@ func GetQueryCmd() *cobra.Command { for _, cmd := range cmds { moduleQueryCmd.AddCommand(cmd) } - return moduleQueryCmd } + +// CmdCreateFunTokenFromBankCoin broadcast MsgCreateFunToken +func CmdCreateFunTokenFromBankCoin() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-fun-token-from-bank-coin [denom] [flags]", + Short: `Create an erc-20 fungible token from bank coin [denom]"`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + txFactory, err := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + if err != nil { + return err + } + txFactory = txFactory. + WithTxConfig(clientCtx.TxConfig). + WithAccountRetriever(clientCtx.AccountRetriever) + + msg := &evm.MsgCreateFunToken{ + Sender: clientCtx.GetFromAddress().String(), + FromBankDenom: args[0], + } + return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txFactory, msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// SendFunTokenToEvm broadcast MsgSendFunTokenToEvm +func SendFunTokenToEvm() *cobra.Command { + cmd := &cobra.Command{ + Use: "send-fun-token-to-erc-20 [to_eth_addr] [coin] [flags]", + Short: `Send bank [coin] to its erc-20 representation for the user [to_eth_addr]"`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + txFactory, err := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + if err != nil { + return err + } + txFactory = txFactory. + WithTxConfig(clientCtx.TxConfig). + WithAccountRetriever(clientCtx.AccountRetriever) + + coin, err := sdk.ParseCoinNormalized(args[1]) + if err != nil { + return err + } + msg := &evm.MsgSendFunTokenToEvm{ + Sender: clientCtx.GetFromAddress().String(), + BankCoin: coin, + ToEthAddr: eth.MustNewHexAddrFromStr(args[0]), + } + return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txFactory, msg) + }, + } + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/evm/deps.go b/x/evm/deps.go index 862f2cf6b..c02a9ec32 100644 --- a/x/evm/deps.go +++ b/x/evm/deps.go @@ -31,6 +31,7 @@ type AccountKeeper interface { SetAccount(ctx sdk.Context, account authtypes.AccountI) RemoveAccount(ctx sdk.Context, account authtypes.AccountI) GetParams(ctx sdk.Context) (params authtypes.Params) + SetModuleAccount(ctx sdk.Context, macc authtypes.ModuleAccountI) } // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/x/evm/events.pb.go b/x/evm/events.pb.go index d7e35e49a..195e6248f 100644 --- a/x/evm/events.pb.go +++ b/x/evm/events.pb.go @@ -5,6 +5,8 @@ package evm import ( fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -278,40 +280,185 @@ func (m *EventBlockBloom) GetBloom() string { return "" } +// EventFunTokenFromBankCoin defines a fun token creation from the bank coin event. +type EventFunTokenFromBankCoin struct { + BankDenom string `protobuf:"bytes,1,opt,name=bank_denom,json=bankDenom,proto3" json:"bank_denom,omitempty"` + Erc20ContractAddress string `protobuf:"bytes,2,opt,name=erc20_contract_address,json=erc20ContractAddress,proto3" json:"erc20_contract_address,omitempty"` + Creator string `protobuf:"bytes,3,opt,name=creator,proto3" json:"creator,omitempty"` +} + +func (m *EventFunTokenFromBankCoin) Reset() { *m = EventFunTokenFromBankCoin{} } +func (m *EventFunTokenFromBankCoin) String() string { return proto.CompactTextString(m) } +func (*EventFunTokenFromBankCoin) ProtoMessage() {} +func (*EventFunTokenFromBankCoin) Descriptor() ([]byte, []int) { + return fileDescriptor_f8bc26b53c788f17, []int{4} +} +func (m *EventFunTokenFromBankCoin) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventFunTokenFromBankCoin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventFunTokenFromBankCoin.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventFunTokenFromBankCoin) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventFunTokenFromBankCoin.Merge(m, src) +} +func (m *EventFunTokenFromBankCoin) XXX_Size() int { + return m.Size() +} +func (m *EventFunTokenFromBankCoin) XXX_DiscardUnknown() { + xxx_messageInfo_EventFunTokenFromBankCoin.DiscardUnknown(m) +} + +var xxx_messageInfo_EventFunTokenFromBankCoin proto.InternalMessageInfo + +func (m *EventFunTokenFromBankCoin) GetBankDenom() string { + if m != nil { + return m.BankDenom + } + return "" +} + +func (m *EventFunTokenFromBankCoin) GetErc20ContractAddress() string { + if m != nil { + return m.Erc20ContractAddress + } + return "" +} + +func (m *EventFunTokenFromBankCoin) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +// SendFunTokenToEvm defines sending fun token to erc20 event. +type EventSendFunTokenToEvm struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Erc20ContractAddress string `protobuf:"bytes,2,opt,name=erc20_contract_address,json=erc20ContractAddress,proto3" json:"erc20_contract_address,omitempty"` + ToEthAddr string `protobuf:"bytes,3,opt,name=to_eth_addr,json=toEthAddr,proto3" json:"to_eth_addr,omitempty"` + BankCoin types.Coin `protobuf:"bytes,4,opt,name=bank_coin,json=bankCoin,proto3" json:"bank_coin" yaml:"bank_coin"` +} + +func (m *EventSendFunTokenToEvm) Reset() { *m = EventSendFunTokenToEvm{} } +func (m *EventSendFunTokenToEvm) String() string { return proto.CompactTextString(m) } +func (*EventSendFunTokenToEvm) ProtoMessage() {} +func (*EventSendFunTokenToEvm) Descriptor() ([]byte, []int) { + return fileDescriptor_f8bc26b53c788f17, []int{5} +} +func (m *EventSendFunTokenToEvm) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventSendFunTokenToEvm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventSendFunTokenToEvm.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventSendFunTokenToEvm) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventSendFunTokenToEvm.Merge(m, src) +} +func (m *EventSendFunTokenToEvm) XXX_Size() int { + return m.Size() +} +func (m *EventSendFunTokenToEvm) XXX_DiscardUnknown() { + xxx_messageInfo_EventSendFunTokenToEvm.DiscardUnknown(m) +} + +var xxx_messageInfo_EventSendFunTokenToEvm proto.InternalMessageInfo + +func (m *EventSendFunTokenToEvm) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *EventSendFunTokenToEvm) GetErc20ContractAddress() string { + if m != nil { + return m.Erc20ContractAddress + } + return "" +} + +func (m *EventSendFunTokenToEvm) GetToEthAddr() string { + if m != nil { + return m.ToEthAddr + } + return "" +} + +func (m *EventSendFunTokenToEvm) GetBankCoin() types.Coin { + if m != nil { + return m.BankCoin + } + return types.Coin{} +} + func init() { proto.RegisterType((*EventEthereumTx)(nil), "eth.evm.v1.EventEthereumTx") proto.RegisterType((*EventTxLog)(nil), "eth.evm.v1.EventTxLog") proto.RegisterType((*EventMessage)(nil), "eth.evm.v1.EventMessage") proto.RegisterType((*EventBlockBloom)(nil), "eth.evm.v1.EventBlockBloom") + proto.RegisterType((*EventFunTokenFromBankCoin)(nil), "eth.evm.v1.EventFunTokenFromBankCoin") + proto.RegisterType((*EventSendFunTokenToEvm)(nil), "eth.evm.v1.EventSendFunTokenToEvm") } func init() { proto.RegisterFile("eth/evm/v1/events.proto", fileDescriptor_f8bc26b53c788f17) } var fileDescriptor_f8bc26b53c788f17 = []byte{ - // 363 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0xc1, 0x6a, 0xdb, 0x40, - 0x10, 0x86, 0xad, 0xda, 0x96, 0xeb, 0x6d, 0x4b, 0x61, 0x29, 0xb5, 0x0a, 0x45, 0x18, 0x95, 0xd2, - 0x9e, 0x24, 0x4c, 0xcf, 0xbd, 0x38, 0x38, 0xe4, 0x90, 0xe4, 0x10, 0x14, 0x02, 0xb9, 0x88, 0x95, - 0x35, 0xd1, 0x2e, 0x91, 0xb4, 0x42, 0x3b, 0x12, 0xeb, 0xb7, 0xc8, 0x63, 0x05, 0x72, 0xf1, 0x31, - 0xc7, 0x60, 0xbf, 0x48, 0xd8, 0x95, 0x42, 0x6e, 0xf3, 0xff, 0xb3, 0xf3, 0x2f, 0xdf, 0x0c, 0x59, - 0x00, 0xf2, 0x08, 0xba, 0x32, 0xea, 0x56, 0x11, 0x74, 0x50, 0xa1, 0x0a, 0xeb, 0x46, 0xa2, 0xa4, - 0x04, 0x90, 0x87, 0xd0, 0x95, 0x61, 0xb7, 0x0a, 0x9e, 0x1c, 0xf2, 0x75, 0x63, 0x9a, 0x1b, 0xe4, - 0xd0, 0x40, 0x5b, 0xc6, 0x9a, 0x7e, 0x27, 0x2e, 0x2b, 0x65, 0x5b, 0xa1, 0xe7, 0x2c, 0x9d, 0xbf, - 0xf3, 0xab, 0x41, 0xd1, 0x1f, 0xe4, 0x23, 0x20, 0x4f, 0x38, 0x53, 0xdc, 0xfb, 0x60, 0x3b, 0x33, - 0x40, 0x7e, 0xc6, 0x14, 0xa7, 0xdf, 0xc8, 0x54, 0x54, 0x19, 0x68, 0x6f, 0x6c, 0xfd, 0x5e, 0x98, - 0x81, 0x9c, 0xa9, 0xa4, 0x55, 0x90, 0x79, 0x93, 0x7e, 0x20, 0x67, 0xea, 0x5a, 0x41, 0x46, 0x29, - 0x99, 0xd8, 0x9c, 0xa9, 0xb5, 0x6d, 0x4d, 0x7f, 0x92, 0x79, 0x03, 0x5b, 0x51, 0x0b, 0xa8, 0xd0, - 0x73, 0x6d, 0xe3, 0xdd, 0xa0, 0x01, 0xf9, 0x62, 0x7e, 0x47, 0x9d, 0xdc, 0x31, 0x51, 0x40, 0xe6, - 0xcd, 0xec, 0x8b, 0x4f, 0x80, 0x3c, 0xd6, 0xa7, 0xd6, 0x0a, 0x7e, 0x13, 0x62, 0x61, 0x62, 0x7d, - 0x2e, 0x73, 0xba, 0x20, 0x33, 0xd4, 0x49, 0x21, 0x73, 0xe5, 0x39, 0xcb, 0xb1, 0x01, 0x41, 0xe3, - 0xab, 0xe0, 0x86, 0x7c, 0xb6, 0xcf, 0x2e, 0x40, 0x29, 0x96, 0x83, 0x01, 0x2e, 0x65, 0xd6, 0x16, - 0xf0, 0x06, 0xdc, 0x2b, 0xe3, 0x2b, 0xa8, 0x32, 0x68, 0x06, 0xdc, 0x41, 0x0d, 0xc1, 0xb8, 0xab, - 0x61, 0xe0, 0x75, 0x51, 0xc7, 0xbb, 0x1a, 0x82, 0x3f, 0xc3, 0x32, 0xd7, 0x85, 0xdc, 0xde, 0xaf, - 0x0b, 0x29, 0x4b, 0xb3, 0x99, 0xd4, 0x14, 0x43, 0x74, 0x2f, 0xd6, 0xff, 0x1f, 0x0f, 0xbe, 0xb3, - 0x3f, 0xf8, 0xce, 0xcb, 0xc1, 0x77, 0x1e, 0x8e, 0xfe, 0x68, 0x7f, 0xf4, 0x47, 0xcf, 0x47, 0x7f, - 0x74, 0xfb, 0x2b, 0x17, 0xc8, 0xdb, 0x34, 0xdc, 0xca, 0x32, 0xba, 0x14, 0xa9, 0x68, 0xda, 0x13, - 0xce, 0x44, 0x15, 0x55, 0xb6, 0x8e, 0xb4, 0xb9, 0x68, 0xea, 0xda, 0x43, 0xfe, 0x7b, 0x0d, 0x00, - 0x00, 0xff, 0xff, 0xba, 0x7a, 0xfa, 0x28, 0xe3, 0x01, 0x00, 0x00, + // 564 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0x8e, 0x69, 0x9b, 0x34, 0x1b, 0x10, 0x68, 0x15, 0xa5, 0x4e, 0x05, 0x6e, 0x65, 0x84, 0xe0, + 0x64, 0x93, 0xc2, 0x09, 0x89, 0x03, 0x09, 0x89, 0x38, 0x00, 0x42, 0xc5, 0x08, 0x89, 0x8b, 0xb5, + 0xb6, 0x07, 0xaf, 0x15, 0x7b, 0x37, 0xf2, 0xae, 0x2d, 0xe7, 0x15, 0x38, 0xf1, 0x58, 0x95, 0xb8, + 0xf4, 0xd8, 0x53, 0x85, 0x92, 0x37, 0xe0, 0x09, 0xd0, 0xae, 0x37, 0x05, 0xae, 0xdc, 0x66, 0xbe, + 0xf9, 0xf1, 0xf7, 0x7d, 0x9e, 0x45, 0x47, 0x20, 0xa9, 0x0f, 0x75, 0xe1, 0xd7, 0x13, 0x1f, 0x6a, + 0x60, 0x52, 0x78, 0xab, 0x92, 0x4b, 0x8e, 0x11, 0x48, 0xea, 0x41, 0x5d, 0x78, 0xf5, 0xe4, 0xd8, + 0x89, 0xb9, 0x28, 0xb8, 0xf0, 0x23, 0x22, 0xc0, 0xaf, 0x27, 0x11, 0x48, 0x32, 0xf1, 0x63, 0x9e, + 0xb1, 0xb6, 0xf7, 0x78, 0x98, 0xf2, 0x94, 0xeb, 0xd0, 0x57, 0x51, 0x8b, 0xba, 0x3f, 0x2c, 0x74, + 0x77, 0xae, 0x56, 0xce, 0x25, 0x85, 0x12, 0xaa, 0x22, 0x68, 0xf0, 0x08, 0x75, 0x49, 0xc1, 0x2b, + 0x26, 0x6d, 0xeb, 0xd4, 0x7a, 0xd2, 0x3f, 0x37, 0x19, 0x1e, 0xa3, 0x43, 0x90, 0x34, 0xa4, 0x44, + 0x50, 0xfb, 0x96, 0xae, 0xf4, 0x40, 0xd2, 0x37, 0x44, 0x50, 0x3c, 0x44, 0x07, 0x19, 0x4b, 0xa0, + 0xb1, 0xf7, 0x34, 0xde, 0x26, 0x6a, 0x20, 0x25, 0x22, 0xac, 0x04, 0x24, 0xf6, 0x7e, 0x3b, 0x90, + 0x12, 0xf1, 0x49, 0x40, 0x82, 0x31, 0xda, 0xd7, 0x7b, 0x0e, 0x34, 0xac, 0x63, 0x7c, 0x1f, 0xf5, + 0x4b, 0x88, 0xb3, 0x55, 0x06, 0x4c, 0xda, 0x5d, 0x5d, 0xf8, 0x03, 0x60, 0x17, 0xdd, 0x51, 0x5f, + 0x97, 0x4d, 0xf8, 0x95, 0x64, 0x39, 0x24, 0x76, 0x4f, 0x77, 0x0c, 0x40, 0xd2, 0xa0, 0x59, 0x68, + 0xc8, 0x7d, 0x84, 0x90, 0x16, 0x13, 0x34, 0x6f, 0x79, 0x8a, 0x8f, 0x50, 0x4f, 0x36, 0x61, 0xce, + 0x53, 0x61, 0x5b, 0xa7, 0x7b, 0x4a, 0x88, 0x54, 0xb8, 0x70, 0x3f, 0xa3, 0xdb, 0xba, 0xed, 0x1d, + 0x08, 0x41, 0x52, 0x50, 0x82, 0x0b, 0x9e, 0x54, 0x39, 0xec, 0x04, 0xb7, 0x99, 0xc2, 0x05, 0xb0, + 0x04, 0x4a, 0x23, 0xd7, 0x64, 0x66, 0xb1, 0x5c, 0xaf, 0xc0, 0xe8, 0xed, 0xca, 0x26, 0x58, 0xaf, + 0xc0, 0x7d, 0x6c, 0xcc, 0x9c, 0xe6, 0x3c, 0x5e, 0x4e, 0x73, 0xce, 0x0b, 0xe5, 0x4c, 0xa4, 0x02, + 0xb3, 0xba, 0x4d, 0xdc, 0x6f, 0x16, 0x1a, 0xeb, 0xce, 0x45, 0xc5, 0x02, 0xbe, 0x04, 0xb6, 0x28, + 0x79, 0x31, 0x25, 0x6c, 0x39, 0xe3, 0x19, 0xc3, 0x0f, 0x10, 0x8a, 0x08, 0x5b, 0x86, 0x09, 0xb0, + 0x9b, 0xc1, 0xbe, 0x42, 0x5e, 0x2b, 0x00, 0x3f, 0x47, 0x23, 0x28, 0xe3, 0xb3, 0xa7, 0x61, 0xcc, + 0x99, 0x2c, 0x49, 0x2c, 0x43, 0x92, 0x24, 0x25, 0x08, 0x61, 0x68, 0x0e, 0x75, 0x75, 0x66, 0x8a, + 0xaf, 0xda, 0x1a, 0xb6, 0x51, 0x2f, 0x2e, 0x81, 0x48, 0x5e, 0x1a, 0xd2, 0xbb, 0xd4, 0xbd, 0xb2, + 0xd0, 0x48, 0x93, 0xf9, 0x08, 0x2c, 0xd9, 0x11, 0x0a, 0xf8, 0xbc, 0x2e, 0xfe, 0x72, 0xc0, 0xfa, + 0xc7, 0x81, 0xff, 0xa3, 0xe0, 0xa0, 0x81, 0xe4, 0xa1, 0xfa, 0x8b, 0xaa, 0xdb, 0xd0, 0xe8, 0x4b, + 0x3e, 0x97, 0x54, 0xb5, 0xe0, 0x0f, 0x48, 0xab, 0x0c, 0xd5, 0xd5, 0xea, 0x83, 0x19, 0x9c, 0x8d, + 0xbd, 0xf6, 0xac, 0x3d, 0x75, 0xd6, 0x9e, 0x39, 0x6b, 0x4f, 0xb9, 0x34, 0xb5, 0x2f, 0xae, 0x4f, + 0x3a, 0xbf, 0xae, 0x4f, 0xee, 0xad, 0x49, 0x91, 0xbf, 0x70, 0x6f, 0x26, 0xdd, 0xf3, 0xc3, 0xc8, + 0x38, 0x39, 0x7d, 0x79, 0xb1, 0x71, 0xac, 0xcb, 0x8d, 0x63, 0xfd, 0xdc, 0x38, 0xd6, 0xf7, 0xad, + 0xd3, 0xb9, 0xdc, 0x3a, 0x9d, 0xab, 0xad, 0xd3, 0xf9, 0xf2, 0x30, 0xcd, 0x24, 0xad, 0x22, 0x2f, + 0xe6, 0x85, 0xff, 0x3e, 0x8b, 0xb2, 0xb2, 0x9a, 0x51, 0x92, 0x31, 0x9f, 0xe9, 0xd8, 0x6f, 0xd4, + 0x7b, 0x8b, 0xba, 0xfa, 0x91, 0x3c, 0xfb, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x93, 0xb4, 0x8f, 0x71, + 0x81, 0x03, 0x00, 0x00, } func (m *EventEthereumTx) Marshal() (dAtA []byte, err error) { @@ -492,6 +639,104 @@ func (m *EventBlockBloom) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventFunTokenFromBankCoin) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventFunTokenFromBankCoin) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventFunTokenFromBankCoin) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x1a + } + if len(m.Erc20ContractAddress) > 0 { + i -= len(m.Erc20ContractAddress) + copy(dAtA[i:], m.Erc20ContractAddress) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Erc20ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.BankDenom) > 0 { + i -= len(m.BankDenom) + copy(dAtA[i:], m.BankDenom) + i = encodeVarintEvents(dAtA, i, uint64(len(m.BankDenom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventSendFunTokenToEvm) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventSendFunTokenToEvm) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventSendFunTokenToEvm) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.BankCoin.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.ToEthAddr) > 0 { + i -= len(m.ToEthAddr) + copy(dAtA[i:], m.ToEthAddr) + i = encodeVarintEvents(dAtA, i, uint64(len(m.ToEthAddr))) + i-- + dAtA[i] = 0x1a + } + if len(m.Erc20ContractAddress) > 0 { + i -= len(m.Erc20ContractAddress) + copy(dAtA[i:], m.Erc20ContractAddress) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Erc20ContractAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { offset -= sovEvents(v) base := offset @@ -589,6 +834,50 @@ func (m *EventBlockBloom) Size() (n int) { return n } +func (m *EventFunTokenFromBankCoin) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BankDenom) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Erc20ContractAddress) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventSendFunTokenToEvm) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.Erc20ContractAddress) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.ToEthAddr) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = m.BankCoin.Size() + n += 1 + l + sovEvents(uint64(l)) + return n +} + func sovEvents(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1179,6 +1468,331 @@ func (m *EventBlockBloom) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventFunTokenFromBankCoin) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventFunTokenFromBankCoin: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventFunTokenFromBankCoin: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BankDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BankDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventSendFunTokenToEvm) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventSendFunTokenToEvm: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventSendFunTokenToEvm: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20ContractAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20ContractAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToEthAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToEthAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BankCoin", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BankCoin.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvents(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/evm/evmmodule/genesis.go b/x/evm/evmmodule/genesis.go index c2ea8faa7..32b9f0ca7 100644 --- a/x/evm/evmmodule/genesis.go +++ b/x/evm/evmmodule/genesis.go @@ -7,7 +7,6 @@ import ( abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -25,6 +24,9 @@ func InitGenesis( ) []abci.ValidatorUpdate { k.SetParams(ctx, genState.Params) + // Note that "GetModuleAccount" initializes the module account with permissions + // under the hood if it did not already exist. This is important because the + // EVM module needs to be able to send and receive funds during MsgEthereumTx if evmModule := accountKeeper.GetModuleAccount(ctx, evm.ModuleName); evmModule == nil { panic("the EVM module account has not been set") } diff --git a/x/evm/evmtest/erc20.go b/x/evm/evmtest/erc20.go index 88d32aa4e..9709c914c 100644 --- a/x/evm/evmtest/erc20.go +++ b/x/evm/evmtest/erc20.go @@ -4,8 +4,10 @@ import ( "math/big" "testing" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" "github.com/NibiruChain/nibiru/x/evm" ) @@ -29,3 +31,54 @@ func AssertERC20BalanceEqual( assert.NoError(t, err) assert.Equal(t, balance.String(), gotBalance.String()) } + +// CreateFunTokenForBankCoin: Uses the "TestDeps.Sender" account to create a +// "FunToken" mapping for a new coin +func CreateFunTokenForBankCoin( + deps *TestDeps, bankDenom string, s *suite.Suite, +) (funtoken evm.FunToken) { + s.T().Log("Setup: Create a coin in the bank state") + bankMetadata := bank.Metadata{ + DenomUnits: []*bank.DenomUnit{ + { + Denom: bankDenom, + Exponent: 0, + }, + }, + Base: bankDenom, + Display: bankDenom, + Name: bankDenom, + Symbol: bankDenom, + } + if deps.Chain.BankKeeper.HasDenomMetaData(deps.Ctx, bankDenom) { + s.Failf("setting bank.DenomMetadata would overwrite existing denom \"%s\"", bankDenom) + } + deps.Chain.BankKeeper.SetDenomMetaData(deps.Ctx, bankMetadata) + + s.T().Log("happy: CreateFunToken for the bank coin") + createFuntokenResp, err := deps.K.CreateFunToken( + deps.GoCtx(), + &evm.MsgCreateFunToken{ + FromBankDenom: bankDenom, + Sender: deps.Sender.NibiruAddr.String(), + }, + ) + s.NoError(err, "bankDenom %s", bankDenom) + erc20 := createFuntokenResp.FuntokenMapping.Erc20Addr + funtoken = evm.FunToken{ + Erc20Addr: erc20, + BankDenom: bankDenom, + IsMadeFromCoin: true, + } + s.Equal(createFuntokenResp.FuntokenMapping, funtoken) + + s.T().Log("Expect ERC20 to be deployed") + erc20Addr := erc20.ToAddr() + queryCodeReq := &evm.QueryCodeRequest{ + Address: erc20Addr.String(), + } + _, err = deps.K.Code(deps.Ctx, queryCodeReq) + s.NoError(err) + + return funtoken +} diff --git a/x/evm/evmtest/eth_test.go b/x/evm/evmtest/eth_test.go index f6f0cb332..774b2d3d7 100644 --- a/x/evm/evmtest/eth_test.go +++ b/x/evm/evmtest/eth_test.go @@ -2,6 +2,7 @@ package evmtest_test import ( + "math/big" "testing" "github.com/stretchr/testify/suite" @@ -9,15 +10,15 @@ import ( "github.com/NibiruChain/nibiru/x/evm/evmtest" ) -type SuiteEVMTest struct { +type Suite struct { suite.Suite } -func TestSuiteEVMTest(t *testing.T) { - suite.Run(t, new(SuiteEVMTest)) +func TestSuiteEVM(t *testing.T) { + suite.Run(t, new(Suite)) } -func (s *SuiteEVMTest) TestSampleFns() { +func (s *Suite) TestSampleFns() { s.T().Log("Test NewEthTxMsg") ethTxMsg := evmtest.NewEthTxMsg() err := ethTxMsg.ValidateBasic() @@ -31,3 +32,17 @@ func (s *SuiteEVMTest) TestSampleFns() { s.T().Log("Test NewEthTxMsgs") _, _, _ = evmtest.NewEthTxMsgAsCmt(s.T()) } + +func (s *Suite) TestERC20Helpers() { + deps := evmtest.NewTestDeps() + bankDenom := "token" + funtoken := evmtest.CreateFunTokenForBankCoin(&deps, bankDenom, &s.Suite) + erc20Contract := funtoken.Erc20Addr.ToAddr() + + evmtest.AssertERC20BalanceEqual( + s.T(), &deps, + erc20Contract, + deps.Sender.EthAddr, + big.NewInt(0), + ) +} diff --git a/x/evm/evmtest/smart_contract_test.go b/x/evm/evmtest/smart_contract_test.go index 7d9c209e4..e9b498e0e 100644 --- a/x/evm/evmtest/smart_contract_test.go +++ b/x/evm/evmtest/smart_contract_test.go @@ -8,7 +8,7 @@ import ( "github.com/NibiruChain/nibiru/x/evm/evmtest" ) -func (s *SuiteEVMTest) TestCreateContractTxMsg() { +func (s *Suite) TestCreateContractTxMsg() { deps := evmtest.NewTestDeps() ethAcc := evmtest.NewEthAccInfo() @@ -24,7 +24,7 @@ func (s *SuiteEVMTest) TestCreateContractTxMsg() { s.Require().NoError(ethTxMsg.ValidateBasic()) } -func (s *SuiteEVMTest) TestCreateContractGethCoreMsg() { +func (s *Suite) TestCreateContractGethCoreMsg() { deps := evmtest.NewTestDeps() ethAcc := evmtest.NewEthAccInfo() diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 8a89ff4f5..d65a32433 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -391,11 +391,14 @@ func (k Keeper) LoadERC20BigInt( methodName string, args ...any, ) (out *big.Int, err error) { + commit := false res, err := k.CallContract( - ctx, erc20Abi, + ctx, + erc20Abi, evm.ModuleAddressEVM(), &erc20Contract, - false, methodName, + commit, + methodName, args..., ) if err != nil { diff --git a/x/evm/keeper/erc20_test.go b/x/evm/keeper/erc20_test.go index 83dc3b87d..411a5a688 100644 --- a/x/evm/keeper/erc20_test.go +++ b/x/evm/keeper/erc20_test.go @@ -3,7 +3,11 @@ package keeper_test import ( "fmt" + "math/big" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" bank "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ethereum/go-ethereum/crypto" @@ -73,7 +77,7 @@ func (s *Suite) TestCreateFunTokenFromERC20() { createFuntokenResp, err := deps.K.CreateFunToken( deps.GoCtx(), &evm.MsgCreateFunToken{ - FromErc20: erc20Addr, + FromErc20: &erc20Addr, Sender: deps.Sender.NibiruAddr.String(), }, ) @@ -90,7 +94,7 @@ func (s *Suite) TestCreateFunTokenFromERC20() { _, err = deps.K.CreateFunToken( deps.GoCtx(), &evm.MsgCreateFunToken{ - FromErc20: erc20Addr, + FromErc20: &erc20Addr, Sender: deps.Sender.NibiruAddr.String(), }, ) @@ -100,7 +104,7 @@ func (s *Suite) TestCreateFunTokenFromERC20() { _, err = deps.K.CreateFunToken( deps.GoCtx(), &evm.MsgCreateFunToken{ - FromErc20: erc20Addr, + FromErc20: &erc20Addr, }, ) s.ErrorContains(err, "invalid sender") @@ -158,19 +162,8 @@ func (s *Suite) TestCreateFunTokenFromCoin() { s.T().Log("Setup: Create a coin in the bank state") bankDenom := "sometoken" - bankMetadata := bank.Metadata{ - DenomUnits: []*bank.DenomUnit{ - { - Denom: bankDenom, - Exponent: 0, - }, - }, - Base: bankDenom, - Display: bankDenom, - Name: bankDenom, - Symbol: "TOKEN", - } - deps.Chain.BankKeeper.SetDenomMetaData(deps.Ctx, bankMetadata) + + setBankDenomMetadata(deps.Ctx, deps.Chain.BankKeeper, bankDenom) s.T().Log("happy: CreateFunToken for the bank coin") createFuntokenResp, err := deps.K.CreateFunToken( @@ -218,3 +211,201 @@ func (s *Suite) TestCreateFunTokenFromCoin() { ) s.ErrorContains(err, "Funtoken mapping already created") } + +// TestSendFunTokenToEvm executes sending fun tokens from bank coin to erc20 and checks the results: +// - sender balance should be reduced by sendAmount +// - erc-20 balance should be increased by sendAmount +// - evm module account should hold sender's coins +func (s *Suite) TestSendFunTokenToEvm() { + for _, tc := range []struct { + name string + bankDenom string + senderBalanceBefore math.Int + amountToSend math.Int + wantErr string + }{ + { + name: "happy: proper sending", + bankDenom: "unibi", + senderBalanceBefore: math.NewInt(100), + amountToSend: math.NewInt(10), + wantErr: "", + }, + { + name: "sad: not registered bank denom", + bankDenom: "not-registered-denom", + senderBalanceBefore: math.NewInt(100), + amountToSend: math.NewInt(10), + wantErr: "does not exist", + }, + { + name: "sad: insufficient balance", + bankDenom: "unibi", + senderBalanceBefore: math.NewInt(10), + amountToSend: math.NewInt(100), + wantErr: "insufficient funds", + }, + } { + s.Run(tc.name, func() { + deps := evmtest.NewTestDeps() + bankDenom := "unibi" + recipientEVMAddr := eth.MustNewHexAddrFromStr("0x1234500000000000000000000000000000000000") + evmModuleAddr := deps.Chain.AccountKeeper.GetModuleAddress(evm.ModuleName) + spendableAmount := tc.senderBalanceBefore.Int64() + spendableCoins := sdk.NewCoins(sdk.NewInt64Coin(bankDenom, spendableAmount)) + + ctx := deps.GoCtx() + setBankDenomMetadata(deps.Ctx, deps.Chain.BankKeeper, bankDenom) + + // Fund sender's wallet + err := deps.Chain.BankKeeper.MintCoins(deps.Ctx, evm.ModuleName, spendableCoins) + s.Require().NoError(err) + err = deps.Chain.BankKeeper.SendCoinsFromModuleToAccount( + deps.Ctx, evm.ModuleName, deps.Sender.NibiruAddr, spendableCoins, + ) + s.Require().NoError(err) + + // Create fun token from coin + createFunTokenResp, err := deps.K.CreateFunToken( + ctx, + &evm.MsgCreateFunToken{ + FromBankDenom: bankDenom, + Sender: deps.Sender.NibiruAddr.String(), + }, + ) + s.Require().NoError(err) + funTokenErc20Addr := createFunTokenResp.FuntokenMapping.Erc20Addr.ToAddr() + + // Send fun token to ERC-20 contract + _, err = deps.K.SendFunTokenToEvm( + ctx, + &evm.MsgSendFunTokenToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.Coin{Denom: tc.bankDenom, Amount: tc.amountToSend}, + ToEthAddr: recipientEVMAddr, + }, + ) + if tc.wantErr != "" { + s.Require().ErrorContains(err, tc.wantErr) + return + } + s.Require().NoError(err) + + // Check 1: coins are stored on a module balance + moduleBalance, err := deps.Chain.BankKeeper.Balance(ctx, &bank.QueryBalanceRequest{ + Address: evmModuleAddr.String(), + Denom: bankDenom, + }) + s.Require().NoError(err) + s.Equal(tc.amountToSend, moduleBalance.Balance.Amount) + + // Check 2: Sender balance reduced by send amount + senderBalance, err := deps.Chain.BankKeeper.Balance(ctx, &bank.QueryBalanceRequest{ + Address: deps.Sender.NibiruAddr.String(), + Denom: bankDenom, + }) + s.Require().NoError(err) + s.Equal(tc.senderBalanceBefore.Sub(tc.amountToSend), senderBalance.Balance.Amount) + + // Check 3: erc-20 balance equals to send amount + recipientERC20Balance, err := deps.K.CallContract( + deps.Ctx, + embeds.Contract_ERC20Minter.ABI, + evm.ModuleAddressEVM(), + &funTokenErc20Addr, + false, + "balanceOf", + recipientEVMAddr.ToAddr(), + ) + s.Require().NoError(err) + res, err := embeds.Contract_ERC20Minter.ABI.Unpack( + "balanceOf", recipientERC20Balance.Ret, + ) + s.Require().NoError(err) + s.Equal(1, len(res)) + s.Equal(tc.amountToSend.BigInt(), res[0]) + }) + } +} + +// setBankDenomMetadata utility method to set bank denom metadata required for working with coin +func setBankDenomMetadata(ctx sdk.Context, bankKeeper bankkeeper.Keeper, bankDenom string) { + bankMetadata := bank.Metadata{ + DenomUnits: []*bank.DenomUnit{ + { + Denom: bankDenom, + Exponent: 0, + }, + }, + Base: bankDenom, + Display: bankDenom, + Name: bankDenom, + Symbol: "TOKEN", + } + bankKeeper.SetDenomMetaData(ctx, bankMetadata) +} + +func (s *Suite) TestERC20Calls() { + deps := evmtest.NewTestDeps() + bankDenom := "ibc/btc" + funtoken := evmtest.CreateFunTokenForBankCoin(&deps, bankDenom, &s.Suite) + contract := funtoken.Erc20Addr.ToAddr() + + theUser := deps.Sender.EthAddr + theEvm := evm.ModuleAddressEVM() + + s.T().Log("Mint tokens - Fail from non-owner") + { + from := theUser + to := theUser + _, err := deps.K.ERC20().Mint(contract, from, to, big.NewInt(69_420), deps.Ctx) + s.ErrorContains(err, "Ownable: caller is not the owner") + } + + s.T().Log("Mint tokens - Success") + { + from := theEvm + to := theEvm + + _, err := deps.K.ERC20().Mint(contract, from, to, big.NewInt(69_420), deps.Ctx) + s.NoError(err) + + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(0)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(69_420)) + } + + s.T().Log("Transfer - Not enough funds") + { + from := theUser + to := theEvm + _, err := deps.K.ERC20().Transfer(contract, from, to, big.NewInt(9_420), deps.Ctx) + s.ErrorContains(err, "ERC20: transfer amount exceeds balance") + // balances unchanged + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(0)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(69_420)) + } + + s.T().Log("Transfer - Success (sanity check)") + { + from := theEvm + to := theUser + _, err := deps.K.ERC20().Transfer(contract, from, to, big.NewInt(9_420), deps.Ctx) + s.NoError(err) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(9_420)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(60_000)) + } + + s.T().Log("Burn tokens - Allowed as non-owner") + { + from := theUser + _, err := deps.K.ERC20().Burn(contract, from, big.NewInt(420), deps.Ctx) + s.NoError(err) + + from = theEvm + _, err = deps.K.ERC20().Burn(contract, from, big.NewInt(6_000), deps.Ctx) + s.NoError(err) + + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(9_000)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(54_000)) + } +} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 607c624e9..ea42381f5 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -21,6 +21,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/NibiruChain/nibiru/x/evm/embeds" + "github.com/NibiruChain/nibiru/eth" "github.com/NibiruChain/nibiru/x/evm" "github.com/NibiruChain/nibiru/x/evm/statedb" @@ -490,6 +492,12 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, }, nil } +// CreateFunToken is a gRPC transaction message for creating fungible token +// ("FunToken") a mapping between a bank coin and ERC20 token. +// +// If the mapping is generated from an ERC20, this tx creates a bank coin to go +// with it, and if the mapping's generated from a coin, the EVM module +// deploys an ERC20 contract that for which it will be the owner. func (k *Keeper) CreateFunToken( goCtx context.Context, msg *evm.MsgCreateFunToken, ) (resp *evm.MsgCreateFunTokenResponse, err error) { @@ -502,11 +510,20 @@ func (k *Keeper) CreateFunToken( // TODO: UD-DEBUG: feat: Add fee upon registration. ctx := sdk.UnwrapSDKContext(goCtx) + + emptyErc20 := msg.FromErc20 == nil || msg.FromErc20.Size() == 0 switch { - case msg.FromErc20 != "" && msg.FromBankDenom == "": - funtoken, err = k.CreateFunTokenFromERC20(ctx, msg.FromErc20) - case msg.FromErc20 == "" && msg.FromBankDenom != "": + case !emptyErc20 && msg.FromBankDenom == "": + funtoken, err = k.CreateFunTokenFromERC20(ctx, *msg.FromErc20) + case emptyErc20 && msg.FromBankDenom != "": funtoken, err = k.CreateFunTokenFromCoin(ctx, msg.FromBankDenom) + if err == nil { + _ = ctx.EventManager().EmitTypedEvent(&evm.EventFunTokenFromBankCoin{ + Creator: msg.Sender, + BankDenom: funtoken.BankDenom, + Erc20ContractAddress: funtoken.Erc20Addr.String(), + }) + } default: // Impossible to reach this case due to ValidateBasic err = fmt.Errorf( @@ -520,3 +537,56 @@ func (k *Keeper) CreateFunToken( FuntokenMapping: funtoken, }, err } + +// SendFunTokenToEvm Sends a coin with a valid "FunToken" mapping to the +// given recipient address ("to_eth_addr") in the corresponding ERC20 +// representation. +func (k *Keeper) SendFunTokenToEvm( + goCtx context.Context, msg *evm.MsgSendFunTokenToEvm, +) (resp *evm.MsgSendFunTokenToEvmResponse, err error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender := sdk.MustAccAddressFromBech32(msg.Sender) + toEthAddr := msg.ToEthAddr.ToAddr() + bankDenom := msg.BankCoin.Denom + amount := msg.BankCoin.Amount + + funTokens := k.FunTokens.Collect(ctx, k.FunTokens.Indexes.BankDenom.ExactMatch(ctx, bankDenom)) + if len(funTokens) == 0 { + return nil, fmt.Errorf("funtoken for bank denom \"%s\" does not exist", bankDenom) + } + erc20ContractAddr := funTokens[0].Erc20Addr.ToAddr() + + // Step 1: Send coins to the evm module account + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, evm.ModuleName, sdk.Coins{msg.BankCoin}) + if err != nil { + return nil, errors.Wrap(err, "failed to send coins to module account") + } + + // Step 2: evm call to erc20 minter: mint tokens for a toEthAddr + evmResp, err := k.CallContract( + ctx, + embeds.Contract_ERC20Minter.ABI, + evm.ModuleAddressEVM(), + &erc20ContractAddr, + true, + "mint", + toEthAddr, + amount.BigInt(), + ) + if err != nil { + return nil, err + } + if evmResp.Failed() { + return nil, + fmt.Errorf("failed to mint erc-20 tokens of contract %s", erc20ContractAddr.String()) + } + _ = ctx.EventManager().EmitTypedEvent(&evm.EventSendFunTokenToEvm{ + Sender: msg.Sender, + Erc20ContractAddress: erc20ContractAddr.String(), + ToEthAddr: toEthAddr.String(), + BankCoin: msg.BankCoin, + }) + + return &evm.MsgSendFunTokenToEvmResponse{}, nil +} diff --git a/x/evm/msg.go b/x/evm/msg.go index 5d80786b9..252b46d86 100644 --- a/x/evm/msg.go +++ b/x/evm/msg.go @@ -492,7 +492,9 @@ func (m *MsgCreateFunToken) ValidateBasic() error { erc20 := m.FromErc20 bankDenom := m.FromBankDenom - if (erc20 == "" && bankDenom == "") || (erc20 != "" && bankDenom != "") { + emptyBankDenom := bankDenom == "" + emptyErc20 := !(erc20 != nil && erc20.Size() > 0) + if (emptyErc20 && emptyBankDenom) || (!emptyErc20 && !emptyBankDenom) { return errMsgCreateFunTokenValidate(fmt.Sprintf( "Either the \"from_erc20\" or \"from_bank_denom\" must be set (but not both)."+ "got values (from_erc20=\"%s\", from_bank_denom=\"%s\")", erc20, bankDenom, @@ -506,3 +508,29 @@ func (m *MsgCreateFunToken) ValidateBasic() error { func (m MsgCreateFunToken) GetSignBytes() []byte { return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) } + +// GetSigners returns the expected signers for a MsgSendFunTokenToEvm message. +func (m MsgSendFunTokenToEvm) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(m.Sender) + return []sdk.AccAddress{addr} +} + +func errMsgSendFunTokenToEvmValidate(errMsg string) error { + return fmt.Errorf("MsgSendFunTokenToEvm ValidateBasic error: %s", errMsg) +} + +// ValidateBasic does a sanity check of the provided data +func (m *MsgSendFunTokenToEvm) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(m.Sender); err != nil { + return errMsgCreateFunTokenValidate("invalid sender addr") + } + if m.ToEthAddr == "" { + return errMsgSendFunTokenToEvmValidate("\"to_eth_addr\" must be set") + } + return nil +} + +// GetSignBytes implements the LegacyMsg interface. +func (m MsgSendFunTokenToEvm) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&m)) +} diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index a75eca440..e73eaabe0 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -26,7 +26,7 @@ var ( // Precompile address for "FunToken.sol", the contract that // enables transfers of ERC20 tokens to "nibi" addresses as bank coins // using the ERC20's `FunToken` mapping. -var PrecompileAddr_FuntokenGateway eth.HexAddr = eth.MustNewHexAddrFromStr( +var PrecompileAddr_FuntokenGateway = eth.MustNewHexAddrFromStr( "0x0000000000000000000000000000000000000800", ) @@ -198,6 +198,8 @@ func (p precompileFunToken) bankSend( return method.Outputs.Pack() // TODO: change interface } +// ArgsFunTokenBankSend: Constructor for an "args" array of arguments for the +// "IFunToken.bankSend" function. func ArgsFunTokenBankSend( erc20 gethcommon.Address, amount *big.Int, diff --git a/x/evm/precompile/funtoken_test.go b/x/evm/precompile/funtoken_test.go index edf25382b..1aecefa03 100644 --- a/x/evm/precompile/funtoken_test.go +++ b/x/evm/precompile/funtoken_test.go @@ -5,8 +5,10 @@ import ( "math/big" "testing" - bank "github.com/cosmos/cosmos-sdk/x/bank/types" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/NibiruChain/nibiru/eth" "github.com/NibiruChain/nibiru/x/common/testutil" "github.com/NibiruChain/nibiru/x/evm" "github.com/NibiruChain/nibiru/x/evm/embeds" @@ -31,52 +33,6 @@ func (s *Suite) TestPrecompile_FunToken() { s.Run("HappyPath", s.FunToken_HappyPath) } -func CreateFunTokenForBankCoin( - deps *evmtest.TestDeps, bankDenom string, s *Suite, -) (funtoken evm.FunToken) { - s.T().Log("Setup: Create a coin in the bank state") - bankMetadata := bank.Metadata{ - DenomUnits: []*bank.DenomUnit{ - { - Denom: bankDenom, - Exponent: 0, - }, - }, - Base: bankDenom, - Display: bankDenom, - Name: bankDenom, - Symbol: "TOKEN", - } - deps.Chain.BankKeeper.SetDenomMetaData(deps.Ctx, bankMetadata) - - s.T().Log("happy: CreateFunToken for the bank coin") - createFuntokenResp, err := deps.K.CreateFunToken( - deps.GoCtx(), - &evm.MsgCreateFunToken{ - FromBankDenom: bankDenom, - Sender: deps.Sender.NibiruAddr.String(), - }, - ) - s.NoError(err, "bankDenom %s", bankDenom) - erc20 := createFuntokenResp.FuntokenMapping.Erc20Addr - funtoken = evm.FunToken{ - Erc20Addr: erc20, - BankDenom: bankDenom, - IsMadeFromCoin: true, - } - s.Equal(createFuntokenResp.FuntokenMapping, funtoken) - - s.T().Log("Expect ERC20 to be deployed") - erc20Addr := erc20.ToAddr() - queryCodeReq := &evm.QueryCodeRequest{ - Address: erc20Addr.String(), - } - _, err = deps.K.Code(deps.Ctx, queryCodeReq) - s.NoError(err) - - return funtoken -} - // PrecompileExists: An integration test showing that a "PrecompileError" occurs // when calling the FunToken func (s *Suite) FunToken_PrecompileExists() { @@ -117,66 +73,82 @@ func (s *Suite) FunToken_PrecompileExists() { s.ErrorContains(err, "Precompile error") } +// FunToken_HappyPath: runs a whole process of sending fun token from bank to evm and back +// Steps: +// 1. Mint a new bank coin: ibc/usdc +// 2. Create fungible token from the bank coin +// 3. Send coins from bank to evm account +// 4. Send some coins between evm accounts +// 5. Send part of the tokens from evm to a bank account func (s *Suite) FunToken_HappyPath() { precompileAddr := precompile.PrecompileAddr_FuntokenGateway abi := embeds.Contract_Funtoken.ABI deps := evmtest.NewTestDeps() + bankDenom := "ibc/usdc" + amountToSendToEvm := int64(69_420) + amountToSendWithinEvm := int64(1) + amountToSendFromEvm := int64(419) + theUser := deps.Sender.EthAddr theEvm := evm.ModuleAddressEVM() s.True(deps.K.PrecompileSet().Has(precompileAddr.ToAddr()), "did not see precompile address during \"InitPrecompiles\"") + // Create new fungible token s.T().Log("Create FunToken mapping and ERC20") - bankDenom := "ibc/usdc" - funtoken := CreateFunTokenForBankCoin(&deps, bankDenom, s) + funtoken := evmtest.CreateFunTokenForBankCoin(&deps, bankDenom, &s.Suite) contract := funtoken.Erc20Addr.ToAddr() + // Mint coins for the sender + spendableCoins := sdk.NewCoins(sdk.NewInt64Coin(bankDenom, amountToSendToEvm)) + err := deps.Chain.BankKeeper.MintCoins(deps.Ctx, evm.ModuleName, spendableCoins) + s.Require().NoError(err) + err = deps.Chain.BankKeeper.SendCoinsFromModuleToAccount( + deps.Ctx, evm.ModuleName, deps.Sender.NibiruAddr, spendableCoins, + ) + s.Require().NoError(err) + s.T().Log("Balances of the ERC20 should start empty") evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(0)) evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(0)) - s.T().Log("Mint tokens - Fail from non-owner") - { - from := theUser - to := theUser - input, err := embeds.Contract_ERC20Minter.ABI.Pack("mint", to, big.NewInt(69_420)) - s.NoError(err) - _, err = evmtest.DoEthTx(&deps, contract, from, input) - s.ErrorContains(err, "Ownable: caller is not the owner") - } - - s.T().Log("Mint tokens - Success") - { - from := theEvm - to := theUser - input, err := embeds.Contract_ERC20Minter.ABI.Pack("mint", to, big.NewInt(69_420)) - s.NoError(err) + // Send fungible tokens from bank to EVM + _, err = deps.K.SendFunTokenToEvm( + deps.Ctx, + &evm.MsgSendFunTokenToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.Coin{Denom: bankDenom, Amount: math.NewInt(amountToSendToEvm)}, + ToEthAddr: eth.MustNewHexAddrFromStr(theUser.String()), + }, + ) + s.Require().NoError(err, "failed to send FunToken to EVM") - _, err = evmtest.DoEthTx(&deps, contract, from, input) - s.NoError(err) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(69_420)) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(0)) - } + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(amountToSendToEvm)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(0)) + // Transfer tokens to another account within EVM s.T().Log("Transfer - Success (sanity check)") randomAcc := testutil.AccAddress() + amountRemaining := amountToSendToEvm - amountToSendWithinEvm { from := theUser to := theEvm - _, err := deps.K.ERC20().Transfer(contract, from, to, big.NewInt(1), deps.Ctx) + _, err := deps.K.ERC20().Transfer(contract, from, to, big.NewInt(amountToSendWithinEvm), deps.Ctx) s.NoError(err) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(69_419)) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(1)) - s.Equal("0", - deps.Chain.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(amountRemaining)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(amountToSendWithinEvm)) + s.Equal( + int64(0), + deps.Chain.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.Int64(), ) } + // Send fungible token from EVM to bank s.T().Log("Send using precompile") - amtToSend := int64(419) - callArgs := precompile.ArgsFunTokenBankSend(contract, big.NewInt(amtToSend), randomAcc) + + callArgs := precompile.ArgsFunTokenBankSend(contract, big.NewInt(amountToSendFromEvm), randomAcc) methodName := string(precompile.FunTokenMethod_BankSend) input, err := abi.Pack(methodName, callArgs...) s.NoError(err) @@ -185,15 +157,21 @@ func (s *Suite) FunToken_HappyPath() { _, err = evmtest.DoEthTx(&deps, precompileAddr.ToAddr(), from, input) s.Require().NoError(err) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(69_419-amtToSend)) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(1)) - s.Equal(fmt.Sprintf("%d", amtToSend), - deps.Chain.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), + evmtest.AssertERC20BalanceEqual( + s.T(), + &deps, + contract, + theUser, + big.NewInt(amountRemaining-amountToSendFromEvm), ) - - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(69_000)) - evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(1)) - s.Equal("419", + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(amountToSendWithinEvm)) + s.Equal(fmt.Sprintf("%d", amountToSendFromEvm), deps.Chain.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), ) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theUser, big.NewInt(amountRemaining-amountToSendFromEvm)) + evmtest.AssertERC20BalanceEqual(s.T(), &deps, contract, theEvm, big.NewInt(amountToSendWithinEvm)) + s.Equal( + amountToSendFromEvm, + deps.Chain.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.Int64(), + ) } diff --git a/x/evm/tx.pb.go b/x/evm/tx.pb.go index 5677fcde6..329cd8080 100644 --- a/x/evm/tx.pb.go +++ b/x/evm/tx.pb.go @@ -11,6 +11,7 @@ import ( github_com_NibiruChain_nibiru_eth "github.com/NibiruChain/nibiru/eth" _ "github.com/cosmos/cosmos-proto" types "github.com/cosmos/cosmos-sdk/codec/types" + types1 "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" @@ -446,7 +447,7 @@ var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo // denomination for a bank coin can be given to create the mapping to an ERC20. type MsgCreateFunToken struct { // Hexadecimal address of the ERC20 token to which the `FunToken` maps - FromErc20 github_com_NibiruChain_nibiru_eth.HexAddr `protobuf:"bytes,1,opt,name=from_erc20,json=fromErc20,proto3,customtype=github.com/NibiruChain/nibiru/eth.HexAddr" json:"from_erc20"` + FromErc20 *github_com_NibiruChain_nibiru_eth.HexAddr `protobuf:"bytes,1,opt,name=from_erc20,json=fromErc20,proto3,customtype=github.com/NibiruChain/nibiru/eth.HexAddr" json:"from_erc20,omitempty"` // Coin denomination in the Bank Module. FromBankDenom string `protobuf:"bytes,2,opt,name=from_bank_denom,json=fromBankDenom,proto3" json:"from_bank_denom,omitempty"` // Sender: Address for the signer of the transaction. @@ -545,6 +546,99 @@ func (m *MsgCreateFunTokenResponse) GetFuntokenMapping() FunToken { return FunToken{} } +// MsgSendFunTokenToEvm: Arguments to send a bank coin to ERC-20 representation +type MsgSendFunTokenToEvm struct { + // Hexadecimal address of the ERC20 token to which the `FunToken` maps + ToEthAddr github_com_NibiruChain_nibiru_eth.HexAddr `protobuf:"bytes,1,opt,name=to_eth_addr,json=toEthAddr,proto3,customtype=github.com/NibiruChain/nibiru/eth.HexAddr" json:"to_eth_addr"` + // Sender: Address for the signer of the transaction. + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + // Bank coin to get converted to ERC20 + BankCoin types1.Coin `protobuf:"bytes,3,opt,name=bank_coin,json=bankCoin,proto3" json:"bank_coin" yaml:"bank_coin"` +} + +func (m *MsgSendFunTokenToEvm) Reset() { *m = MsgSendFunTokenToEvm{} } +func (m *MsgSendFunTokenToEvm) String() string { return proto.CompactTextString(m) } +func (*MsgSendFunTokenToEvm) ProtoMessage() {} +func (*MsgSendFunTokenToEvm) Descriptor() ([]byte, []int) { + return fileDescriptor_82a0bfe4f0bab953, []int{10} +} +func (m *MsgSendFunTokenToEvm) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSendFunTokenToEvm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSendFunTokenToEvm.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSendFunTokenToEvm) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSendFunTokenToEvm.Merge(m, src) +} +func (m *MsgSendFunTokenToEvm) XXX_Size() int { + return m.Size() +} +func (m *MsgSendFunTokenToEvm) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSendFunTokenToEvm.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSendFunTokenToEvm proto.InternalMessageInfo + +func (m *MsgSendFunTokenToEvm) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgSendFunTokenToEvm) GetBankCoin() types1.Coin { + if m != nil { + return m.BankCoin + } + return types1.Coin{} +} + +type MsgSendFunTokenToEvmResponse struct { +} + +func (m *MsgSendFunTokenToEvmResponse) Reset() { *m = MsgSendFunTokenToEvmResponse{} } +func (m *MsgSendFunTokenToEvmResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSendFunTokenToEvmResponse) ProtoMessage() {} +func (*MsgSendFunTokenToEvmResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_82a0bfe4f0bab953, []int{11} +} +func (m *MsgSendFunTokenToEvmResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSendFunTokenToEvmResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSendFunTokenToEvmResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgSendFunTokenToEvmResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSendFunTokenToEvmResponse.Merge(m, src) +} +func (m *MsgSendFunTokenToEvmResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSendFunTokenToEvmResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSendFunTokenToEvmResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSendFunTokenToEvmResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgEthereumTx)(nil), "eth.evm.v1.MsgEthereumTx") proto.RegisterType((*LegacyTx)(nil), "eth.evm.v1.LegacyTx") @@ -556,81 +650,92 @@ func init() { proto.RegisterType((*MsgUpdateParamsResponse)(nil), "eth.evm.v1.MsgUpdateParamsResponse") proto.RegisterType((*MsgCreateFunToken)(nil), "eth.evm.v1.MsgCreateFunToken") proto.RegisterType((*MsgCreateFunTokenResponse)(nil), "eth.evm.v1.MsgCreateFunTokenResponse") + proto.RegisterType((*MsgSendFunTokenToEvm)(nil), "eth.evm.v1.MsgSendFunTokenToEvm") + proto.RegisterType((*MsgSendFunTokenToEvmResponse)(nil), "eth.evm.v1.MsgSendFunTokenToEvmResponse") } func init() { proto.RegisterFile("eth/evm/v1/tx.proto", fileDescriptor_82a0bfe4f0bab953) } var fileDescriptor_82a0bfe4f0bab953 = []byte{ - // 1104 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xbf, 0x6f, 0x23, 0xc5, - 0x17, 0xcf, 0xda, 0xeb, 0x5f, 0xcf, 0xbe, 0xe4, 0xbe, 0xfb, 0xcd, 0x71, 0xb6, 0x39, 0xbc, 0xc6, - 0x11, 0xc8, 0x20, 0x65, 0xf7, 0x2e, 0x48, 0x48, 0x17, 0x89, 0x22, 0xce, 0x0f, 0x38, 0x94, 0x40, - 0xb4, 0x38, 0x14, 0x34, 0xd6, 0x78, 0x77, 0xb2, 0x5e, 0x25, 0x3b, 0xb3, 0xda, 0x99, 0xb5, 0x1c, - 0xca, 0xab, 0x90, 0x28, 0x00, 0xd1, 0x03, 0x0d, 0x0d, 0x15, 0xc5, 0x15, 0xfc, 0x09, 0x27, 0xaa, - 0x13, 0x34, 0xe8, 0x0a, 0x83, 0x12, 0x24, 0xa4, 0x94, 0x14, 0xd4, 0x68, 0x66, 0xd7, 0xbf, 0x12, - 0xd9, 0xc0, 0x09, 0xd1, 0xcd, 0x9b, 0xf7, 0xde, 0x67, 0xde, 0xfb, 0x7c, 0x66, 0xdf, 0x2c, 0xfc, - 0x1f, 0xf3, 0x9e, 0x89, 0xfb, 0xbe, 0xd9, 0xbf, 0x67, 0xf2, 0x81, 0x11, 0x84, 0x94, 0x53, 0x0d, - 0x30, 0xef, 0x19, 0xb8, 0xef, 0x1b, 0xfd, 0x7b, 0xd5, 0xdb, 0x36, 0x65, 0x3e, 0x65, 0xa6, 0xcf, - 0x5c, 0x11, 0xe3, 0x33, 0x37, 0x0e, 0xaa, 0x56, 0x62, 0x47, 0x47, 0x5a, 0x66, 0x6c, 0x24, 0xae, - 0xd5, 0x29, 0x50, 0x01, 0x93, 0xec, 0xba, 0xd4, 0xa5, 0x71, 0xb4, 0x58, 0x25, 0xbb, 0x77, 0x5c, - 0x4a, 0xdd, 0x53, 0x6c, 0xa2, 0xc0, 0x33, 0x11, 0x21, 0x94, 0x23, 0xee, 0x51, 0x32, 0x42, 0xaa, - 0x24, 0x5e, 0x69, 0x75, 0xa3, 0x63, 0x13, 0x91, 0xb3, 0xd8, 0xd5, 0xf8, 0x44, 0x81, 0x1b, 0x07, - 0xcc, 0xdd, 0xe5, 0x3d, 0x1c, 0xe2, 0xc8, 0x6f, 0x0f, 0xb4, 0x26, 0xa8, 0x0e, 0xe2, 0xa8, 0xac, - 0xd4, 0x95, 0x66, 0x71, 0x63, 0xd5, 0x88, 0x73, 0x8d, 0x51, 0xae, 0xb1, 0x45, 0xce, 0x2c, 0x19, - 0xa1, 0x55, 0x40, 0x65, 0xde, 0x87, 0xb8, 0x9c, 0xaa, 0x2b, 0x4d, 0xa5, 0x95, 0xb9, 0x1c, 0xea, - 0xca, 0xba, 0x25, 0xb7, 0x34, 0x1d, 0xd4, 0x1e, 0x62, 0xbd, 0x72, 0xba, 0xae, 0x34, 0x0b, 0xad, - 0xe2, 0xef, 0x43, 0x3d, 0x17, 0x9e, 0x06, 0x9b, 0x8d, 0xf5, 0x86, 0x25, 0x1d, 0x9a, 0x06, 0xea, - 0x71, 0x48, 0xfd, 0xb2, 0x2a, 0x02, 0x2c, 0xb9, 0xde, 0x54, 0x3f, 0xfa, 0x4a, 0x5f, 0x6a, 0x7c, - 0x96, 0x82, 0xfc, 0x3e, 0x76, 0x91, 0x7d, 0xd6, 0x1e, 0x68, 0xab, 0x90, 0x21, 0x94, 0xd8, 0x58, - 0x56, 0xa3, 0x5a, 0xb1, 0xa1, 0xbd, 0x0e, 0x05, 0x17, 0x09, 0xce, 0x3c, 0x3b, 0x3e, 0xbd, 0xd0, - 0xaa, 0x3c, 0x1d, 0xea, 0xb7, 0x62, 0xfa, 0x98, 0x73, 0x62, 0x78, 0xd4, 0xf4, 0x11, 0xef, 0x19, - 0x0f, 0x08, 0xb7, 0xf2, 0x2e, 0x62, 0x87, 0x22, 0x54, 0xab, 0x41, 0xda, 0x45, 0x4c, 0x16, 0xa5, - 0xb6, 0x4a, 0xe7, 0x43, 0x3d, 0xff, 0x26, 0x62, 0xfb, 0x9e, 0xef, 0x71, 0x4b, 0x38, 0xb4, 0x65, - 0x48, 0x71, 0x9a, 0x94, 0x94, 0xe2, 0x54, 0xbb, 0x0f, 0x99, 0x3e, 0x3a, 0x8d, 0x70, 0x39, 0x23, - 0xcf, 0x58, 0x9b, 0x7b, 0xc6, 0xf9, 0x50, 0xcf, 0x6e, 0xf9, 0x34, 0x22, 0xdc, 0x8a, 0x33, 0x44, - 0x7f, 0x92, 0xc5, 0x6c, 0x5d, 0x69, 0x96, 0x12, 0xbe, 0x4a, 0xa0, 0xf4, 0xcb, 0x39, 0xb9, 0xa1, - 0xf4, 0x85, 0x15, 0x96, 0xf3, 0xb1, 0x15, 0x0a, 0x8b, 0x95, 0x0b, 0xb1, 0xc5, 0x36, 0x97, 0x05, - 0x13, 0xdf, 0x3f, 0x5a, 0xcf, 0xb6, 0x07, 0x3b, 0x88, 0xa3, 0xc6, 0x77, 0x69, 0x28, 0x6d, 0xd9, - 0x36, 0x66, 0x6c, 0xdf, 0x63, 0xbc, 0x3d, 0xd0, 0xde, 0x86, 0xbc, 0xdd, 0x43, 0x1e, 0xe9, 0x78, - 0x8e, 0xa4, 0xa6, 0xd0, 0x32, 0x17, 0x15, 0x97, 0xdb, 0x16, 0xc1, 0x0f, 0x76, 0x2e, 0x87, 0x7a, - 0xce, 0x8e, 0x97, 0x56, 0xb2, 0x70, 0x26, 0x1c, 0xa7, 0xe6, 0x72, 0x9c, 0xfe, 0xc7, 0x1c, 0xab, - 0x8b, 0x39, 0xce, 0x5c, 0xe7, 0x38, 0xfb, 0xcc, 0x1c, 0xe7, 0xa6, 0x38, 0x3e, 0x82, 0x3c, 0x92, - 0x44, 0x61, 0x56, 0xce, 0xd7, 0xd3, 0xcd, 0xe2, 0xc6, 0x6d, 0x63, 0xf2, 0x1d, 0x1a, 0x31, 0x89, - 0xed, 0x28, 0x38, 0xc5, 0xad, 0xfa, 0xe3, 0xa1, 0xbe, 0x74, 0x39, 0xd4, 0x01, 0x8d, 0x99, 0xfd, - 0xe6, 0x67, 0x1d, 0x26, 0x3c, 0x5b, 0x63, 0xa8, 0x58, 0xba, 0xc2, 0x8c, 0x74, 0x30, 0x23, 0x5d, - 0x71, 0x9e, 0x74, 0x7f, 0xa4, 0xa1, 0xb4, 0x73, 0x46, 0x90, 0xef, 0xd9, 0x7b, 0x18, 0xff, 0x27, - 0xd2, 0xdd, 0x87, 0xa2, 0x90, 0x8e, 0x7b, 0x41, 0xc7, 0x46, 0xc1, 0x5f, 0x8b, 0x27, 0x84, 0x6e, - 0x7b, 0xc1, 0x36, 0x0a, 0x46, 0xa9, 0xc7, 0x18, 0xcb, 0x54, 0xf5, 0xef, 0xa4, 0xee, 0x61, 0x2c, - 0x52, 0x13, 0xe1, 0x33, 0x8b, 0x85, 0xcf, 0x5e, 0x17, 0x3e, 0xf7, 0xcc, 0xc2, 0xe7, 0xe7, 0x08, - 0x5f, 0xf8, 0x97, 0x85, 0x87, 0x19, 0xe1, 0x8b, 0x33, 0xc2, 0x97, 0xe6, 0x09, 0xdf, 0x80, 0xea, - 0xee, 0x80, 0x63, 0xc2, 0x3c, 0x4a, 0xde, 0x0d, 0xe4, 0x38, 0x9e, 0x4c, 0xd9, 0x64, 0xd6, 0x7d, - 0xa1, 0xc0, 0xad, 0x99, 0xe9, 0x6b, 0x61, 0x16, 0x50, 0xc2, 0x64, 0x8b, 0x72, 0x80, 0x2a, 0xf1, - 0x7c, 0x94, 0x33, 0x73, 0x0d, 0xd4, 0x53, 0xea, 0xb2, 0x72, 0x4a, 0xb6, 0xb7, 0x32, 0xdd, 0xde, - 0x3e, 0x75, 0x2d, 0xe9, 0xd4, 0x6e, 0x42, 0x3a, 0xc4, 0x5c, 0x8a, 0x5e, 0xb2, 0xc4, 0x52, 0xab, - 0x40, 0xbe, 0xef, 0x77, 0x70, 0x18, 0xd2, 0x30, 0x99, 0x6d, 0xb9, 0xbe, 0xbf, 0x2b, 0x4c, 0xe1, - 0x12, 0x72, 0x47, 0x0c, 0x3b, 0xb1, 0x70, 0x56, 0xce, 0x45, 0xec, 0x88, 0x61, 0x27, 0x29, 0xf0, - 0x63, 0x05, 0x56, 0x0e, 0x98, 0x7b, 0x14, 0x38, 0x88, 0xe3, 0x43, 0x14, 0x22, 0x9f, 0x89, 0xc9, - 0x80, 0x22, 0xde, 0xa3, 0xa1, 0xc7, 0xcf, 0x92, 0x1b, 0x5c, 0xfe, 0xe1, 0xd1, 0xfa, 0x6a, 0xf2, - 0x78, 0x6d, 0x39, 0x4e, 0x88, 0x19, 0x7b, 0x8f, 0x87, 0x1e, 0x71, 0xad, 0x49, 0xa8, 0x76, 0x17, - 0xb2, 0x81, 0x44, 0x90, 0xb7, 0xb5, 0xb8, 0xa1, 0x4d, 0x37, 0x10, 0x63, 0xb7, 0x54, 0x21, 0x8d, - 0x95, 0xc4, 0x6d, 0x2e, 0x3f, 0xfc, 0xed, 0xdb, 0x57, 0x27, 0x08, 0x8d, 0x0a, 0xdc, 0xbe, 0x52, - 0xcc, 0x88, 0xaf, 0xc6, 0xd7, 0x0a, 0xfc, 0xef, 0x80, 0xb9, 0xdb, 0x21, 0x46, 0x1c, 0xef, 0x45, - 0xa4, 0x4d, 0x4f, 0x30, 0xd1, 0x0e, 0x01, 0xc4, 0xcb, 0xd2, 0xc1, 0xa1, 0xbd, 0x71, 0x37, 0xa9, - 0xf5, 0x9e, 0x38, 0xe2, 0xe9, 0x50, 0x7f, 0xc5, 0xf5, 0x78, 0x2f, 0xea, 0x1a, 0x36, 0xf5, 0xcd, - 0x77, 0xbc, 0xae, 0x17, 0x46, 0xf2, 0x4b, 0x33, 0x89, 0x5c, 0x9b, 0xa2, 0xb6, 0xb7, 0xf0, 0x40, - 0x74, 0x63, 0x15, 0x04, 0xc8, 0xae, 0xc0, 0xd0, 0x5e, 0x86, 0x15, 0x89, 0xd8, 0x45, 0xe4, 0xa4, - 0xe3, 0x60, 0x42, 0xfd, 0xf8, 0x01, 0xb2, 0x6e, 0x88, 0xed, 0x16, 0x22, 0x27, 0x3b, 0x62, 0x53, - 0x7b, 0x0e, 0xb2, 0x0c, 0x13, 0x07, 0x87, 0xf1, 0xe7, 0x67, 0x25, 0x56, 0xa3, 0x0b, 0x95, 0x6b, - 0x65, 0x8e, 0x45, 0xdf, 0x85, 0x9b, 0xc7, 0x11, 0xe1, 0x62, 0xaf, 0xe3, 0xa3, 0x20, 0xf0, 0x88, - 0x3b, 0x7e, 0x86, 0xa7, 0xb8, 0x1a, 0xe5, 0x25, 0x6c, 0xad, 0x8c, 0x72, 0x0e, 0xe2, 0x94, 0x8d, - 0x2f, 0x53, 0x90, 0x3e, 0x60, 0xae, 0x46, 0x00, 0xa6, 0xde, 0xf5, 0xca, 0x34, 0xc4, 0xcc, 0xa5, - 0xab, 0xbe, 0x38, 0xd7, 0x35, 0xe6, 0xb7, 0xf1, 0xf0, 0xc7, 0x5f, 0x3f, 0x4f, 0xdd, 0x69, 0x54, - 0xc7, 0xfc, 0x24, 0x3f, 0x26, 0x49, 0x68, 0x87, 0x0f, 0xb4, 0x43, 0x28, 0xcd, 0x5c, 0x94, 0xe7, - 0xaf, 0xc0, 0x4e, 0x3b, 0xab, 0x6b, 0x0b, 0x9c, 0x63, 0x42, 0xde, 0x87, 0xe5, 0x2b, 0x8a, 0xbe, - 0x70, 0x25, 0x6d, 0xd6, 0x5d, 0x7d, 0x69, 0xa1, 0x7b, 0x84, 0xdb, 0x7a, 0xe3, 0xf1, 0x79, 0x4d, - 0x79, 0x72, 0x5e, 0x53, 0x7e, 0x39, 0xaf, 0x29, 0x9f, 0x5e, 0xd4, 0x96, 0x9e, 0x5c, 0xd4, 0x96, - 0x7e, 0xba, 0xa8, 0x2d, 0x7d, 0xb0, 0xb6, 0xf8, 0x56, 0x0c, 0x44, 0xdf, 0xdd, 0xac, 0xfc, 0x19, - 0x7a, 0xed, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0xf8, 0xd4, 0x86, 0xf7, 0x09, 0x00, 0x00, + // 1239 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6f, 0x1b, 0xc5, + 0x17, 0xcf, 0xda, 0x1b, 0xff, 0x78, 0x76, 0x93, 0x76, 0xbf, 0xe9, 0xb7, 0x6b, 0x53, 0xbc, 0x66, + 0x23, 0x90, 0x41, 0xca, 0x6e, 0x13, 0x24, 0xa4, 0x46, 0xe2, 0x10, 0x27, 0x2e, 0x14, 0x25, 0x10, + 0xb6, 0x2e, 0x07, 0x2e, 0xd6, 0x78, 0x77, 0xb2, 0x5e, 0x25, 0x3b, 0xb3, 0xda, 0x19, 0x5b, 0x0e, + 0x27, 0xd4, 0x13, 0x12, 0x07, 0x40, 0xdc, 0x11, 0x17, 0x2e, 0x9c, 0x38, 0xf4, 0xc0, 0x9f, 0x50, + 0x71, 0xaa, 0xe8, 0x05, 0xf5, 0x60, 0x50, 0x8a, 0x84, 0x94, 0x63, 0x0f, 0x9c, 0xd1, 0xcc, 0xae, + 0x1d, 0x3b, 0x21, 0x29, 0xad, 0x10, 0xb7, 0x79, 0xf3, 0x7e, 0xcc, 0x7b, 0x9f, 0xcf, 0x9b, 0x37, + 0x03, 0xff, 0xc3, 0xbc, 0x67, 0xe3, 0x41, 0x68, 0x0f, 0x56, 0x6d, 0x3e, 0xb4, 0xa2, 0x98, 0x72, + 0xaa, 0x01, 0xe6, 0x3d, 0x0b, 0x0f, 0x42, 0x6b, 0xb0, 0x5a, 0xbd, 0xe6, 0x52, 0x16, 0x52, 0x66, + 0x87, 0xcc, 0x17, 0x36, 0x21, 0xf3, 0x13, 0xa3, 0x6a, 0x2d, 0x55, 0x74, 0x11, 0xc3, 0xf6, 0x60, + 0xb5, 0x8b, 0x39, 0x5a, 0xb5, 0x5d, 0x1a, 0x90, 0x54, 0x5f, 0x49, 0xf4, 0x1d, 0x29, 0xd9, 0x89, + 0x90, 0xaa, 0x96, 0xa6, 0x0e, 0x15, 0xc7, 0xa4, 0xbb, 0x3e, 0xf5, 0x69, 0x62, 0x2d, 0x56, 0xe9, + 0xee, 0x75, 0x9f, 0x52, 0xff, 0x00, 0xdb, 0x28, 0x0a, 0x6c, 0x44, 0x08, 0xe5, 0x88, 0x07, 0x94, + 0x8c, 0x23, 0x55, 0x52, 0xad, 0x94, 0xba, 0xfd, 0x3d, 0x1b, 0x91, 0xc3, 0x44, 0x65, 0x7e, 0xa1, + 0xc0, 0xa5, 0x1d, 0xe6, 0xb7, 0x78, 0x0f, 0xc7, 0xb8, 0x1f, 0xb6, 0x87, 0x5a, 0x03, 0x54, 0x0f, + 0x71, 0xa4, 0x2b, 0x75, 0xa5, 0x51, 0x5a, 0x5b, 0xb2, 0x12, 0x5f, 0x6b, 0xec, 0x6b, 0x6d, 0x90, + 0x43, 0x47, 0x5a, 0x68, 0x15, 0x50, 0x59, 0xf0, 0x09, 0xd6, 0x33, 0x75, 0xa5, 0xa1, 0x34, 0xe7, + 0x8f, 0x47, 0x86, 0xb2, 0xe2, 0xc8, 0x2d, 0xcd, 0x00, 0xb5, 0x87, 0x58, 0x4f, 0xcf, 0xd6, 0x95, + 0x46, 0xb1, 0x59, 0x7a, 0x3a, 0x32, 0xf2, 0xf1, 0x41, 0xb4, 0x6e, 0xae, 0x98, 0x8e, 0x54, 0x68, + 0x1a, 0xa8, 0x7b, 0x31, 0x0d, 0x75, 0x55, 0x18, 0x38, 0x72, 0xbd, 0xae, 0x7e, 0xf6, 0xad, 0x31, + 0x67, 0x7e, 0x95, 0x81, 0xc2, 0x36, 0xf6, 0x91, 0x7b, 0xd8, 0x1e, 0x6a, 0x4b, 0x30, 0x4f, 0x28, + 0x71, 0xb1, 0xcc, 0x46, 0x75, 0x12, 0x41, 0x7b, 0x0b, 0x8a, 0x3e, 0x12, 0x98, 0x05, 0x6e, 0x72, + 0x7a, 0xb1, 0x59, 0x79, 0x3c, 0x32, 0xae, 0x26, 0xf0, 0x31, 0x6f, 0xdf, 0x0a, 0xa8, 0x1d, 0x22, + 0xde, 0xb3, 0x6e, 0x13, 0xee, 0x14, 0x7c, 0xc4, 0x76, 0x85, 0xa9, 0x56, 0x83, 0xac, 0x8f, 0x98, + 0x4c, 0x4a, 0x6d, 0x96, 0x8f, 0x46, 0x46, 0xe1, 0x1d, 0xc4, 0xb6, 0x83, 0x30, 0xe0, 0x8e, 0x50, + 0x68, 0x0b, 0x90, 0xe1, 0x34, 0x4d, 0x29, 0xc3, 0xa9, 0x76, 0x13, 0xe6, 0x07, 0xe8, 0xa0, 0x8f, + 0xf5, 0x79, 0x79, 0xc6, 0xf2, 0xb9, 0x67, 0x1c, 0x8d, 0x8c, 0xdc, 0x46, 0x48, 0xfb, 0x84, 0x3b, + 0x89, 0x87, 0xa8, 0x4f, 0xa2, 0x98, 0xab, 0x2b, 0x8d, 0x72, 0x8a, 0x57, 0x19, 0x94, 0x81, 0x9e, + 0x97, 0x1b, 0xca, 0x40, 0x48, 0xb1, 0x5e, 0x48, 0xa4, 0x58, 0x48, 0x4c, 0x2f, 0x26, 0x12, 0x5b, + 0x5f, 0x10, 0x48, 0xfc, 0x74, 0x7f, 0x25, 0xd7, 0x1e, 0x6e, 0x21, 0x8e, 0xcc, 0x1f, 0xb3, 0x50, + 0xde, 0x70, 0x5d, 0xcc, 0xd8, 0x76, 0xc0, 0x78, 0x7b, 0xa8, 0xbd, 0x07, 0x05, 0xb7, 0x87, 0x02, + 0xd2, 0x09, 0x3c, 0x09, 0x4d, 0xb1, 0x69, 0x5f, 0x94, 0x5c, 0x7e, 0x53, 0x18, 0xdf, 0xde, 0x3a, + 0x1e, 0x19, 0x79, 0x37, 0x59, 0x3a, 0xe9, 0xc2, 0x3b, 0xc1, 0x38, 0x73, 0x2e, 0xc6, 0xd9, 0xe7, + 0xc6, 0x58, 0xbd, 0x18, 0xe3, 0xf9, 0xb3, 0x18, 0xe7, 0x5e, 0x18, 0xe3, 0xfc, 0x14, 0xc6, 0x77, + 0xa1, 0x80, 0x24, 0x50, 0x98, 0xe9, 0x85, 0x7a, 0xb6, 0x51, 0x5a, 0xbb, 0x66, 0x9d, 0xdc, 0x53, + 0x2b, 0x01, 0xb1, 0xdd, 0x8f, 0x0e, 0x70, 0xb3, 0xfe, 0x60, 0x64, 0xcc, 0x1d, 0x8f, 0x0c, 0x40, + 0x13, 0x64, 0xbf, 0xff, 0xd5, 0x80, 0x13, 0x9c, 0x9d, 0x49, 0xa8, 0x84, 0xba, 0xe2, 0x0c, 0x75, + 0x30, 0x43, 0x5d, 0xe9, 0x3c, 0xea, 0xfe, 0xcc, 0x42, 0x79, 0xeb, 0x90, 0xa0, 0x30, 0x70, 0x6f, + 0x61, 0xfc, 0x9f, 0x50, 0x77, 0x13, 0x4a, 0x82, 0x3a, 0x1e, 0x44, 0x1d, 0x17, 0x45, 0xcf, 0x26, + 0x4f, 0x10, 0xdd, 0x0e, 0xa2, 0x4d, 0x14, 0x8d, 0x5d, 0xf7, 0x30, 0x96, 0xae, 0xea, 0x3f, 0x71, + 0xbd, 0x85, 0xb1, 0x70, 0x4d, 0x89, 0x9f, 0xbf, 0x98, 0xf8, 0xdc, 0x59, 0xe2, 0xf3, 0x2f, 0x4c, + 0x7c, 0xe1, 0x1c, 0xe2, 0x8b, 0xff, 0x32, 0xf1, 0x30, 0x43, 0x7c, 0x69, 0x86, 0xf8, 0xf2, 0x79, + 0xc4, 0x9b, 0x50, 0x6d, 0x0d, 0x39, 0x26, 0x2c, 0xa0, 0xe4, 0x83, 0x48, 0x8e, 0xe3, 0x93, 0x29, + 0x9b, 0xce, 0xba, 0x6f, 0x14, 0xb8, 0x3a, 0x33, 0x7d, 0x1d, 0xcc, 0x22, 0x4a, 0x98, 0x2c, 0x51, + 0x0e, 0x50, 0x25, 0x99, 0x8f, 0x72, 0x66, 0x2e, 0x83, 0x7a, 0x40, 0x7d, 0xa6, 0x67, 0x64, 0x79, + 0x8b, 0xd3, 0xe5, 0x6d, 0x53, 0xdf, 0x91, 0x4a, 0xed, 0x32, 0x64, 0x63, 0xcc, 0x25, 0xe9, 0x65, + 0x47, 0x2c, 0xb5, 0x0a, 0x14, 0x06, 0x61, 0x07, 0xc7, 0x31, 0x8d, 0xd3, 0xd9, 0x96, 0x1f, 0x84, + 0x2d, 0x21, 0x0a, 0x95, 0xa0, 0xbb, 0xcf, 0xb0, 0x97, 0x10, 0xe7, 0xe4, 0x7d, 0xc4, 0xee, 0x32, + 0xec, 0xa5, 0x09, 0x7e, 0xae, 0xc0, 0xe2, 0x0e, 0xf3, 0xef, 0x46, 0x1e, 0xe2, 0x78, 0x17, 0xc5, + 0x28, 0x64, 0x62, 0x32, 0xa0, 0x3e, 0xef, 0xd1, 0x38, 0xe0, 0x87, 0x69, 0x07, 0xeb, 0x3f, 0xdf, + 0x5f, 0x59, 0x4a, 0x1f, 0xaf, 0x0d, 0xcf, 0x8b, 0x31, 0x63, 0x77, 0x78, 0x1c, 0x10, 0xdf, 0x39, + 0x31, 0xd5, 0x6e, 0x40, 0x2e, 0x92, 0x11, 0x64, 0xb7, 0x96, 0xd6, 0xb4, 0xe9, 0x02, 0x92, 0xd8, + 0x4d, 0x55, 0x50, 0xe3, 0xa4, 0x76, 0xeb, 0x0b, 0xf7, 0xfe, 0xf8, 0xe1, 0x8d, 0x93, 0x08, 0x66, + 0x05, 0xae, 0x9d, 0x4a, 0x66, 0x8c, 0x97, 0xf9, 0x9d, 0x02, 0x57, 0x76, 0x98, 0xbf, 0x19, 0x63, + 0xc4, 0xf1, 0xad, 0x3e, 0x69, 0xd3, 0x7d, 0x4c, 0xb4, 0x5d, 0x00, 0xf1, 0xb2, 0x74, 0x70, 0xec, + 0xae, 0xdd, 0x48, 0x73, 0x5d, 0x7d, 0x30, 0x32, 0x94, 0xc7, 0x23, 0xe3, 0x75, 0x3f, 0xe0, 0xbd, + 0x7e, 0xd7, 0x72, 0x69, 0x68, 0xbf, 0x1f, 0x74, 0x83, 0xb8, 0x2f, 0x6f, 0x9a, 0x4d, 0xe4, 0xda, + 0x16, 0xb9, 0xbd, 0x8b, 0x87, 0xa2, 0x1a, 0xa7, 0x28, 0x82, 0xb4, 0x44, 0x0c, 0xed, 0x35, 0x58, + 0x94, 0x11, 0xbb, 0x88, 0xec, 0x77, 0x3c, 0x4c, 0x68, 0x98, 0x3c, 0x40, 0xce, 0x25, 0xb1, 0xdd, + 0x44, 0x64, 0x7f, 0x4b, 0x6c, 0x6a, 0xff, 0x87, 0x1c, 0xc3, 0xc4, 0xc3, 0x71, 0x72, 0xfd, 0x9c, + 0x54, 0x32, 0xbb, 0x50, 0x39, 0x93, 0xe6, 0x84, 0xf4, 0x16, 0x5c, 0xde, 0xeb, 0x13, 0x2e, 0xf6, + 0x3a, 0x21, 0x8a, 0xa2, 0x80, 0xf8, 0x93, 0x67, 0x78, 0x0a, 0xab, 0xb1, 0x5f, 0x8a, 0xd6, 0xe2, + 0xd8, 0x67, 0x27, 0x71, 0x31, 0x1f, 0x29, 0xb0, 0xb4, 0xc3, 0xfc, 0x3b, 0x98, 0x78, 0x63, 0xd3, + 0x36, 0x6d, 0x0d, 0x42, 0xed, 0x43, 0x28, 0x71, 0xda, 0xc1, 0xbc, 0xd7, 0x41, 0x9e, 0x17, 0x4f, + 0xe1, 0x31, 0xf7, 0x9c, 0x78, 0x70, 0xda, 0xe2, 0x3d, 0xb1, 0x9c, 0xaa, 0x33, 0x33, 0x5d, 0xa7, + 0xb6, 0x0b, 0x45, 0x09, 0x91, 0xf8, 0xea, 0x48, 0x08, 0x4a, 0x6b, 0x15, 0x2b, 0xed, 0x10, 0xf1, + 0x17, 0xb2, 0xd2, 0xbf, 0x90, 0xb5, 0x49, 0x03, 0xd2, 0xd4, 0x45, 0x0e, 0x4f, 0x47, 0xc6, 0xe5, + 0x43, 0x14, 0x1e, 0xac, 0x9b, 0x13, 0x4f, 0xd3, 0x29, 0x88, 0xb5, 0xb0, 0x31, 0x6b, 0x70, 0xfd, + 0xef, 0x8a, 0x1a, 0x83, 0xb7, 0xf6, 0x69, 0x16, 0xb2, 0x3b, 0xcc, 0xd7, 0x08, 0xc0, 0xd4, 0x6f, + 0xa6, 0x32, 0x0d, 0xdc, 0xcc, 0x55, 0xab, 0xbe, 0x72, 0xae, 0x6a, 0xd2, 0x55, 0xe6, 0xbd, 0x47, + 0xbf, 0x7f, 0x9d, 0xb9, 0x6e, 0x56, 0x27, 0x28, 0xa4, 0xdf, 0xb1, 0xd4, 0xb4, 0xc3, 0x87, 0xda, + 0x2e, 0x94, 0x67, 0xae, 0xc7, 0x4b, 0xa7, 0xc2, 0x4e, 0x2b, 0xab, 0xcb, 0x17, 0x28, 0x27, 0x6d, + 0xf0, 0x11, 0x2c, 0x9c, 0xea, 0xe3, 0x97, 0x4f, 0xb9, 0xcd, 0xaa, 0xab, 0xaf, 0x5e, 0xa8, 0x9e, + 0xc4, 0xed, 0xc0, 0x95, 0xb3, 0x3d, 0x51, 0x3f, 0xe5, 0x7b, 0xc6, 0xa2, 0xda, 0x78, 0x96, 0xc5, + 0xf8, 0x80, 0xe6, 0xdb, 0x0f, 0x8e, 0x6a, 0xca, 0xc3, 0xa3, 0x9a, 0xf2, 0xdb, 0x51, 0x4d, 0xf9, + 0xf2, 0x49, 0x6d, 0xee, 0xe1, 0x93, 0xda, 0xdc, 0x2f, 0x4f, 0x6a, 0x73, 0x1f, 0x2f, 0x5f, 0xdc, + 0x5c, 0x43, 0x01, 0x6c, 0x37, 0x27, 0xff, 0x98, 0x6f, 0xfe, 0x15, 0x00, 0x00, 0xff, 0xff, 0x5d, + 0xb8, 0xdf, 0xf4, 0x6e, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -654,6 +759,10 @@ type MsgClient interface { // address can be given to create the mapping to a bank coin, or the // denomination for a bank coin can be given to create the mapping to an ERC20. CreateFunToken(ctx context.Context, in *MsgCreateFunToken, opts ...grpc.CallOption) (*MsgCreateFunTokenResponse, error) + // SendFunTokenToEvm: Sends a coin with a valid "FunToken" mapping to the + // given recipient address ("to_eth_addr") in the corresponding ERC20 + // representation. + SendFunTokenToEvm(ctx context.Context, in *MsgSendFunTokenToEvm, opts ...grpc.CallOption) (*MsgSendFunTokenToEvmResponse, error) } type msgClient struct { @@ -691,6 +800,15 @@ func (c *msgClient) CreateFunToken(ctx context.Context, in *MsgCreateFunToken, o return out, nil } +func (c *msgClient) SendFunTokenToEvm(ctx context.Context, in *MsgSendFunTokenToEvm, opts ...grpc.CallOption) (*MsgSendFunTokenToEvmResponse, error) { + out := new(MsgSendFunTokenToEvmResponse) + err := c.cc.Invoke(ctx, "/eth.evm.v1.Msg/SendFunTokenToEvm", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // EthereumTx defines a method submitting Ethereum transactions. @@ -702,6 +820,10 @@ type MsgServer interface { // address can be given to create the mapping to a bank coin, or the // denomination for a bank coin can be given to create the mapping to an ERC20. CreateFunToken(context.Context, *MsgCreateFunToken) (*MsgCreateFunTokenResponse, error) + // SendFunTokenToEvm: Sends a coin with a valid "FunToken" mapping to the + // given recipient address ("to_eth_addr") in the corresponding ERC20 + // representation. + SendFunTokenToEvm(context.Context, *MsgSendFunTokenToEvm) (*MsgSendFunTokenToEvmResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -717,6 +839,9 @@ func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateP func (*UnimplementedMsgServer) CreateFunToken(ctx context.Context, req *MsgCreateFunToken) (*MsgCreateFunTokenResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateFunToken not implemented") } +func (*UnimplementedMsgServer) SendFunTokenToEvm(ctx context.Context, req *MsgSendFunTokenToEvm) (*MsgSendFunTokenToEvmResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SendFunTokenToEvm not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -776,6 +901,24 @@ func _Msg_CreateFunToken_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Msg_SendFunTokenToEvm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSendFunTokenToEvm) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SendFunTokenToEvm(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/eth.evm.v1.Msg/SendFunTokenToEvm", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SendFunTokenToEvm(ctx, req.(*MsgSendFunTokenToEvm)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "eth.evm.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -792,6 +935,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "CreateFunToken", Handler: _Msg_CreateFunToken_Handler, }, + { + MethodName: "SendFunTokenToEvm", + Handler: _Msg_SendFunTokenToEvm_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "eth/evm/v1/tx.proto", @@ -1375,12 +1522,47 @@ func (m *MsgCreateFunToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } + if m.FromErc20 != nil { + { + size := m.FromErc20.Size() + i -= size + if _, err := m.FromErc20.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateFunTokenResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateFunTokenResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateFunTokenResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l { - size := m.FromErc20.Size() - i -= size - if _, err := m.FromErc20.MarshalTo(dAtA[i:]); err != nil { + size, err := m.FuntokenMapping.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { return 0, err } + i -= size i = encodeVarintTx(dAtA, i, uint64(size)) } i-- @@ -1388,7 +1570,7 @@ func (m *MsgCreateFunToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *MsgCreateFunTokenResponse) Marshal() (dAtA []byte, err error) { +func (m *MsgSendFunTokenToEvm) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1398,18 +1580,18 @@ func (m *MsgCreateFunTokenResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *MsgCreateFunTokenResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *MsgSendFunTokenToEvm) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *MsgCreateFunTokenResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *MsgSendFunTokenToEvm) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l { - size, err := m.FuntokenMapping.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.BankCoin.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -1417,10 +1599,50 @@ func (m *MsgCreateFunTokenResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro i = encodeVarintTx(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x1a + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + { + size := m.ToEthAddr.Size() + i -= size + if _, err := m.ToEthAddr.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0xa return len(dAtA) - i, nil } +func (m *MsgSendFunTokenToEvmResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgSendFunTokenToEvmResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSendFunTokenToEvmResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1678,8 +1900,10 @@ func (m *MsgCreateFunToken) Size() (n int) { } var l int _ = l - l = m.FromErc20.Size() - n += 1 + l + sovTx(uint64(l)) + if m.FromErc20 != nil { + l = m.FromErc20.Size() + n += 1 + l + sovTx(uint64(l)) + } l = len(m.FromBankDenom) if l > 0 { n += 1 + l + sovTx(uint64(l)) @@ -1702,6 +1926,32 @@ func (m *MsgCreateFunTokenResponse) Size() (n int) { return n } +func (m *MsgSendFunTokenToEvm) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ToEthAddr.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.BankCoin.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgSendFunTokenToEvmResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -3504,6 +3754,8 @@ func (m *MsgCreateFunToken) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var v github_com_NibiruChain_nibiru_eth.HexAddr + m.FromErc20 = &v if err := m.FromErc20.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -3676,6 +3928,205 @@ func (m *MsgCreateFunTokenResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgSendFunTokenToEvm) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSendFunTokenToEvm: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSendFunTokenToEvm: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToEthAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ToEthAddr.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BankCoin", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BankCoin.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSendFunTokenToEvmResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgSendFunTokenToEvmResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSendFunTokenToEvmResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0