From 53c10bb849594742032ab556bbf1c9360e4fbb54 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 10 Jun 2024 12:32:58 -0500 Subject: [PATCH 1/7] 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 --- e2e/evm/test/contract_send_nibi.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/e2e/evm/test/contract_send_nibi.test.ts b/e2e/evm/test/contract_send_nibi.test.ts index 75d368846..bbbe78b88 100644 --- a/e2e/evm/test/contract_send_nibi.test.ts +++ b/e2e/evm/test/contract_send_nibi.test.ts @@ -1,10 +1,9 @@ -import { describe, it, expect, beforeAll } from "bun:test" // eslint-disable-line import/no-unresolved -import { AddressLike, ethers } from "ethers" +import { describe, it, expect } from "bun:test" // eslint-disable-line import/no-unresolved +import { ethers } from "ethers" import { account, provider, deployContract } from "./setup" import { SendNibiCompiled } from "../types/ethers-contracts" -import { TypedContractMethod } from "../types/ethers-contracts/common" -type SendMethod = TypedContractMethod<[_to: AddressLike], [void], "payable"> +type SendMethod = SendNibiCompiled["sendViaCall"] const doContractSend = async (sendMethod: SendMethod) => { const recipientAddress = ethers.Wallet.createRandom().address From d65dfaf88ff5881a585a7534b480656fe40d0a1d Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 24 Jun 2024 12:03:13 -0500 Subject: [PATCH 2/7] wip!: save progress --- eth/hex.go | 60 +++++ eth/hex_test.go | 174 ++++++++++++++ eth/state_encoder.go | 12 +- proto/eth/evm/v1/evm.proto | 17 ++ proto/eth/evm/v1/genesis.proto | 4 + x/evm/access_list_test.go | 1 + x/evm/const.go | 7 + x/evm/events.go | 18 +- x/evm/evm.go | 70 ++++++ x/evm/evm.pb.go | 423 +++++++++++++++++++++++++++------ x/evm/evm_test.go | 100 ++++++++ x/evm/genesis.pb.go | 105 ++++++-- x/evm/keeper/evm_state.go | 2 +- x/evm/keeper/funtoken_state.go | 84 +++++++ x/evm/keeper/keeper.go | 7 + x/evm/query_test.go | 58 ----- 16 files changed, 972 insertions(+), 170 deletions(-) create mode 100644 eth/hex.go create mode 100644 eth/hex_test.go create mode 100644 x/evm/evm.go create mode 100644 x/evm/evm_test.go create mode 100644 x/evm/keeper/funtoken_state.go delete mode 100644 x/evm/query_test.go diff --git a/eth/hex.go b/eth/hex.go new file mode 100644 index 000000000..594d411e6 --- /dev/null +++ b/eth/hex.go @@ -0,0 +1,60 @@ +package eth + +import ( + "fmt" + + gethcommon "github.com/ethereum/go-ethereum/common" +) + +/////////// HexAddr + +// TODO: UD-DEBUG: The eth.Addr should map to only one HexString +// TODO: UD-DEBUG: The eth.Addr should be derivable from HexString +// TODO: Constructor should be safe (errorable) +// TODO: UD-DEBUG: HexString -> bytes -> eth.Addr == HexString -> eth.Addr +// TODO: UD-DEBUG: validate: HexString === HexString -> HexString(eth.Addr.Hex()) + +// HexAddr: An ERC55-comlpiant hexadecimal-encoded string representing the 20 +// byte address of an Ethereum account. +type HexAddr string + +func NewHexAddr(addr EthAddr) HexAddr { + return HexAddr(addr.Hex()) +} + +const HexAddrError = "HexAddrError" + +func (h HexAddr) Valid() error { + // Check address encoding bijectivity + wantAddr := h.ToAddr().Hex() // gethcommon.Address.Hex() + haveAddr := string(h) // should be equivalent to ↑ + + if !gethcommon.IsHexAddress(haveAddr) || haveAddr != wantAddr { + return fmt.Errorf( + "%s: Etherem address is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", + HexAddrError, haveAddr, wantAddr, + ) + } + + return nil +} + +func NewHexAddrFromStr(addr string) HexAddr { + return HexAddr(gethcommon.HexToAddress(addr).Hex()) +} + +func (h HexAddr) ToAddr() EthAddr { + return gethcommon.HexToAddress(string(h)) +} + +// func (h HexAddr) Bytes() []byte { +// return gethcommon.Hex2Bytes( +// strings.TrimPrefix(string(h), "0x"), +// ) +// } + +func (h HexAddr) String() string { return h.ToAddr().Hex() } + +func (h HexAddr) FromBytes(bz []byte) HexAddr { + return HexAddr(gethcommon.BytesToAddress(bz).Hex()) +} diff --git a/eth/hex_test.go b/eth/hex_test.go new file mode 100644 index 000000000..6d07ade07 --- /dev/null +++ b/eth/hex_test.go @@ -0,0 +1,174 @@ +package eth_test + +import ( + "fmt" + + "github.com/NibiruChain/nibiru/eth" + "github.com/ethereum/go-ethereum/common" +) + +var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ + eth.HexAddr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), + eth.HexAddr("0xAe967917c465db8578ca9024c205720b1a3651A9"), + eth.HexAddr("0x1111111111111111111112222222222223333323"), +} + +// TestHexAddr_NewHexAddr: Test to showcase the flexibility of inputs that can be +// passed to `eth.NewHexAddrFromStr` and result in a "valid" `HexAddr` that preserves +// bijectivity with `gethcommon.Address` and has a canonical string +// representation. +// +// We only want to store valid `HexAddr` strings in state. Hex addresses that +// include or remove the prefix, or change the letters to and from lower and +// upper case will all produce the same `HexAddr` when passed to +// `eth.NewHexAddrFromStr`. +func (s *Suite) TestHexAddr_NewHexAddr() { + + // InputAddrVariation: An instance of a "hexAddr" that derives to the + // expected Ethereum address and results in the same string representation. + type InputAddrVariation struct { + hexAddr string + testCaseName string + wantNotEqual bool + } + + for _, tcGroup := range []struct { + want eth.HexAddr + hexAddrs []InputAddrVariation + }{ + { + want: threeValidAddrs[0], + hexAddrs: []InputAddrVariation{ + { + hexAddr: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + testCaseName: "happy: no-op (sanity check to show constructor doesn't break a valid input)", + }, + { + hexAddr: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + testCaseName: "happy: lower case is valid", + }, + { + hexAddr: "0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED", + testCaseName: "happy: upper case is valid", + }, + { + hexAddr: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + testCaseName: "happy: 0x prefix: missing", + }, + { + hexAddr: "nibi1zaa12312312aacbcbeabea123", + testCaseName: "sad: bech32 is not hex", + wantNotEqual: true, + }, + }, + }, + { + want: threeValidAddrs[1], + hexAddrs: []InputAddrVariation{ + { + hexAddr: "0XAe967917c465db8578ca9024c205720b1a3651A9", + testCaseName: "happy: 0x prefix: typo", + }, + { + hexAddr: "0xae967917c465db8578ca9024c205720b1a3651A9", + testCaseName: "happy: mixed case checksum not valid according to ERC55", + }, + { + hexAddr: "not-a-hex-addr", + testCaseName: "sad: sanity check: clearly not a hex addr", + wantNotEqual: true, + }, + }, + }, + { + want: threeValidAddrs[2], + hexAddrs: []InputAddrVariation{ + { + hexAddr: "0x1111111111111111111112222222222223333323", + testCaseName: "happy", + }, + }, + }, + } { + + want := tcGroup.want + for _, tc := range tcGroup.hexAddrs { + tcName := fmt.Sprintf("want %s, %s", want, tc.testCaseName) + s.Run(tcName, func() { + got := eth.NewHexAddrFromStr(tc.hexAddr) + err := got.Valid() + + // gethcommon.Address input should give the same thing + got2 := eth.NewHexAddr(common.HexToAddress(tc.hexAddr)) + if tc.wantNotEqual { + s.NotEqual(want, got) + s.NotEqual(want.ToAddr(), got.ToAddr()) + s.NotEqual(want, got2) + s.NotEqual(want.ToAddr(), got2.ToAddr()) + } else { + // string input should give the canonical HexAddr + s.Equal(want, got) + s.Equal(want.ToAddr(), got.ToAddr()) + + // gethcommon.Address input should give the same thing + got2 := eth.NewHexAddr(common.HexToAddress(tc.hexAddr)) + s.Equal(want, got2) + s.Equal(want.ToAddr(), got2.ToAddr()) + } + + s.Require().NoError(err) + }) + } + } +} + +// TestHexAddr_Valid: Test that demonstrates +func (s *Suite) TestHexAddr_Valid() { + for _, tc := range []struct { + name string + hexAddr string + wantErr string + }{ + { + name: "happy 0", + hexAddr: threeValidAddrs[0].String(), + }, + { + name: "happy 1", + hexAddr: threeValidAddrs[1].String(), + }, + { + name: "happy 2", + hexAddr: threeValidAddrs[2].String(), + }, + { + name: "0x prefix: missing", + hexAddr: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + wantErr: eth.HexAddrError, + }, + { + name: "0x prefix: typo", + hexAddr: "0XAe967917c465db8578ca9024c205720b1a3651A9", + wantErr: eth.HexAddrError, + }, + { + name: "mixed case checksum not valid according to ERC55", + hexAddr: "0xae967917c465db8578ca9024c205720b1a3651A9", + wantErr: eth.HexAddrError, + }, + { + name: "sad 1", + hexAddr: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + wantErr: eth.HexAddrError, + }, + } { + s.Run(tc.name, func() { + err := eth.HexAddr(tc.hexAddr).Valid() + if tc.wantErr != "" { + s.Require().ErrorContains(err, tc.wantErr) + return + } + s.Require().NoError(err) + }) + } +} diff --git a/eth/state_encoder.go b/eth/state_encoder.go index 4c329b029..205ab7097 100644 --- a/eth/state_encoder.go +++ b/eth/state_encoder.go @@ -4,7 +4,7 @@ import ( fmt "fmt" "github.com/NibiruChain/collections" - ethcommon "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" ) // BytesToHex converts a byte array to a hexadecimal string @@ -13,10 +13,10 @@ func BytesToHex(bz []byte) string { } // EthAddr: (alias) 20 byte address of an Ethereum account. -type EthAddr = ethcommon.Address +type EthAddr = gethcommon.Address // EthHash: (alias) 32 byte Keccak256 hash of arbitrary data. -type EthHash = ethcommon.Hash //revive:disable-line:exported +type EthHash = gethcommon.Hash //revive:disable-line:exported var ( // Implements a `collections.ValueEncoder` for the `[]byte` type @@ -44,7 +44,7 @@ func (_ veBytes) Name() string { return "[]byte" } type veEthAddr struct{} func (_ veEthAddr) Encode(value EthAddr) []byte { return value.Bytes() } -func (_ veEthAddr) Decode(bz []byte) EthAddr { return ethcommon.BytesToAddress(bz) } +func (_ veEthAddr) Decode(bz []byte) EthAddr { return gethcommon.BytesToAddress(bz) } func (_ veEthAddr) Stringify(value EthAddr) string { return value.Hex() } func (_ veEthAddr) Name() string { return "EthAddr" } @@ -65,7 +65,7 @@ type keEthAddr struct{} func (_ keEthAddr) Encode(value EthAddr) []byte { return value.Bytes() } func (_ keEthAddr) Decode(bz []byte) (int, EthAddr) { - return ethcommon.AddressLength, ethcommon.BytesToAddress(bz) + return gethcommon.AddressLength, gethcommon.BytesToAddress(bz) } func (_ keEthAddr) Stringify(value EthAddr) string { return value.Hex() } @@ -74,6 +74,6 @@ type keEthHash struct{} func (_ keEthHash) Encode(value EthHash) []byte { return value.Bytes() } func (_ keEthHash) Decode(bz []byte) (int, EthHash) { - return ethcommon.HashLength, ethcommon.BytesToHash(bz) + return gethcommon.HashLength, gethcommon.BytesToHash(bz) } func (_ keEthHash) Stringify(value EthHash) string { return value.Hex() } diff --git a/proto/eth/evm/v1/evm.proto b/proto/eth/evm/v1/evm.proto index ed822a175..aa961cbf9 100644 --- a/proto/eth/evm/v1/evm.proto +++ b/proto/eth/evm/v1/evm.proto @@ -6,6 +6,23 @@ import "gogoproto/gogo.proto"; option go_package = "github.com/NibiruChain/nibiru/x/evm"; +// FunToken is a fungible token mapping between a bank coin and a corresponding +// ERC-20 smart contract. Bank coins here refer to tokens like NIBI, IBC +// coins (ICS-20), and token factory coins, which are each represented by the +// "Coin" type in Golang. +message FunToken { + // Hexadecimal address of the ERC20 token to which the `FunToken` maps + string erc20_addr = 1; + + // bank_denom: Coin denomination in the Bank Module. + string bank_denom = 2; + + // True if the `FunToken` mapping was created from an existing bank coin and + // the ERC-20 contract gets deployed by the module account. False if the + // mapping was created from an externally owned ERC-20 contract. + bool is_made_from_coin = 3; +} + // Params defines the EVM module parameters message Params { option (gogoproto.equal) = true; diff --git a/proto/eth/evm/v1/genesis.proto b/proto/eth/evm/v1/genesis.proto index a0a59a248..384fdfa5b 100644 --- a/proto/eth/evm/v1/genesis.proto +++ b/proto/eth/evm/v1/genesis.proto @@ -11,8 +11,12 @@ option go_package = "github.com/NibiruChain/nibiru/x/evm"; message GenesisState { // accounts is an array containing the ethereum genesis accounts. repeated GenesisAccount accounts = 1 [(gogoproto.nullable) = false]; + // params defines all the parameters of the module. Params params = 2 [(gogoproto.nullable) = false]; + + // Fungible token mappings corresponding to ERC-20 smart contract tokens. + repeated eth.evm.v1.FunToken funtoken_mappings = 3 [(gogoproto.nullable) = false]; } // GenesisAccount defines an account to be initialized in the genesis state. diff --git a/x/evm/access_list_test.go b/x/evm/access_list_test.go index c66de410b..b3c8df00f 100644 --- a/x/evm/access_list_test.go +++ b/x/evm/access_list_test.go @@ -1,3 +1,4 @@ +// Copyright (c) 2023-2024 Nibi, Inc. package evm_test import ( diff --git a/x/evm/const.go b/x/evm/const.go index 7188b4209..aaf521983 100644 --- a/x/evm/const.go +++ b/x/evm/const.go @@ -28,6 +28,13 @@ const ( KeyPrefixAccState KeyPrefixParams KeyPrefixEthAddrIndex + + // KV store prefix for `FunToken` mappings + KeyPrefixFunTokens + // KV store prefix for indexing `FunToken` by ERC-20 address + KeyPrefixFunTokenIdxErc20 + // KV store prefix for indexing `FunToken` by bank coin denomination + KeyPrefixFunTokenIdxBankDenom ) // KVStore transient prefix namespaces for the EVM Module. Transient stores only diff --git a/x/evm/events.go b/x/evm/events.go index 3b89eac17..3bf3dad0a 100644 --- a/x/evm/events.go +++ b/x/evm/events.go @@ -7,19 +7,15 @@ const ( EventTypeBlockBloom = "block_bloom" EventTypeTxLog = "tx_log" - AttributeKeyContractAddress = "contract" - AttributeKeyRecipient = "recipient" - AttributeKeyTxHash = "txHash" - AttributeKeyEthereumTxHash = "ethereumTxHash" - AttributeKeyTxIndex = "txIndex" - AttributeKeyTxGasUsed = "txGasUsed" - AttributeKeyTxType = "txType" - AttributeKeyTxLog = "txLog" + AttributeKeyRecipient = "recipient" + AttributeKeyTxHash = "txHash" + AttributeKeyEthereumTxHash = "ethereumTxHash" + AttributeKeyTxIndex = "txIndex" + AttributeKeyTxGasUsed = "txGasUsed" + AttributeKeyTxType = "txType" + AttributeKeyTxLog = "txLog" // tx failed in eth vm execution AttributeKeyEthereumTxFailed = "ethereumTxFailed" AttributeValueCategory = ModuleName AttributeKeyEthereumBloom = "bloom" - - MetricKeyTransitionDB = "transition_db" - MetricKeyStaticCall = "static_call" ) diff --git a/x/evm/evm.go b/x/evm/evm.go new file mode 100644 index 000000000..99973ef7e --- /dev/null +++ b/x/evm/evm.go @@ -0,0 +1,70 @@ +// Copyright (c) 2023-2024 Nibi, Inc. +package evm + +import ( + "fmt" + + "github.com/cometbft/cometbft/crypto/tmhash" + sdk "github.com/cosmos/cosmos-sdk/types" + gethcommon "github.com/ethereum/go-ethereum/common" +) + +// FIXME: Explore problems arrising from ERC1155 creating multiple fungible +// tokens that are valid ERC20s with the same address. +// https://github.com/NibiruChain/nibiru/issues/1933 +func (fun FunToken) ID() []byte { + return newFunTokenIDFromStr(fun.Erc20Addr, fun.BankDenom) +} + +func NewFunTokenID(erc20 gethcommon.Address, bankDenom string) []byte { + erc20Addr := erc20.Hex() + return newFunTokenIDFromStr(erc20Addr, bankDenom) +} + +func newFunTokenIDFromStr(erc20AddrHex string, bankDenom string) []byte { + return tmhash.Sum([]byte(erc20AddrHex + "|" + bankDenom)) +} + +func errValidateFunToken(errMsg string) error { + return fmt.Errorf("FunTokenError: %s", errMsg) +} + +func (fun FunToken) Validate() error { + if err := sdk.ValidateDenom(fun.BankDenom); err != nil { + return errValidateFunToken(err.Error()) + } + + if !gethcommon.IsHexAddress(fun.Erc20Addr) { + return errValidateFunToken( + fmt.Sprintf("ERC20 addr is not a valid, hex-encoded Ethereum address (%s)", fun.Erc20Addr), + ) + } + + // Check address encoding bijectivity + wantAddr := fun.ERC20Addr().Hex() + haveAddr := fun.Erc20Addr + if haveAddr != wantAddr { + return errValidateFunToken(fmt.Sprintf( + "ERC20 addr is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", + haveAddr, wantAddr, + )) + } + return nil +} + +// NewFunToken is a canonical constructor for the [FunToken] type. Using this +// function helps guarantee a consistent string representation from the +// hex-encoded Ethereum address. +func NewFunToken( + erc20 gethcommon.Address, bankDenom string, isMadeFromCoin bool, +) FunToken { + return FunToken{ + Erc20Addr: erc20.Hex(), + BankDenom: bankDenom, + IsMadeFromCoin: isMadeFromCoin, + } +} + +func (fun FunToken) ERC20Addr() gethcommon.Address { + return gethcommon.HexToAddress(fun.Erc20Addr) +} diff --git a/x/evm/evm.pb.go b/x/evm/evm.pb.go index 7da40c94b..0661925f8 100644 --- a/x/evm/evm.pb.go +++ b/x/evm/evm.pb.go @@ -23,6 +23,75 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// FunToken is a fungible token mapping between a bank coin and a corresponding +// ERC-20 smart contract. Bank coins here refer to tokens like NIBI, IBC +// coins (ICS-20), and token factory coins, which are each represented by the +// "Coin" type in Golang. +type FunToken struct { + // Hexadecimal address of the ERC20 token to which the `FunToken` maps + Erc20Addr string `protobuf:"bytes,1,opt,name=erc20_addr,json=erc20Addr,proto3" json:"erc20_addr,omitempty"` + // bank_denom: Coin denomination in the Bank Module. + BankDenom string `protobuf:"bytes,2,opt,name=bank_denom,json=bankDenom,proto3" json:"bank_denom,omitempty"` + // True if the `FunToken` mapping was created from an existing bank coin and + // the ERC-20 contract gets deployed by the module account. False if the + // mapping was created from an externally owned ERC-20 contract. + IsMadeFromCoin bool `protobuf:"varint,3,opt,name=is_made_from_coin,json=isMadeFromCoin,proto3" json:"is_made_from_coin,omitempty"` +} + +func (m *FunToken) Reset() { *m = FunToken{} } +func (m *FunToken) String() string { return proto.CompactTextString(m) } +func (*FunToken) ProtoMessage() {} +func (*FunToken) Descriptor() ([]byte, []int) { + return fileDescriptor_98abbdadb327b7d0, []int{0} +} +func (m *FunToken) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FunToken) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FunToken.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 *FunToken) XXX_Merge(src proto.Message) { + xxx_messageInfo_FunToken.Merge(m, src) +} +func (m *FunToken) XXX_Size() int { + return m.Size() +} +func (m *FunToken) XXX_DiscardUnknown() { + xxx_messageInfo_FunToken.DiscardUnknown(m) +} + +var xxx_messageInfo_FunToken proto.InternalMessageInfo + +func (m *FunToken) GetErc20Addr() string { + if m != nil { + return m.Erc20Addr + } + return "" +} + +func (m *FunToken) GetBankDenom() string { + if m != nil { + return m.BankDenom + } + return "" +} + +func (m *FunToken) GetIsMadeFromCoin() bool { + if m != nil { + return m.IsMadeFromCoin + } + return false +} + // Params defines the EVM module parameters type Params struct { // evm_denom represents the token denomination used to run the EVM state @@ -48,7 +117,7 @@ func (m *Params) Reset() { *m = Params{} } func (m *Params) String() string { return proto.CompactTextString(m) } func (*Params) ProtoMessage() {} func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{0} + return fileDescriptor_98abbdadb327b7d0, []int{1} } func (m *Params) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -138,7 +207,7 @@ func (m *State) Reset() { *m = State{} } func (m *State) String() string { return proto.CompactTextString(m) } func (*State) ProtoMessage() {} func (*State) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{1} + return fileDescriptor_98abbdadb327b7d0, []int{2} } func (m *State) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -195,7 +264,7 @@ func (m *TransactionLogs) Reset() { *m = TransactionLogs{} } func (m *TransactionLogs) String() string { return proto.CompactTextString(m) } func (*TransactionLogs) ProtoMessage() {} func (*TransactionLogs) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{2} + return fileDescriptor_98abbdadb327b7d0, []int{3} } func (m *TransactionLogs) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -271,7 +340,7 @@ func (m *Log) Reset() { *m = Log{} } func (m *Log) String() string { return proto.CompactTextString(m) } func (*Log) ProtoMessage() {} func (*Log) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{3} + return fileDescriptor_98abbdadb327b7d0, []int{4} } func (m *Log) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -386,7 +455,7 @@ func (m *TxResult) Reset() { *m = TxResult{} } func (m *TxResult) String() string { return proto.CompactTextString(m) } func (*TxResult) ProtoMessage() {} func (*TxResult) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{4} + return fileDescriptor_98abbdadb327b7d0, []int{5} } func (m *TxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -427,7 +496,7 @@ func (m *AccessTuple) Reset() { *m = AccessTuple{} } func (m *AccessTuple) String() string { return proto.CompactTextString(m) } func (*AccessTuple) ProtoMessage() {} func (*AccessTuple) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{5} + return fileDescriptor_98abbdadb327b7d0, []int{6} } func (m *AccessTuple) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -485,7 +554,7 @@ func (m *TraceConfig) Reset() { *m = TraceConfig{} } func (m *TraceConfig) String() string { return proto.CompactTextString(m) } func (*TraceConfig) ProtoMessage() {} func (*TraceConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_98abbdadb327b7d0, []int{6} + return fileDescriptor_98abbdadb327b7d0, []int{7} } func (m *TraceConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -585,6 +654,7 @@ func (m *TraceConfig) GetTracerJsonConfig() string { } func init() { + proto.RegisterType((*FunToken)(nil), "eth.evm.v1.FunToken") proto.RegisterType((*Params)(nil), "eth.evm.v1.Params") proto.RegisterType((*State)(nil), "eth.evm.v1.State") proto.RegisterType((*TransactionLogs)(nil), "eth.evm.v1.TransactionLogs") @@ -597,73 +667,77 @@ func init() { func init() { proto.RegisterFile("eth/evm/v1/evm.proto", fileDescriptor_98abbdadb327b7d0) } var fileDescriptor_98abbdadb327b7d0 = []byte{ - // 1041 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0x41, 0x6f, 0xdb, 0x46, - 0x13, 0xb5, 0x2c, 0x4a, 0xa2, 0x56, 0x72, 0xa4, 0x6c, 0xf4, 0xe5, 0x63, 0x13, 0x40, 0x14, 0x98, - 0x8b, 0x0e, 0xa9, 0x05, 0xbb, 0x28, 0x0a, 0xb8, 0x48, 0x01, 0xd3, 0x71, 0xd1, 0xa8, 0x4e, 0x60, - 0x6c, 0x9c, 0x1e, 0x7a, 0x21, 0x56, 0xe4, 0x94, 0x62, 0x4d, 0x72, 0x05, 0xee, 0x4a, 0xa5, 0x7f, - 0x40, 0x81, 0x1e, 0x7b, 0xed, 0x2d, 0x3f, 0x27, 0xe8, 0x29, 0xc7, 0x9e, 0x88, 0xc2, 0xbe, 0xb4, - 0x3a, 0xea, 0x17, 0x14, 0xbb, 0x4b, 0x59, 0xb2, 0x0b, 0xf4, 0xa4, 0x79, 0xf3, 0x76, 0x76, 0x86, - 0x6f, 0x1e, 0x29, 0xd4, 0x03, 0x31, 0x1d, 0xc1, 0x22, 0x19, 0x2d, 0x0e, 0xe4, 0xcf, 0xfe, 0x2c, - 0x63, 0x82, 0x61, 0x04, 0x62, 0xba, 0x2f, 0xe1, 0xe2, 0xe0, 0x49, 0x2f, 0x64, 0x21, 0x53, 0xe9, - 0x91, 0x8c, 0xf4, 0x09, 0xe7, 0xb7, 0x2a, 0xaa, 0x9f, 0xd3, 0x8c, 0x26, 0x1c, 0x1f, 0xa0, 0x26, - 0x2c, 0x12, 0x2f, 0x80, 0x94, 0x25, 0x56, 0x65, 0x50, 0x19, 0x36, 0xdd, 0xde, 0xaa, 0xb0, 0xbb, - 0x57, 0x34, 0x89, 0x8f, 0x9c, 0x5b, 0xca, 0x21, 0x26, 0x2c, 0x92, 0x97, 0x32, 0xc4, 0x2f, 0xd0, - 0x1e, 0xa4, 0x74, 0x12, 0x83, 0xe7, 0x67, 0x40, 0x05, 0x58, 0xbb, 0x83, 0xca, 0xd0, 0x74, 0xad, - 0x55, 0x61, 0xf7, 0xca, 0xb2, 0x6d, 0xda, 0x21, 0x6d, 0x8d, 0x4f, 0x14, 0xc4, 0x5f, 0xa0, 0xd6, - 0x9a, 0xa7, 0x71, 0x6c, 0x55, 0x55, 0xf1, 0xe3, 0x55, 0x61, 0xe3, 0xbb, 0xc5, 0x34, 0x8e, 0x1d, - 0x82, 0xca, 0x52, 0x1a, 0xc7, 0xf8, 0x18, 0x21, 0xc8, 0x45, 0x46, 0x3d, 0x88, 0x66, 0xdc, 0x32, - 0x06, 0xd5, 0x61, 0xd5, 0x75, 0xae, 0x0b, 0xbb, 0x79, 0x2a, 0xb3, 0xa7, 0xaf, 0xce, 0xf9, 0xaa, - 0xb0, 0x1f, 0x96, 0x97, 0xdc, 0x1e, 0x74, 0x48, 0x53, 0x81, 0xd3, 0x68, 0xc6, 0xf1, 0x21, 0xfa, - 0x1f, 0x8d, 0x63, 0xf6, 0x93, 0x37, 0x4f, 0xa5, 0x12, 0xe0, 0x0b, 0x08, 0x3c, 0x91, 0x73, 0xab, - 0x2e, 0xa7, 0x20, 0x8f, 0x14, 0xf9, 0x6e, 0xc3, 0x5d, 0xe4, 0x1c, 0x7f, 0x8a, 0x30, 0xf5, 0x45, - 0xb4, 0x00, 0x6f, 0x96, 0x81, 0xcf, 0x92, 0x59, 0x14, 0x03, 0xb7, 0x1a, 0x83, 0xea, 0xb0, 0x49, - 0x1e, 0x6a, 0xe6, 0x7c, 0x43, 0xe0, 0x43, 0xd4, 0x96, 0xaa, 0xf9, 0x53, 0x9a, 0xa6, 0x10, 0x73, - 0xcb, 0x94, 0x07, 0xdd, 0xce, 0x75, 0x61, 0xb7, 0x4e, 0xbf, 0x7b, 0x7d, 0x52, 0xa6, 0x49, 0x0b, - 0x16, 0xc9, 0x1a, 0x1c, 0x19, 0x7f, 0xbd, 0xb7, 0x2b, 0x63, 0xc3, 0xac, 0x75, 0xeb, 0xce, 0x08, - 0xd5, 0xde, 0x0a, 0xa9, 0x53, 0x17, 0x55, 0x2f, 0xe1, 0x4a, 0xef, 0x84, 0xc8, 0x10, 0xf7, 0x50, - 0x6d, 0x41, 0xe3, 0xb9, 0x16, 0xbc, 0x49, 0x34, 0x70, 0xc6, 0xa8, 0x73, 0x91, 0xd1, 0x94, 0xcb, - 0x51, 0x58, 0x7a, 0xc6, 0x42, 0x8e, 0x31, 0x32, 0xa6, 0x94, 0x4f, 0xcb, 0x5a, 0x15, 0xe3, 0x67, - 0xc8, 0x88, 0x59, 0xc8, 0xad, 0xdd, 0x41, 0x75, 0xd8, 0x3a, 0xec, 0xec, 0x6f, 0x4c, 0xb2, 0x7f, - 0xc6, 0x42, 0xa2, 0x48, 0xe7, 0xf7, 0x5d, 0x54, 0x3d, 0x63, 0x21, 0xb6, 0x50, 0x83, 0x06, 0x41, - 0x06, 0x9c, 0x97, 0x77, 0xac, 0x21, 0x7e, 0x8c, 0xea, 0x82, 0xcd, 0x22, 0x5f, 0x5f, 0xd4, 0x24, - 0x25, 0x92, 0x2d, 0x03, 0x2a, 0xa8, 0x5a, 0x67, 0x9b, 0xa8, 0x58, 0x4a, 0x31, 0x89, 0x99, 0x7f, - 0xe9, 0xa5, 0xf3, 0x64, 0x02, 0x99, 0x65, 0x0c, 0x2a, 0x43, 0xc3, 0xed, 0x2c, 0x0b, 0xbb, 0xa5, - 0xf2, 0x6f, 0x54, 0x9a, 0x6c, 0x03, 0xfc, 0x1c, 0x35, 0x44, 0xee, 0xa9, 0xe9, 0x6b, 0xca, 0x8d, - 0x8f, 0x96, 0x85, 0xdd, 0x11, 0x9b, 0x07, 0xfc, 0x86, 0xf2, 0x29, 0xa9, 0x8b, 0x5c, 0xfe, 0xe2, - 0x11, 0x32, 0x45, 0xee, 0x45, 0x69, 0x00, 0xb9, 0x5a, 0xa1, 0xe1, 0xf6, 0x96, 0x85, 0xdd, 0xdd, - 0x3a, 0xfe, 0x4a, 0x72, 0xa4, 0x21, 0x72, 0x15, 0xe0, 0xe7, 0x08, 0xe9, 0x91, 0x54, 0x87, 0x86, - 0xea, 0xb0, 0xb7, 0x2c, 0xec, 0xa6, 0xca, 0xaa, 0xbb, 0x37, 0x21, 0x76, 0x50, 0x4d, 0xdf, 0x6d, - 0xaa, 0xbb, 0xdb, 0xcb, 0xc2, 0x36, 0x63, 0x16, 0xea, 0x3b, 0x35, 0x25, 0xa5, 0xca, 0x20, 0x61, - 0x0b, 0x08, 0xac, 0xa6, 0x32, 0xd1, 0x1a, 0x3a, 0x3f, 0xef, 0x22, 0xf3, 0x22, 0x27, 0xc0, 0xe7, - 0xb1, 0xc0, 0x5f, 0xa3, 0xae, 0xcf, 0x52, 0x91, 0x51, 0x5f, 0x78, 0x77, 0xa4, 0x75, 0x9f, 0xae, - 0x0a, 0xfb, 0xff, 0xda, 0xb5, 0xf7, 0x4f, 0x38, 0xa4, 0xb3, 0x4e, 0x1d, 0x97, 0xfa, 0xf7, 0x50, - 0x6d, 0x12, 0x33, 0x96, 0x28, 0x0f, 0xb4, 0x89, 0x06, 0xf8, 0x4c, 0xa9, 0xa6, 0xf6, 0x2b, 0x17, - 0xd0, 0x3a, 0x7c, 0xba, 0xbd, 0xdf, 0x7b, 0xf6, 0x70, 0x1f, 0x7f, 0x28, 0xec, 0x9d, 0x55, 0x61, - 0x3f, 0xd0, 0x5d, 0xcb, 0x4a, 0x47, 0xaa, 0xaa, 0xec, 0xd3, 0x45, 0xd5, 0x0c, 0x84, 0x5a, 0x57, - 0x9b, 0xc8, 0x10, 0x3f, 0x41, 0x66, 0x06, 0x0b, 0xc8, 0x04, 0x04, 0x6a, 0x2d, 0x26, 0xb9, 0xc5, - 0xf8, 0x13, 0x64, 0x86, 0x94, 0x7b, 0x73, 0x0e, 0x81, 0xde, 0x01, 0x69, 0x84, 0x94, 0xbf, 0xe3, - 0x10, 0x1c, 0x19, 0xbf, 0xbc, 0xb7, 0x77, 0x1c, 0x8a, 0x5a, 0xc7, 0xbe, 0x0f, 0x9c, 0x5f, 0xcc, - 0x67, 0x31, 0xfc, 0x87, 0xb7, 0x0e, 0x51, 0x9b, 0x0b, 0x96, 0xd1, 0x10, 0xbc, 0x4b, 0xb8, 0x2a, - 0x1d, 0xa6, 0xfd, 0x52, 0xe6, 0xbf, 0x85, 0x2b, 0x4e, 0xb6, 0x41, 0xd9, 0xe2, 0xef, 0x2a, 0x6a, - 0x5d, 0x64, 0xd4, 0x87, 0x13, 0x96, 0xfe, 0x10, 0x85, 0xca, 0xa5, 0x12, 0x66, 0x65, 0x8b, 0x12, - 0xc9, 0xde, 0x22, 0x4a, 0x80, 0xcd, 0x45, 0xf9, 0x0e, 0xad, 0xa1, 0xac, 0xc8, 0x00, 0x72, 0xf0, - 0x95, 0x80, 0x06, 0x29, 0x11, 0xfe, 0x1c, 0xed, 0x05, 0x11, 0x57, 0x5f, 0x24, 0x2e, 0xa8, 0x7f, - 0xa9, 0x1f, 0xdf, 0xed, 0x2e, 0x0b, 0xbb, 0x5d, 0x12, 0x6f, 0x65, 0x9e, 0xdc, 0x41, 0xf8, 0x4b, - 0xd4, 0xd9, 0x94, 0xa9, 0x69, 0xf5, 0x27, 0xc6, 0xc5, 0xcb, 0xc2, 0x7e, 0x70, 0x7b, 0x54, 0x31, - 0xe4, 0x1e, 0x96, 0x3b, 0x0e, 0x60, 0x32, 0x0f, 0x95, 0xed, 0x4c, 0xa2, 0x81, 0xcc, 0xc6, 0x51, - 0x12, 0x09, 0x65, 0xb3, 0x1a, 0xd1, 0x40, 0xce, 0x57, 0x7e, 0x30, 0x13, 0x48, 0x58, 0x76, 0x65, - 0xb5, 0x36, 0xf3, 0x69, 0xe2, 0xb5, 0xca, 0x93, 0x3b, 0x08, 0xbb, 0x08, 0x97, 0x65, 0x19, 0x88, - 0x79, 0x96, 0x7a, 0xea, 0xe5, 0x6d, 0xab, 0x5a, 0xf5, 0x0a, 0x69, 0x96, 0x28, 0xf2, 0x25, 0x15, - 0x94, 0xfc, 0x2b, 0x83, 0xbf, 0x42, 0x58, 0xcb, 0xea, 0xfd, 0xc8, 0x59, 0xea, 0xf9, 0x4a, 0x7a, - 0x6b, 0x4f, 0x99, 0x5a, 0xf5, 0xd7, 0xac, 0x5e, 0x09, 0xe9, 0x6a, 0x34, 0xe6, 0x2c, 0xd5, 0x99, - 0xb1, 0x61, 0x1a, 0xdd, 0xda, 0xd8, 0x30, 0x1b, 0x5d, 0x73, 0x6c, 0x98, 0xa8, 0xdb, 0xba, 0x15, - 0xa2, 0x7c, 0x16, 0xf2, 0x68, 0x8d, 0xb7, 0x86, 0x74, 0x5f, 0x7c, 0xb8, 0xee, 0x57, 0x3e, 0x5e, - 0xf7, 0x2b, 0x7f, 0x5e, 0xf7, 0x2b, 0xbf, 0xde, 0xf4, 0x77, 0x3e, 0xde, 0xf4, 0x77, 0xfe, 0xb8, - 0xe9, 0xef, 0x7c, 0xff, 0x2c, 0x8c, 0xc4, 0x74, 0x3e, 0xd9, 0xf7, 0x59, 0x32, 0x7a, 0x13, 0x4d, - 0xa2, 0x6c, 0x7e, 0x32, 0xa5, 0x51, 0x3a, 0x4a, 0x55, 0x3c, 0xca, 0xe5, 0x7f, 0xe4, 0xa4, 0xae, - 0xfe, 0x02, 0x3f, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0x43, 0x47, 0xd2, 0x97, 0x3c, 0x07, 0x00, - 0x00, + // 1108 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0x4f, 0x6f, 0xdb, 0x36, + 0x14, 0x8f, 0x63, 0x39, 0x96, 0x69, 0xa7, 0x76, 0x59, 0xaf, 0xd3, 0x5a, 0x2c, 0x0a, 0xd4, 0x4b, + 0x06, 0x74, 0xf1, 0x9a, 0x61, 0x18, 0xd0, 0xa1, 0x03, 0xa2, 0x34, 0xc5, 0x9a, 0xa5, 0x45, 0xc1, + 0xba, 0x3b, 0xec, 0x22, 0xd0, 0xd2, 0xab, 0xac, 0x59, 0x12, 0x0d, 0x92, 0xf2, 0x9c, 0x0f, 0x30, + 0x60, 0xc7, 0x5d, 0x77, 0xeb, 0xc7, 0x29, 0x76, 0xea, 0x71, 0x27, 0x61, 0x48, 0x2f, 0x9b, 0x8f, + 0xfe, 0x04, 0x03, 0x49, 0x39, 0x76, 0x3a, 0x60, 0x27, 0xbf, 0xdf, 0xef, 0xc7, 0xf7, 0x47, 0xef, + 0x3d, 0xd2, 0xa8, 0x0f, 0x72, 0x3c, 0x80, 0x59, 0x36, 0x98, 0x3d, 0x50, 0x3f, 0x87, 0x53, 0xce, + 0x24, 0xc3, 0x08, 0xe4, 0xf8, 0x50, 0xc1, 0xd9, 0x83, 0x3b, 0xfd, 0x98, 0xc5, 0x4c, 0xd3, 0x03, + 0x65, 0x99, 0x13, 0x9e, 0x40, 0xf6, 0x93, 0x22, 0x1f, 0xb2, 0x09, 0xe4, 0xf8, 0x53, 0x84, 0x80, + 0x87, 0x47, 0x5f, 0x04, 0x34, 0x8a, 0xb8, 0x53, 0xdb, 0xaf, 0x1d, 0xb4, 0x48, 0x4b, 0x33, 0xc7, + 0x51, 0xc4, 0x95, 0x3c, 0xa2, 0xf9, 0x24, 0x88, 0x20, 0x67, 0x99, 0xb3, 0x6d, 0x64, 0xc5, 0x3c, + 0x56, 0x04, 0xfe, 0x0c, 0xdd, 0x4c, 0x44, 0x90, 0xd1, 0x08, 0x82, 0xd7, 0x9c, 0x65, 0x41, 0xc8, + 0x92, 0xdc, 0xa9, 0xef, 0xd7, 0x0e, 0x6c, 0x72, 0x23, 0x11, 0xcf, 0x68, 0x04, 0x4f, 0x38, 0xcb, + 0x4e, 0x58, 0x92, 0x7b, 0xbf, 0xd7, 0xd1, 0xce, 0x0b, 0xca, 0x69, 0x26, 0xf0, 0x03, 0xd4, 0x82, + 0x59, 0x56, 0xc5, 0xd4, 0x29, 0xfd, 0xfe, 0xb2, 0x74, 0x7b, 0x17, 0x34, 0x4b, 0x1f, 0x7a, 0x57, + 0x92, 0x47, 0x6c, 0x98, 0x65, 0x26, 0xd1, 0x23, 0xb4, 0x0b, 0x39, 0x1d, 0xa5, 0x10, 0x84, 0x1c, + 0xa8, 0x04, 0x5d, 0x8a, 0xed, 0x3b, 0xcb, 0xd2, 0xed, 0x57, 0x6e, 0x9b, 0xb2, 0x47, 0x3a, 0x06, + 0x9f, 0x68, 0x88, 0xbf, 0x46, 0xed, 0x95, 0x4e, 0xd3, 0xd4, 0x54, 0xe8, 0xdf, 0x5e, 0x96, 0x2e, + 0xbe, 0xee, 0x4c, 0xd3, 0xd4, 0x23, 0xa8, 0x72, 0xa5, 0x69, 0x8a, 0x8f, 0x11, 0x82, 0xb9, 0xe4, + 0x34, 0x80, 0x64, 0x2a, 0x1c, 0x6b, 0xbf, 0x7e, 0x50, 0xf7, 0xbd, 0xcb, 0xd2, 0x6d, 0x9d, 0x2a, + 0xf6, 0xf4, 0xe9, 0x0b, 0xb1, 0x2c, 0xdd, 0x9b, 0x55, 0x90, 0xab, 0x83, 0x1e, 0x69, 0x69, 0x70, + 0x9a, 0x4c, 0x05, 0x3e, 0x42, 0x1f, 0xd1, 0x34, 0x65, 0x3f, 0x07, 0x45, 0xae, 0xda, 0x0f, 0xa1, + 0x84, 0x28, 0x90, 0x73, 0xe1, 0xec, 0xe8, 0x3e, 0xdd, 0xd2, 0xe2, 0xab, 0xb5, 0x36, 0x9c, 0x0b, + 0xfc, 0x39, 0xc2, 0x34, 0x94, 0xc9, 0x0c, 0x82, 0x29, 0x87, 0x90, 0x65, 0xd3, 0x24, 0x05, 0xe1, + 0x34, 0xf7, 0xeb, 0x07, 0x2d, 0x72, 0xd3, 0x28, 0x2f, 0xd6, 0x02, 0x3e, 0x42, 0x1d, 0xd5, 0xb5, + 0x70, 0x4c, 0xf3, 0x1c, 0x52, 0xe1, 0xd8, 0xea, 0xa0, 0xdf, 0xbd, 0x2c, 0xdd, 0xf6, 0xe9, 0x0f, + 0xcf, 0x4e, 0x2a, 0x9a, 0xb4, 0x61, 0x96, 0xad, 0xc0, 0x43, 0xeb, 0xef, 0x37, 0x6e, 0xed, 0xcc, + 0xb2, 0x1b, 0xbd, 0x1d, 0x6f, 0x80, 0x1a, 0x2f, 0xa5, 0xea, 0x53, 0x0f, 0xd5, 0x27, 0x70, 0x51, + 0xad, 0x81, 0x32, 0x71, 0x1f, 0x35, 0x66, 0x34, 0x2d, 0xa0, 0x9a, 0xbd, 0x01, 0xde, 0x19, 0xea, + 0x0e, 0x39, 0xcd, 0x85, 0x2a, 0x85, 0xe5, 0xe7, 0x2c, 0x16, 0x18, 0x23, 0x6b, 0x4c, 0xc5, 0xb8, + 0xf2, 0xd5, 0x36, 0xbe, 0x87, 0xac, 0x94, 0xc5, 0xc2, 0xd9, 0xde, 0xaf, 0x1f, 0xb4, 0x8f, 0xba, + 0x87, 0xeb, 0xcd, 0x3c, 0x3c, 0x67, 0x31, 0xd1, 0xa2, 0xf7, 0xc7, 0x36, 0xaa, 0x9f, 0xb3, 0x18, + 0x3b, 0xa8, 0xa9, 0x76, 0x10, 0x84, 0xa8, 0x62, 0xac, 0x20, 0xbe, 0x8d, 0x76, 0x24, 0x9b, 0x26, + 0xa1, 0x09, 0xd4, 0x22, 0x15, 0x52, 0x29, 0x23, 0x2a, 0xa9, 0x1e, 0x67, 0x87, 0x68, 0x5b, 0xb5, + 0x62, 0x94, 0xb2, 0x70, 0x12, 0xe4, 0x45, 0x36, 0x02, 0xee, 0x58, 0xfb, 0xb5, 0x03, 0xcb, 0xef, + 0x2e, 0x4a, 0xb7, 0xad, 0xf9, 0xe7, 0x9a, 0x26, 0x9b, 0x00, 0xdf, 0x47, 0x4d, 0x39, 0x0f, 0x74, + 0xf5, 0x0d, 0xbd, 0x8d, 0xb7, 0x16, 0xa5, 0xdb, 0x95, 0xeb, 0x0f, 0xfc, 0x8e, 0x8a, 0x31, 0xd9, + 0x91, 0x73, 0xf5, 0x8b, 0x07, 0xc8, 0x96, 0xf3, 0x20, 0xc9, 0x23, 0x98, 0xeb, 0x11, 0x5a, 0x7e, + 0x7f, 0x51, 0xba, 0xbd, 0x8d, 0xe3, 0x4f, 0x95, 0x46, 0x9a, 0x72, 0xae, 0x0d, 0x7c, 0x1f, 0x21, + 0x53, 0x92, 0xce, 0xd0, 0xd4, 0x19, 0x76, 0x17, 0xa5, 0xdb, 0xd2, 0xac, 0x8e, 0xbd, 0x36, 0xb1, + 0x87, 0x1a, 0x26, 0xb6, 0xad, 0x63, 0x77, 0x16, 0xa5, 0x6b, 0xa7, 0x2c, 0x36, 0x31, 0x8d, 0xa4, + 0x5a, 0xc5, 0x21, 0x63, 0x33, 0x88, 0x9c, 0x96, 0x5e, 0xa2, 0x15, 0xf4, 0x7e, 0xd9, 0x46, 0xf6, + 0x70, 0x4e, 0x40, 0x14, 0xa9, 0xc4, 0x4f, 0x50, 0x2f, 0x64, 0xb9, 0xe4, 0x34, 0x94, 0xc1, 0xb5, + 0xd6, 0xfa, 0x77, 0x97, 0xa5, 0xfb, 0xb1, 0xd9, 0xda, 0x0f, 0x4f, 0x78, 0xa4, 0xbb, 0xa2, 0x8e, + 0xab, 0xfe, 0xf7, 0x51, 0x63, 0x94, 0xb2, 0xea, 0xfe, 0x77, 0x88, 0x01, 0xf8, 0x5c, 0x77, 0x4d, + 0xcf, 0x57, 0x0d, 0xa0, 0x7d, 0x74, 0x77, 0x73, 0xbe, 0x1f, 0xac, 0x87, 0x7f, 0xfb, 0x6d, 0xe9, + 0x6e, 0x2d, 0x4b, 0xf7, 0x86, 0xc9, 0x5a, 0x79, 0x7a, 0xaa, 0xab, 0x7a, 0x7d, 0x7a, 0xa8, 0xce, + 0x41, 0xea, 0x71, 0x75, 0x88, 0x32, 0xf1, 0x1d, 0x64, 0x73, 0x98, 0x01, 0x97, 0x10, 0xe9, 0xb1, + 0xd8, 0xe4, 0x0a, 0xe3, 0x4f, 0x90, 0x1d, 0x53, 0x11, 0x14, 0x02, 0x22, 0x33, 0x03, 0xd2, 0x8c, + 0xa9, 0x78, 0x25, 0x20, 0x7a, 0x68, 0xfd, 0xfa, 0xc6, 0xdd, 0xf2, 0x28, 0x6a, 0x1f, 0x87, 0x21, + 0x08, 0x31, 0x2c, 0xa6, 0x29, 0xfc, 0xcf, 0x6e, 0x1d, 0xa1, 0x8e, 0x90, 0x8c, 0xd3, 0x18, 0x82, + 0x09, 0x5c, 0x54, 0x1b, 0x66, 0xf6, 0xa5, 0xe2, 0xbf, 0x87, 0x0b, 0x41, 0x36, 0x41, 0x95, 0xe2, + 0x9f, 0x3a, 0x6a, 0x0f, 0x39, 0x0d, 0xe1, 0x84, 0xe5, 0xaf, 0x93, 0x58, 0x6f, 0xa9, 0x82, 0xab, + 0x57, 0xb4, 0x42, 0x2a, 0xb7, 0x4c, 0x32, 0x60, 0x85, 0xac, 0xee, 0xd0, 0x0a, 0x2a, 0x0f, 0x0e, + 0x30, 0x87, 0x50, 0x37, 0xd0, 0x22, 0x15, 0xc2, 0x5f, 0xa1, 0xdd, 0x28, 0x11, 0xfa, 0x45, 0x12, + 0x92, 0x86, 0x13, 0xf3, 0xf9, 0x7e, 0x6f, 0x51, 0xba, 0x9d, 0x4a, 0x78, 0xa9, 0x78, 0x72, 0x0d, + 0xe1, 0x6f, 0x50, 0x77, 0xed, 0xa6, 0xab, 0x35, 0x4f, 0x8c, 0x8f, 0x17, 0xa5, 0x7b, 0xe3, 0xea, + 0xa8, 0x56, 0xc8, 0x07, 0x58, 0xcd, 0x38, 0x82, 0x51, 0x11, 0xeb, 0xb5, 0xb3, 0x89, 0x01, 0x8a, + 0x4d, 0x93, 0x2c, 0x91, 0x7a, 0xcd, 0x1a, 0xc4, 0x00, 0x55, 0x5f, 0xf5, 0x60, 0x66, 0x90, 0x31, + 0x7e, 0xe1, 0xb4, 0xd7, 0xf5, 0x19, 0xe1, 0x99, 0xe6, 0xc9, 0x35, 0x84, 0x7d, 0x84, 0x2b, 0x37, + 0x0e, 0xb2, 0xe0, 0x79, 0xa0, 0x2f, 0x6f, 0x47, 0xfb, 0xea, 0x2b, 0x64, 0x54, 0xa2, 0xc5, 0xc7, + 0x54, 0x52, 0xf2, 0x1f, 0x06, 0x7f, 0x8b, 0xb0, 0x69, 0x6b, 0xf0, 0x93, 0x60, 0x79, 0x10, 0xea, + 0xd6, 0x3b, 0xbb, 0x7a, 0xa9, 0x75, 0x7e, 0xa3, 0x9a, 0x91, 0x90, 0x9e, 0x41, 0x67, 0x82, 0xe5, + 0x86, 0x39, 0xb3, 0x6c, 0xab, 0xd7, 0x38, 0xb3, 0xec, 0x66, 0xcf, 0x3e, 0xb3, 0x6c, 0xd4, 0x6b, + 0x5f, 0x35, 0xa2, 0xfa, 0x16, 0x72, 0x6b, 0x85, 0x37, 0x8a, 0xf4, 0x1f, 0xbd, 0xbd, 0xdc, 0xab, + 0xbd, 0xbb, 0xdc, 0xab, 0xfd, 0x75, 0xb9, 0x57, 0xfb, 0xed, 0xfd, 0xde, 0xd6, 0xbb, 0xf7, 0x7b, + 0x5b, 0x7f, 0xbe, 0xdf, 0xdb, 0xfa, 0xf1, 0x5e, 0x9c, 0xc8, 0x71, 0x31, 0x3a, 0x0c, 0x59, 0x36, + 0x78, 0x9e, 0x8c, 0x12, 0x5e, 0x9c, 0x8c, 0x69, 0x92, 0x0f, 0x72, 0x6d, 0x0f, 0xe6, 0xea, 0x8f, + 0x79, 0xb4, 0xa3, 0xff, 0x77, 0xbf, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x18, 0xc6, 0x36, + 0xb1, 0x07, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -723,6 +797,53 @@ func (this *Params) Equal(that interface{}) bool { } return true } +func (m *FunToken) 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 *FunToken) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FunToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.IsMadeFromCoin { + i-- + if m.IsMadeFromCoin { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.BankDenom) > 0 { + i -= len(m.BankDenom) + copy(dAtA[i:], m.BankDenom) + i = encodeVarintEvm(dAtA, i, uint64(len(m.BankDenom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Erc20Addr) > 0 { + i -= len(m.Erc20Addr) + copy(dAtA[i:], m.Erc20Addr) + i = encodeVarintEvm(dAtA, i, uint64(len(m.Erc20Addr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *Params) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1209,6 +1330,26 @@ func encodeVarintEvm(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *FunToken) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Erc20Addr) + if l > 0 { + n += 1 + l + sovEvm(uint64(l)) + } + l = len(m.BankDenom) + if l > 0 { + n += 1 + l + sovEvm(uint64(l)) + } + if m.IsMadeFromCoin { + n += 2 + } + return n +} + func (m *Params) Size() (n int) { if m == nil { return 0 @@ -1425,6 +1566,140 @@ func sovEvm(x uint64) (n int) { func sozEvm(x uint64) (n int) { return sovEvm(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *FunToken) 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 ErrIntOverflowEvm + } + 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: FunToken: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FunToken: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20Addr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvm + } + 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 ErrInvalidLengthEvm + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvm + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20Addr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + 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 ErrIntOverflowEvm + } + 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 ErrInvalidLengthEvm + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvm + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BankDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsMadeFromCoin", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvm + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsMadeFromCoin = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipEvm(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvm + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Params) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/evm/evm_test.go b/x/evm/evm_test.go new file mode 100644 index 000000000..afb6743b7 --- /dev/null +++ b/x/evm/evm_test.go @@ -0,0 +1,100 @@ +// Copyright (c) 2023-2024 Nibi, Inc. +package evm_test + +import ( + "strconv" + "testing" + + "github.com/NibiruChain/nibiru/eth" + "github.com/NibiruChain/nibiru/x/evm" + "github.com/stretchr/testify/suite" +) + +type TestSuite struct { + suite.Suite +} + +func TestSuite_RunAll(t *testing.T) { + suite.Run(t, new(TestSuite)) +} + +func (s *TestSuite) TestFunToken() { + for testIdx, tc := range []struct { + bankDenom string + erc20Addr string + wantErr string + }{ + { + bankDenom: "", + erc20Addr: "", + wantErr: "FunTokenError", + }, + { + bankDenom: "unibi", + erc20Addr: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + wantErr: "not encoded as expected", + }, + { + bankDenom: "unibi", + erc20Addr: eth.NewHexAddrFromStr("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed").String(), + wantErr: "", + }, + { + bankDenom: "ibc/AAA/BBB", + erc20Addr: "0xE1aA1500b962528cBB42F05bD6d8A6032a85602f", + wantErr: "", + }, + { + bankDenom: "tf/contract-addr/subdenom", + erc20Addr: "0x6B2e60f1030aFa69F584829f1d700b47eE5Fc74a", + wantErr: "", + }, + } { + s.Run(strconv.Itoa(testIdx), func() { + funtoken := evm.FunToken{ + Erc20Addr: tc.erc20Addr, + BankDenom: tc.bankDenom, + } + err := funtoken.Validate() + if tc.wantErr != "" { + s.Require().Error(err) + return + } + s.Require().NoError(err) + }) + } + + for _, tc := range []struct { + name string + A string + B string + }{ + { + name: "capital and lowercase match", + A: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + B: "5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED", + }, + { + name: "0x prefix and no prefix match", + A: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + B: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + }, + { + name: "0x prefix and no prefix match", + A: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + B: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + }, + { + name: "mixed case compatibility", + A: "0x5Bdb32670a05Daa22Cb2E279B80044c37dc85e61", + B: "0x5BDB32670A05DAA22CB2E279B80044C37DC85E61", + }, + } { + s.Run(tc.name, func() { + funA := evm.FunToken{Erc20Addr: tc.A} + funB := evm.FunToken{Erc20Addr: tc.B} + + s.EqualValues(funA.ERC20Addr(), funB.ERC20Addr()) + }) + } +} diff --git a/x/evm/genesis.pb.go b/x/evm/genesis.pb.go index 3d7f9ada9..0f8a9980b 100644 --- a/x/evm/genesis.pb.go +++ b/x/evm/genesis.pb.go @@ -29,6 +29,8 @@ type GenesisState struct { Accounts []GenesisAccount `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"` // params defines all the parameters of the module. Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` + // Fungible token mappings corresponding to ERC-20 smart contract tokens. + FuntokenMappings []FunToken `protobuf:"bytes,3,rep,name=funtoken_mappings,json=funtokenMappings,proto3" json:"funtoken_mappings"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -78,6 +80,13 @@ func (m *GenesisState) GetParams() Params { return Params{} } +func (m *GenesisState) GetFuntokenMappings() []FunToken { + if m != nil { + return m.FuntokenMappings + } + return nil +} + // GenesisAccount defines an account to be initialized in the genesis state. // Its main difference between with Geth's GenesisAccount is that it uses a // custom storage type and that it doesn't contain the private key field. @@ -152,26 +161,28 @@ func init() { func init() { proto.RegisterFile("eth/evm/v1/genesis.proto", fileDescriptor_d41c81841e3983b5) } var fileDescriptor_d41c81841e3983b5 = []byte{ - // 297 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x3f, 0x4e, 0xc3, 0x30, - 0x18, 0xc5, 0x63, 0x5a, 0x35, 0xd4, 0x45, 0x20, 0xac, 0x0e, 0x51, 0x06, 0xb7, 0x2a, 0x4b, 0x26, - 0x9b, 0x96, 0xb5, 0x0c, 0x84, 0x81, 0x0d, 0xa1, 0x74, 0x63, 0x73, 0x12, 0x2b, 0xc9, 0x90, 0xb8, - 0x8a, 0x9d, 0x88, 0x01, 0x71, 0x06, 0xce, 0xc1, 0x49, 0x3a, 0x76, 0x64, 0x02, 0x94, 0x5c, 0x04, - 0xc5, 0x49, 0x21, 0xdd, 0x9e, 0x3f, 0xff, 0xde, 0xfb, 0xfe, 0x40, 0x8b, 0xab, 0x98, 0xf2, 0x32, - 0xa5, 0xe5, 0x92, 0x46, 0x3c, 0xe3, 0x32, 0x91, 0x64, 0x9b, 0x0b, 0x25, 0x10, 0xe4, 0x2a, 0x26, - 0xbc, 0x4c, 0x49, 0xb9, 0xb4, 0xa7, 0x3d, 0xaa, 0x29, 0x69, 0xc2, 0x9e, 0x46, 0x22, 0x12, 0x5a, - 0xd2, 0x46, 0xb5, 0xd5, 0xc5, 0x1b, 0x3c, 0x7b, 0x68, 0x83, 0x36, 0x8a, 0x29, 0x8e, 0xd6, 0xf0, - 0x94, 0x05, 0x81, 0x28, 0x32, 0x25, 0x2d, 0x30, 0x1f, 0x38, 0x93, 0x95, 0x4d, 0xfe, 0xa3, 0x49, - 0xc7, 0xde, 0xb5, 0x88, 0x3b, 0xdc, 0x7d, 0xcd, 0x0c, 0xef, 0xcf, 0x81, 0xae, 0xe1, 0x68, 0xcb, - 0x72, 0x96, 0x4a, 0xeb, 0x64, 0x0e, 0x9c, 0xc9, 0x0a, 0xf5, 0xbd, 0x4f, 0xfa, 0xa7, 0xf3, 0x74, - 0xdc, 0xe2, 0x15, 0x9e, 0x1f, 0x67, 0x22, 0x0b, 0x9a, 0x2c, 0x0c, 0x73, 0x2e, 0x9b, 0x01, 0x80, - 0x33, 0xf6, 0x0e, 0x4f, 0x84, 0xe0, 0x30, 0x10, 0x21, 0xd7, 0xd9, 0x63, 0x4f, 0x6b, 0xb4, 0x86, - 0xa6, 0x54, 0x22, 0x67, 0x11, 0xb7, 0x06, 0x7a, 0xdc, 0xcb, 0x7e, 0x4b, 0xbd, 0x93, 0x7b, 0xd1, - 0x74, 0xfc, 0xf8, 0x9e, 0x99, 0x9b, 0x96, 0xf4, 0x0e, 0x16, 0xf7, 0x76, 0x57, 0x61, 0xb0, 0xaf, - 0x30, 0xf8, 0xa9, 0x30, 0x78, 0xaf, 0xb1, 0xb1, 0xaf, 0xb1, 0xf1, 0x59, 0x63, 0xe3, 0xf9, 0x2a, - 0x4a, 0x54, 0x5c, 0xf8, 0x24, 0x10, 0x29, 0x7d, 0x4c, 0xfc, 0x24, 0x2f, 0xee, 0x63, 0x96, 0x64, - 0x34, 0xd3, 0x9a, 0xbe, 0x34, 0x87, 0xf5, 0x47, 0xfa, 0x86, 0x37, 0xbf, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x58, 0x7a, 0xad, 0xd9, 0x97, 0x01, 0x00, 0x00, + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0x31, 0x4e, 0xc3, 0x30, + 0x14, 0x86, 0x63, 0x5a, 0xb5, 0xd4, 0x45, 0x40, 0xad, 0x0e, 0x51, 0x87, 0xb4, 0x2a, 0x4b, 0xa7, + 0x98, 0x96, 0xb5, 0x0c, 0x14, 0x89, 0x4e, 0x20, 0x94, 0x32, 0xb1, 0x20, 0x37, 0x35, 0x49, 0x84, + 0x62, 0x47, 0xb1, 0x13, 0x31, 0x70, 0x08, 0xce, 0xc1, 0x45, 0xe8, 0xd8, 0x91, 0x09, 0x50, 0x7b, + 0x11, 0x64, 0xc7, 0x81, 0xb0, 0xfd, 0x7e, 0xfe, 0xbf, 0xf7, 0x3f, 0xfb, 0x41, 0x9b, 0xca, 0x10, + 0xd3, 0x3c, 0xc6, 0xf9, 0x18, 0x07, 0x94, 0x51, 0x11, 0x09, 0x37, 0x49, 0xb9, 0xe4, 0x08, 0x52, + 0x19, 0xba, 0x34, 0x8f, 0xdd, 0x7c, 0xdc, 0xeb, 0x56, 0x5c, 0xaa, 0xa4, 0x1d, 0xbd, 0x6e, 0xc0, + 0x03, 0xae, 0x25, 0x56, 0xaa, 0xa8, 0x0e, 0xdf, 0x01, 0x3c, 0x98, 0x17, 0x9d, 0x16, 0x92, 0x48, + 0x8a, 0xa6, 0x70, 0x9f, 0xf8, 0x3e, 0xcf, 0x98, 0x14, 0x36, 0x18, 0xd4, 0x46, 0xed, 0x49, 0xcf, + 0xfd, 0xeb, 0xed, 0x1a, 0xef, 0x45, 0x61, 0x99, 0xd5, 0xd7, 0x9f, 0x7d, 0xcb, 0xfb, 0x25, 0xd0, + 0x29, 0x6c, 0x24, 0x24, 0x25, 0xb1, 0xb0, 0xf7, 0x06, 0x60, 0xd4, 0x9e, 0xa0, 0x2a, 0x7b, 0xab, + 0x6f, 0x0c, 0x63, 0x7c, 0x68, 0x0e, 0x3b, 0x8f, 0x19, 0x93, 0xfc, 0x89, 0xb2, 0x87, 0x98, 0x24, + 0x49, 0xc4, 0x02, 0x61, 0xd7, 0x74, 0x70, 0xb7, 0x0a, 0x5f, 0x65, 0xec, 0x4e, 0x99, 0x0c, 0x7e, + 0x5c, 0x42, 0xd7, 0x86, 0x19, 0xbe, 0xc0, 0xc3, 0xff, 0xc3, 0x21, 0x1b, 0x36, 0xc9, 0x6a, 0x95, + 0x52, 0xa1, 0x5e, 0x02, 0x46, 0x2d, 0xaf, 0x3c, 0x22, 0x04, 0xeb, 0x3e, 0x5f, 0x51, 0x3d, 0x64, + 0xcb, 0xd3, 0x1a, 0x4d, 0x61, 0x53, 0x48, 0x9e, 0x92, 0x80, 0x9a, 0xf8, 0x4e, 0x35, 0x5e, 0x7f, + 0xce, 0xec, 0x48, 0x65, 0xbf, 0x7d, 0xf5, 0x9b, 0x8b, 0xc2, 0xe9, 0x95, 0xc8, 0xec, 0x7c, 0xbd, + 0x75, 0xc0, 0x66, 0xeb, 0x80, 0xef, 0xad, 0x03, 0x5e, 0x77, 0x8e, 0xb5, 0xd9, 0x39, 0xd6, 0xc7, + 0xce, 0xb1, 0xee, 0x4f, 0x82, 0x48, 0x86, 0xd9, 0xd2, 0xf5, 0x79, 0x8c, 0x6f, 0xa2, 0x65, 0x94, + 0x66, 0x97, 0x21, 0x89, 0x18, 0x66, 0x5a, 0xe3, 0x67, 0xb5, 0xa2, 0x65, 0x43, 0x6f, 0xe3, 0xec, + 0x27, 0x00, 0x00, 0xff, 0xff, 0x43, 0x29, 0x65, 0x1b, 0xe1, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -194,6 +205,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.FuntokenMappings) > 0 { + for iNdEx := len(m.FuntokenMappings) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FuntokenMappings[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } { size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -297,6 +322,12 @@ func (m *GenesisState) Size() (n int) { } l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) + if len(m.FuntokenMappings) > 0 { + for _, e := range m.FuntokenMappings { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -425,6 +456,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FuntokenMappings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FuntokenMappings = append(m.FuntokenMappings, FunToken{}) + if err := m.FuntokenMappings[len(m.FuntokenMappings)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/evm/keeper/evm_state.go b/x/evm/keeper/evm_state.go index 715105978..d7ee7f3ab 100644 --- a/x/evm/keeper/evm_state.go +++ b/x/evm/keeper/evm_state.go @@ -128,7 +128,7 @@ func (k Keeper) SetParams(ctx sdk.Context, params evm.Params) { k.EvmState.ModuleParams.Set(ctx, params) } -// SetState update contract storage, delete if value is empty. +// SetState updates contract storage and delete if value is empty. func (state EvmState) SetAccState( ctx sdk.Context, addr eth.EthAddr, stateKey eth.EthHash, stateValue []byte, ) { diff --git a/x/evm/keeper/funtoken_state.go b/x/evm/keeper/funtoken_state.go new file mode 100644 index 000000000..22326d1f1 --- /dev/null +++ b/x/evm/keeper/funtoken_state.go @@ -0,0 +1,84 @@ +// Copyright (c) 2023-2024 Nibi, Inc. +package keeper + +import ( + "github.com/NibiruChain/collections" + "github.com/NibiruChain/nibiru/eth" + "github.com/NibiruChain/nibiru/x/evm" + funtoken "github.com/NibiruChain/nibiru/x/evm" + sdkcodec "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + gethcommon "github.com/ethereum/go-ethereum/common" +) + +type funtokenPrimaryKeyType = []byte +type funtokenValueType = funtoken.FunToken + +// FunTokenState isolates the key-value stores (collections) for fungible token +// mappings. This struct is written as an extension of the default indexed map to +// add utility functions. +type FunTokenState struct { + collections.IndexedMap[funtokenPrimaryKeyType, funtokenValueType, IndexesFunToken] +} + +func NewFunTokenState( + cdc sdkcodec.BinaryCodec, + storeKey storetypes.StoreKey, +) FunTokenState { + primaryKeyEncoder := eth.KeyEncoderBytes + valueEncoder := collections.ProtoValueEncoder[funtokenValueType](cdc) + idxMap := collections.NewIndexedMap( + storeKey, evm.KeyPrefixFunTokens, primaryKeyEncoder, valueEncoder, + IndexesFunToken{ + ERC20Addr: collections.NewMultiIndex( + storeKey, evm.KeyPrefixFunTokenIdxErc20, + collections.StringKeyEncoder, // indexing key (IK): ERC-20 addr + primaryKeyEncoder, + func(v evm.FunToken) string { return v.Erc20Addr }, + ), + BankDenom: collections.NewMultiIndex( + storeKey, evm.KeyPrefixFunTokenIdxBankDenom, + collections.StringKeyEncoder, // indexing key (IK): Coin denom + primaryKeyEncoder, + func(v evm.FunToken) string { return v.BankDenom }, + ), + }, + ) + return FunTokenState{IndexedMap: idxMap} +} + +func (idxs IndexesFunToken) IndexerList() []collections.Indexer[funtokenPrimaryKeyType, funtokenValueType] { + return []collections.Indexer[funtokenPrimaryKeyType, funtokenValueType]{ + idxs.ERC20Addr, + idxs.BankDenom, + } +} + +// IndexesFunToken: Abstraction for indexing over the FunToken store. +type IndexesFunToken struct { + // ERC20Addr (MultiIndex): Index FunToken by ERC-20 contract address. + // - indexing key (IK): ERC-20 addr + // - primary key (PK): FunToken ID + // - value (V): FunToken value + ERC20Addr collections.MultiIndex[string, funtokenPrimaryKeyType, funtokenValueType] + + // BankDenom (MultiIndex): Index FunToken by coin denomination + // - indexing key (IK): Coin denom + // - primary key (PK): FunToken ID + // - value (V): FunToken value + BankDenom collections.MultiIndex[string, funtokenPrimaryKeyType, funtokenValueType] +} + +// Insert adds an [evm.FunToken] to state with defensive validation. Errors if +// the given inputs would result in a corrupted [evm.FunToken]. +func (fun FunTokenState) SafeInsert( + ctx sdk.Context, erc20 gethcommon.Address, bankDenom string, isMadeFromCoin bool, +) error { + funtoken := evm.NewFunToken(erc20, bankDenom, isMadeFromCoin) + if err := funtoken.Validate(); err != nil { + return err + } + fun.Insert(ctx, funtoken.ID(), funtoken) + return nil +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 41c26113b..e809b7577 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -32,6 +32,10 @@ type Keeper struct { // EvmState isolates the key-value stores (collections) for the x/evm module. EvmState EvmState + // FunTokens isolates the key-value stores (collections) for fungible token + // mappings. + FunTokens FunTokenState + // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account. authority sdk.AccAddress @@ -49,6 +53,8 @@ type Keeper struct { tracer string } +// NewKeeper is a constructor for an x/evm [Keeper]. This function is necessary +// because the [Keeper] struct has private fields. func NewKeeper( cdc codec.BinaryCodec, storeKey, transientKey storetypes.StoreKey, @@ -67,6 +73,7 @@ func NewKeeper( transientKey: transientKey, authority: authority, EvmState: NewEvmState(cdc, storeKey, transientKey), + FunTokens: NewFunTokenState(cdc, storeKey), accountKeeper: accKeeper, bankKeeper: bankKeeper, stakingKeeper: stakingKeeper, diff --git a/x/evm/query_test.go b/x/evm/query_test.go deleted file mode 100644 index 7c6e54992..000000000 --- a/x/evm/query_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2023-2024 Nibi, Inc. -package evm - -import ( - "github.com/stretchr/testify/suite" - - "github.com/NibiruChain/nibiru/x/common" -) - -type TestSuite struct { - suite.Suite -} - -// TestNilQueries: Checks that all expected sad paths for nil msgs error -func (s *TestSuite) TestNilQueries() { - for _, testCase := range []func() error{ - func() error { - var req *QueryEthAccountRequest = nil - return req.Validate() - }, - func() error { - var req *QueryNibiruAccountRequest = nil - return req.Validate() - }, - func() error { - var req *QueryValidatorAccountRequest = nil - _, err := req.Validate() - return err - }, - func() error { - var req *QueryBalanceRequest = nil - return req.Validate() - }, - func() error { - var req *QueryStorageRequest = nil - return req.Validate() - }, - func() error { - var req *QueryCodeRequest = nil - return req.Validate() - }, - func() error { - var req *EthCallRequest = nil - return req.Validate() - }, - func() error { - var req *QueryTraceTxRequest = nil - return req.Validate() - }, - func() error { - var req *QueryTraceBlockRequest = nil - return req.Validate() - }, - } { - err := testCase() - s.Require().ErrorContains(err, common.ErrNilGrpcMsg.Error()) - } -} From 9271ed02a4b391aae622bc252aa97c3cd06dcc7f Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 24 Jun 2024 15:40:03 -0500 Subject: [PATCH 3/7] chore: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a9986ed3..046b50a86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#1914](https://github.com/NibiruChain/nibiru/pull/1914) - refactor(evm): Remove dead code and document non-EVM ante handler- [#1917](https://github.com/NibiruChain/nibiru/pull/1917) - test(e2e-evm): TypeScript support. Type generation from compiled contracts. Formatter for TS code. - [#1917](https://github.com/NibiruChain/nibiru/pull/1917) - test(e2e-evm): TypeScript support. Type generation from compiled contracts. Formatter for TS code. - [#1922](https://github.com/NibiruChain/nibiru/pull/1922) - feat(evm): tracer option is read from the config. +- [#1936](https://github.com/NibiruChain/nibiru/pull/1936) - feat(evm): EVM fungible token protobufs and encoding tests #### Dapp modules: perp, spot, oracle, etc From e11195fb8cb1f0f06af8552b7b87122fe9517ad3 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 24 Jun 2024 15:48:49 -0500 Subject: [PATCH 4/7] chore: linter --- eth/hex_test.go | 5 ++--- x/evm/evm_test.go | 3 ++- x/evm/keeper/funtoken_state.go | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/eth/hex_test.go b/eth/hex_test.go index 6d07ade07..5d526d09c 100644 --- a/eth/hex_test.go +++ b/eth/hex_test.go @@ -3,8 +3,9 @@ package eth_test import ( "fmt" - "github.com/NibiruChain/nibiru/eth" "github.com/ethereum/go-ethereum/common" + + "github.com/NibiruChain/nibiru/eth" ) var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ @@ -23,7 +24,6 @@ var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ // upper case will all produce the same `HexAddr` when passed to // `eth.NewHexAddrFromStr`. func (s *Suite) TestHexAddr_NewHexAddr() { - // InputAddrVariation: An instance of a "hexAddr" that derives to the // expected Ethereum address and results in the same string representation. type InputAddrVariation struct { @@ -90,7 +90,6 @@ func (s *Suite) TestHexAddr_NewHexAddr() { }, }, } { - want := tcGroup.want for _, tc := range tcGroup.hexAddrs { tcName := fmt.Sprintf("want %s, %s", want, tc.testCaseName) diff --git a/x/evm/evm_test.go b/x/evm/evm_test.go index afb6743b7..500d65fbf 100644 --- a/x/evm/evm_test.go +++ b/x/evm/evm_test.go @@ -5,9 +5,10 @@ import ( "strconv" "testing" + "github.com/stretchr/testify/suite" + "github.com/NibiruChain/nibiru/eth" "github.com/NibiruChain/nibiru/x/evm" - "github.com/stretchr/testify/suite" ) type TestSuite struct { diff --git a/x/evm/keeper/funtoken_state.go b/x/evm/keeper/funtoken_state.go index 22326d1f1..f66f094e5 100644 --- a/x/evm/keeper/funtoken_state.go +++ b/x/evm/keeper/funtoken_state.go @@ -3,13 +3,14 @@ package keeper import ( "github.com/NibiruChain/collections" - "github.com/NibiruChain/nibiru/eth" - "github.com/NibiruChain/nibiru/x/evm" - funtoken "github.com/NibiruChain/nibiru/x/evm" sdkcodec "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" gethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/NibiruChain/nibiru/eth" + "github.com/NibiruChain/nibiru/x/evm" + funtoken "github.com/NibiruChain/nibiru/x/evm" ) type funtokenPrimaryKeyType = []byte From 656e73f3f20ac8546ba0cbfb3ec30081335bfd0e Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Mon, 24 Jun 2024 20:54:03 -0500 Subject: [PATCH 5/7] feat(eth): finish todos for hex.go --- eth/hex.go | 36 ++++++++++------------ eth/hex_test.go | 55 ++++++++++++++++++++++++++++++---- x/evm/evm.go | 2 +- x/evm/evm_test.go | 3 +- x/evm/keeper/funtoken_state.go | 6 ++-- 5 files changed, 73 insertions(+), 29 deletions(-) diff --git a/eth/hex.go b/eth/hex.go index 594d411e6..a76acfbab 100644 --- a/eth/hex.go +++ b/eth/hex.go @@ -8,12 +8,6 @@ import ( /////////// HexAddr -// TODO: UD-DEBUG: The eth.Addr should map to only one HexString -// TODO: UD-DEBUG: The eth.Addr should be derivable from HexString -// TODO: Constructor should be safe (errorable) -// TODO: UD-DEBUG: HexString -> bytes -> eth.Addr == HexString -> eth.Addr -// TODO: UD-DEBUG: validate: HexString === HexString -> HexString(eth.Addr.Hex()) - // HexAddr: An ERC55-comlpiant hexadecimal-encoded string representing the 20 // byte address of an Ethereum account. type HexAddr string @@ -22,6 +16,17 @@ func NewHexAddr(addr EthAddr) HexAddr { return HexAddr(addr.Hex()) } +func NewHexAddrFromStr(addr string) (HexAddr, error) { + hexAddr := HexAddr(gethcommon.HexToAddress(addr).Hex()) + if !gethcommon.IsHexAddress(addr) { + return hexAddr, fmt.Errorf( + "%s: input \"%s\" is not an ERC55-compliant, 20 byte hex address", + HexAddrError, addr, + ) + } + return hexAddr, hexAddr.Valid() +} + const HexAddrError = "HexAddrError" func (h HexAddr) Valid() error { @@ -31,7 +36,7 @@ func (h HexAddr) Valid() error { if !gethcommon.IsHexAddress(haveAddr) || haveAddr != wantAddr { return fmt.Errorf( - "%s: Etherem address is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", + "%s: Ethereum address is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", HexAddrError, haveAddr, wantAddr, ) } @@ -39,22 +44,13 @@ func (h HexAddr) Valid() error { return nil } -func NewHexAddrFromStr(addr string) HexAddr { - return HexAddr(gethcommon.HexToAddress(addr).Hex()) -} - func (h HexAddr) ToAddr() EthAddr { return gethcommon.HexToAddress(string(h)) } -// func (h HexAddr) Bytes() []byte { -// return gethcommon.Hex2Bytes( -// strings.TrimPrefix(string(h), "0x"), -// ) -// } +// ToBytes gets the string representation of the underlying address. +func (h HexAddr) ToBytes() []byte { + return h.ToAddr().Bytes() +} func (h HexAddr) String() string { return h.ToAddr().Hex() } - -func (h HexAddr) FromBytes(bz []byte) HexAddr { - return HexAddr(gethcommon.BytesToAddress(bz).Hex()) -} diff --git a/eth/hex_test.go b/eth/hex_test.go index 5d526d09c..f428b471b 100644 --- a/eth/hex_test.go +++ b/eth/hex_test.go @@ -2,10 +2,12 @@ package eth_test import ( "fmt" + "strconv" - "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/NibiruChain/nibiru/eth" + "github.com/NibiruChain/nibiru/x/common/set" ) var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ @@ -14,6 +16,48 @@ var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ eth.HexAddr("0x1111111111111111111112222222222223333323"), } +func (s *Suite) TestHexAddr_UniqueMapping() { + type CorrectAnswer struct { + gethAddrOut gethcommon.Address + hexAddrOut eth.HexAddr + } + + for tcIdx, tc := range []struct { + equivSet set.Set[string] + }{ + { + equivSet: set.New( + "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + "0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED", + "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + "0X5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED", + ), + }, + } { + s.Run(strconv.Itoa(tcIdx), func() { + s.T().Log("Show that each member of the set is equivalent") + var answer CorrectAnswer + for idx, equivHexAddrString := range tc.equivSet.ToSlice() { + gethAddrOut := gethcommon.HexToAddress(equivHexAddrString) + hexAddrOut, err := eth.NewHexAddrFromStr(equivHexAddrString) + s.NoError(err) + if idx == 0 { + answer = CorrectAnswer{ + gethAddrOut: gethAddrOut, + hexAddrOut: hexAddrOut, + } + continue + } + + s.Equal(answer.gethAddrOut, gethAddrOut) + s.Equal(answer.gethAddrOut, hexAddrOut.ToAddr()) + s.Equal(answer.hexAddrOut, hexAddrOut) + } + }) + } +} + // TestHexAddr_NewHexAddr: Test to showcase the flexibility of inputs that can be // passed to `eth.NewHexAddrFromStr` and result in a "valid" `HexAddr` that preserves // bijectivity with `gethcommon.Address` and has a canonical string @@ -94,23 +138,24 @@ func (s *Suite) TestHexAddr_NewHexAddr() { for _, tc := range tcGroup.hexAddrs { tcName := fmt.Sprintf("want %s, %s", want, tc.testCaseName) s.Run(tcName, func() { - got := eth.NewHexAddrFromStr(tc.hexAddr) - err := got.Valid() + got, err := eth.NewHexAddrFromStr(tc.hexAddr) // gethcommon.Address input should give the same thing - got2 := eth.NewHexAddr(common.HexToAddress(tc.hexAddr)) + got2 := eth.NewHexAddr(gethcommon.HexToAddress(tc.hexAddr)) if tc.wantNotEqual { s.NotEqual(want, got) s.NotEqual(want.ToAddr(), got.ToAddr()) s.NotEqual(want, got2) s.NotEqual(want.ToAddr(), got2.ToAddr()) + s.Require().Error(err) + return } else { // string input should give the canonical HexAddr s.Equal(want, got) s.Equal(want.ToAddr(), got.ToAddr()) // gethcommon.Address input should give the same thing - got2 := eth.NewHexAddr(common.HexToAddress(tc.hexAddr)) + got2 := eth.NewHexAddr(gethcommon.HexToAddress(tc.hexAddr)) s.Equal(want, got2) s.Equal(want.ToAddr(), got2.ToAddr()) } diff --git a/x/evm/evm.go b/x/evm/evm.go index 99973ef7e..06d990079 100644 --- a/x/evm/evm.go +++ b/x/evm/evm.go @@ -45,7 +45,7 @@ func (fun FunToken) Validate() error { haveAddr := fun.Erc20Addr if haveAddr != wantAddr { return errValidateFunToken(fmt.Sprintf( - "ERC20 addr is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", + "Etherem address is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", haveAddr, wantAddr, )) } diff --git a/x/evm/evm_test.go b/x/evm/evm_test.go index 500d65fbf..bbbbe2ce1 100644 --- a/x/evm/evm_test.go +++ b/x/evm/evm_test.go @@ -5,6 +5,7 @@ import ( "strconv" "testing" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" "github.com/NibiruChain/nibiru/eth" @@ -37,7 +38,7 @@ func (s *TestSuite) TestFunToken() { }, { bankDenom: "unibi", - erc20Addr: eth.NewHexAddrFromStr("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed").String(), + erc20Addr: eth.NewHexAddr(gethcommon.HexToAddress("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")).String(), wantErr: "", }, { diff --git a/x/evm/keeper/funtoken_state.go b/x/evm/keeper/funtoken_state.go index f66f094e5..b4f1a1981 100644 --- a/x/evm/keeper/funtoken_state.go +++ b/x/evm/keeper/funtoken_state.go @@ -13,8 +13,10 @@ import ( funtoken "github.com/NibiruChain/nibiru/x/evm" ) -type funtokenPrimaryKeyType = []byte -type funtokenValueType = funtoken.FunToken +type ( + funtokenPrimaryKeyType = []byte + funtokenValueType = funtoken.FunToken +) // FunTokenState isolates the key-value stores (collections) for fungible token // mappings. This struct is written as an extension of the default indexed map to From b2286cf20763d4c763c56b2005dbcb1ab0991567 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Tue, 25 Jun 2024 18:26:41 -0500 Subject: [PATCH 6/7] feat(eth): finalize protobuf impl for eth.HexAddr --- eth/hex.go | 72 +++++++++++++ eth/hex_test.go | 60 ++++++++++- proto/eth/evm/v1/evm.proto | 5 +- x/evm/evm.go | 25 ++--- x/evm/evm.pb.go | 178 ++++++++++++++++----------------- x/evm/evm_test.go | 34 ++++--- x/evm/keeper/funtoken_state.go | 8 +- 7 files changed, 254 insertions(+), 128 deletions(-) diff --git a/eth/hex.go b/eth/hex.go index a76acfbab..3c5c502af 100644 --- a/eth/hex.go +++ b/eth/hex.go @@ -1,8 +1,10 @@ package eth import ( + "encoding/json" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" gethcommon "github.com/ethereum/go-ethereum/common" ) @@ -12,6 +14,8 @@ import ( // byte address of an Ethereum account. type HexAddr string +var _ sdk.CustomProtobufType = (*HexAddr)(nil) + func NewHexAddr(addr EthAddr) HexAddr { return HexAddr(addr.Hex()) } @@ -27,6 +31,16 @@ func NewHexAddrFromStr(addr string) (HexAddr, error) { return hexAddr, hexAddr.Valid() } +// MustNewHexAddrFromStr is the same as [NewHexAddrFromStr], except it panics +// when there's an error. +func MustNewHexAddrFromStr(addr string) HexAddr { + hexAddr, err := NewHexAddrFromStr(addr) + if err != nil { + panic(err) + } + return hexAddr +} + const HexAddrError = "HexAddrError" func (h HexAddr) Valid() error { @@ -54,3 +68,61 @@ func (h HexAddr) ToBytes() []byte { } func (h HexAddr) String() string { return h.ToAddr().Hex() } + +// Marshal implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h HexAddr) Marshal() ([]byte, error) { + return []byte(h), nil +} + +// MarshalJSON returns the [HexAddr] as JSON bytes. +// Implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h HexAddr) MarshalJSON() ([]byte, error) { + return []byte("\"" + h.String() + "\""), nil // a string is already JSON +} + +// MarshalTo serializes a pre-allocated byte slice ("data") directly into the +// [HexAddr] value, avoiding unnecessary memory allocations. +// MarshalTo implements the gogo proto custom type interface. +// Implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h *HexAddr) MarshalTo(data []byte) (n int, err error) { + bz := []byte{} + copy(data, bz) + hexAddr, err := NewHexAddrFromStr(string(bz)) + *h = hexAddr + return h.Size(), err +} + +// Unmarshal implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h *HexAddr) Unmarshal(data []byte) error { + hexAddr, err := NewHexAddrFromStr(string(data)) + *h = hexAddr + return err +} + +// UnmarshalJSON implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h *HexAddr) UnmarshalJSON(bz []byte) error { + text := new(string) + if err := json.Unmarshal(bz, text); err != nil { + return err + } + + hexAddr, err := NewHexAddrFromStr(*text) + if err != nil { + return err + } + + *h = hexAddr + + return nil +} + +// Size implements the gogo proto custom type interface. +// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md +func (h HexAddr) Size() int { + return len(h) +} diff --git a/eth/hex_test.go b/eth/hex_test.go index f428b471b..8d11fafce 100644 --- a/eth/hex_test.go +++ b/eth/hex_test.go @@ -3,6 +3,7 @@ package eth_test import ( "fmt" "strconv" + "strings" gethcommon "github.com/ethereum/go-ethereum/common" @@ -11,9 +12,9 @@ import ( ) var threeValidAddrs []eth.HexAddr = []eth.HexAddr{ - eth.HexAddr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), - eth.HexAddr("0xAe967917c465db8578ca9024c205720b1a3651A9"), - eth.HexAddr("0x1111111111111111111112222222222223333323"), + eth.MustNewHexAddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), + eth.MustNewHexAddrFromStr("0xAe967917c465db8578ca9024c205720b1a3651A9"), + eth.MustNewHexAddrFromStr("0x1111111111111111111112222222222223333323"), } func (s *Suite) TestHexAddr_UniqueMapping() { @@ -216,3 +217,56 @@ func (s *Suite) TestHexAddr_Valid() { }) } } + +func withQuotes(s string) string { return fmt.Sprintf("\"%s\"", s) } + +func withoutQuotes(s string) string { + return strings.TrimPrefix(strings.TrimSuffix(s, "\""), "\"") +} + +func (s *Suite) TestProtobufEncoding() { + for tcIdx, tc := range []struct { + given eth.HexAddr + json string + wantErr string + }{ + { + given: threeValidAddrs[0], + json: withQuotes(threeValidAddrs[0].String()), + }, + { + given: threeValidAddrs[1], + json: withQuotes(threeValidAddrs[1].String()), + }, + { + given: threeValidAddrs[2], + json: withQuotes(threeValidAddrs[2].String()), + }, + } { + s.Run(strconv.Itoa(tcIdx), func() { + givenMut := tc.given + jsonBz, err := givenMut.MarshalJSON() + s.NoError(err) + s.Equal(tc.json, string(jsonBz)) + + err = (&givenMut).UnmarshalJSON(jsonBz) + s.NoError(err) + s.Equal(givenMut, tc.given, + "Given -> MarshalJSON -> UnmarshalJSON returns a different value than the given when it should be an identity operation (no-op). test case #%d", tcIdx) + + bz, err := tc.given.Marshal() + s.NoError(err) + jsonBzWithoutQuotes := withoutQuotes(tc.json) + s.Equal(jsonBzWithoutQuotes, string(bz), + "Marshaling to bytes gives different value than the test case specifies. test case #%d", tcIdx) + + err = (&givenMut).Unmarshal(bz) + s.NoError(err) + s.Equal(tc.given, givenMut, + "Given -> Marshal -> Unmarshal returns a different value than the given when it should be an identity operation (no-op). test case #%d", tcIdx) + + s.Equal(len(tc.given), tc.given.Size()) + s.Equal(len(tc.json), tc.given.Size()+2) + }) + } +} diff --git a/proto/eth/evm/v1/evm.proto b/proto/eth/evm/v1/evm.proto index aa961cbf9..4ce9aeeda 100644 --- a/proto/eth/evm/v1/evm.proto +++ b/proto/eth/evm/v1/evm.proto @@ -12,7 +12,10 @@ option go_package = "github.com/NibiruChain/nibiru/x/evm"; // "Coin" type in Golang. message FunToken { // Hexadecimal address of the ERC20 token to which the `FunToken` maps - string erc20_addr = 1; + string erc20_addr = 1 [ + (gogoproto.customtype) = "github.com/NibiruChain/nibiru/eth.HexAddr", + (gogoproto.nullable) = false + ]; // bank_denom: Coin denomination in the Bank Module. string bank_denom = 2; diff --git a/x/evm/evm.go b/x/evm/evm.go index 06d990079..08612c9d9 100644 --- a/x/evm/evm.go +++ b/x/evm/evm.go @@ -7,13 +7,15 @@ import ( "github.com/cometbft/cometbft/crypto/tmhash" sdk "github.com/cosmos/cosmos-sdk/types" gethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/NibiruChain/nibiru/eth" ) // FIXME: Explore problems arrising from ERC1155 creating multiple fungible // tokens that are valid ERC20s with the same address. // https://github.com/NibiruChain/nibiru/issues/1933 func (fun FunToken) ID() []byte { - return newFunTokenIDFromStr(fun.Erc20Addr, fun.BankDenom) + return newFunTokenIDFromStr(fun.Erc20Addr.String(), fun.BankDenom) } func NewFunTokenID(erc20 gethcommon.Address, bankDenom string) []byte { @@ -34,21 +36,10 @@ func (fun FunToken) Validate() error { return errValidateFunToken(err.Error()) } - if !gethcommon.IsHexAddress(fun.Erc20Addr) { - return errValidateFunToken( - fmt.Sprintf("ERC20 addr is not a valid, hex-encoded Ethereum address (%s)", fun.Erc20Addr), - ) + if err := fun.Erc20Addr.Valid(); err != nil { + return errValidateFunToken(err.Error()) } - // Check address encoding bijectivity - wantAddr := fun.ERC20Addr().Hex() - haveAddr := fun.Erc20Addr - if haveAddr != wantAddr { - return errValidateFunToken(fmt.Sprintf( - "Etherem address is not represented as expected. We have encoding \"%s\" and instead need \"%s\" (gethcommon.Address.Hex)", - haveAddr, wantAddr, - )) - } return nil } @@ -59,12 +50,8 @@ func NewFunToken( erc20 gethcommon.Address, bankDenom string, isMadeFromCoin bool, ) FunToken { return FunToken{ - Erc20Addr: erc20.Hex(), + Erc20Addr: eth.NewHexAddr(erc20), BankDenom: bankDenom, IsMadeFromCoin: isMadeFromCoin, } } - -func (fun FunToken) ERC20Addr() gethcommon.Address { - return gethcommon.HexToAddress(fun.Erc20Addr) -} diff --git a/x/evm/evm.pb.go b/x/evm/evm.pb.go index 0661925f8..8607ee45b 100644 --- a/x/evm/evm.pb.go +++ b/x/evm/evm.pb.go @@ -5,6 +5,7 @@ package evm import ( fmt "fmt" + github_com_NibiruChain_nibiru_eth "github.com/NibiruChain/nibiru/eth" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -29,7 +30,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // "Coin" type in Golang. type FunToken struct { // Hexadecimal address of the ERC20 token to which the `FunToken` maps - Erc20Addr string `protobuf:"bytes,1,opt,name=erc20_addr,json=erc20Addr,proto3" json:"erc20_addr,omitempty"` + Erc20Addr github_com_NibiruChain_nibiru_eth.HexAddr `protobuf:"bytes,1,opt,name=erc20_addr,json=erc20Addr,proto3,customtype=github.com/NibiruChain/nibiru/eth.HexAddr" json:"erc20_addr"` // bank_denom: Coin denomination in the Bank Module. BankDenom string `protobuf:"bytes,2,opt,name=bank_denom,json=bankDenom,proto3" json:"bank_denom,omitempty"` // True if the `FunToken` mapping was created from an existing bank coin and @@ -71,13 +72,6 @@ func (m *FunToken) XXX_DiscardUnknown() { var xxx_messageInfo_FunToken proto.InternalMessageInfo -func (m *FunToken) GetErc20Addr() string { - if m != nil { - return m.Erc20Addr - } - return "" -} - func (m *FunToken) GetBankDenom() string { if m != nil { return m.BankDenom @@ -667,77 +661,78 @@ func init() { func init() { proto.RegisterFile("eth/evm/v1/evm.proto", fileDescriptor_98abbdadb327b7d0) } var fileDescriptor_98abbdadb327b7d0 = []byte{ - // 1108 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0x4f, 0x6f, 0xdb, 0x36, - 0x14, 0x8f, 0x63, 0x39, 0x96, 0x69, 0xa7, 0x76, 0x59, 0xaf, 0xd3, 0x5a, 0x2c, 0x0a, 0xd4, 0x4b, - 0x06, 0x74, 0xf1, 0x9a, 0x61, 0x18, 0xd0, 0xa1, 0x03, 0xa2, 0x34, 0xc5, 0x9a, 0xa5, 0x45, 0xc1, - 0xba, 0x3b, 0xec, 0x22, 0xd0, 0xd2, 0xab, 0xac, 0x59, 0x12, 0x0d, 0x92, 0xf2, 0x9c, 0x0f, 0x30, - 0x60, 0xc7, 0x5d, 0x77, 0xeb, 0xc7, 0x29, 0x76, 0xea, 0x71, 0x27, 0x61, 0x48, 0x2f, 0x9b, 0x8f, - 0xfe, 0x04, 0x03, 0x49, 0x39, 0x76, 0x3a, 0x60, 0x27, 0xbf, 0xdf, 0xef, 0xc7, 0xf7, 0x47, 0xef, - 0x3d, 0xd2, 0xa8, 0x0f, 0x72, 0x3c, 0x80, 0x59, 0x36, 0x98, 0x3d, 0x50, 0x3f, 0x87, 0x53, 0xce, - 0x24, 0xc3, 0x08, 0xe4, 0xf8, 0x50, 0xc1, 0xd9, 0x83, 0x3b, 0xfd, 0x98, 0xc5, 0x4c, 0xd3, 0x03, - 0x65, 0x99, 0x13, 0x9e, 0x40, 0xf6, 0x93, 0x22, 0x1f, 0xb2, 0x09, 0xe4, 0xf8, 0x53, 0x84, 0x80, - 0x87, 0x47, 0x5f, 0x04, 0x34, 0x8a, 0xb8, 0x53, 0xdb, 0xaf, 0x1d, 0xb4, 0x48, 0x4b, 0x33, 0xc7, - 0x51, 0xc4, 0x95, 0x3c, 0xa2, 0xf9, 0x24, 0x88, 0x20, 0x67, 0x99, 0xb3, 0x6d, 0x64, 0xc5, 0x3c, - 0x56, 0x04, 0xfe, 0x0c, 0xdd, 0x4c, 0x44, 0x90, 0xd1, 0x08, 0x82, 0xd7, 0x9c, 0x65, 0x41, 0xc8, - 0x92, 0xdc, 0xa9, 0xef, 0xd7, 0x0e, 0x6c, 0x72, 0x23, 0x11, 0xcf, 0x68, 0x04, 0x4f, 0x38, 0xcb, - 0x4e, 0x58, 0x92, 0x7b, 0xbf, 0xd7, 0xd1, 0xce, 0x0b, 0xca, 0x69, 0x26, 0xf0, 0x03, 0xd4, 0x82, - 0x59, 0x56, 0xc5, 0xd4, 0x29, 0xfd, 0xfe, 0xb2, 0x74, 0x7b, 0x17, 0x34, 0x4b, 0x1f, 0x7a, 0x57, - 0x92, 0x47, 0x6c, 0x98, 0x65, 0x26, 0xd1, 0x23, 0xb4, 0x0b, 0x39, 0x1d, 0xa5, 0x10, 0x84, 0x1c, - 0xa8, 0x04, 0x5d, 0x8a, 0xed, 0x3b, 0xcb, 0xd2, 0xed, 0x57, 0x6e, 0x9b, 0xb2, 0x47, 0x3a, 0x06, - 0x9f, 0x68, 0x88, 0xbf, 0x46, 0xed, 0x95, 0x4e, 0xd3, 0xd4, 0x54, 0xe8, 0xdf, 0x5e, 0x96, 0x2e, - 0xbe, 0xee, 0x4c, 0xd3, 0xd4, 0x23, 0xa8, 0x72, 0xa5, 0x69, 0x8a, 0x8f, 0x11, 0x82, 0xb9, 0xe4, - 0x34, 0x80, 0x64, 0x2a, 0x1c, 0x6b, 0xbf, 0x7e, 0x50, 0xf7, 0xbd, 0xcb, 0xd2, 0x6d, 0x9d, 0x2a, - 0xf6, 0xf4, 0xe9, 0x0b, 0xb1, 0x2c, 0xdd, 0x9b, 0x55, 0x90, 0xab, 0x83, 0x1e, 0x69, 0x69, 0x70, - 0x9a, 0x4c, 0x05, 0x3e, 0x42, 0x1f, 0xd1, 0x34, 0x65, 0x3f, 0x07, 0x45, 0xae, 0xda, 0x0f, 0xa1, - 0x84, 0x28, 0x90, 0x73, 0xe1, 0xec, 0xe8, 0x3e, 0xdd, 0xd2, 0xe2, 0xab, 0xb5, 0x36, 0x9c, 0x0b, - 0xfc, 0x39, 0xc2, 0x34, 0x94, 0xc9, 0x0c, 0x82, 0x29, 0x87, 0x90, 0x65, 0xd3, 0x24, 0x05, 0xe1, - 0x34, 0xf7, 0xeb, 0x07, 0x2d, 0x72, 0xd3, 0x28, 0x2f, 0xd6, 0x02, 0x3e, 0x42, 0x1d, 0xd5, 0xb5, - 0x70, 0x4c, 0xf3, 0x1c, 0x52, 0xe1, 0xd8, 0xea, 0xa0, 0xdf, 0xbd, 0x2c, 0xdd, 0xf6, 0xe9, 0x0f, - 0xcf, 0x4e, 0x2a, 0x9a, 0xb4, 0x61, 0x96, 0xad, 0xc0, 0x43, 0xeb, 0xef, 0x37, 0x6e, 0xed, 0xcc, - 0xb2, 0x1b, 0xbd, 0x1d, 0x6f, 0x80, 0x1a, 0x2f, 0xa5, 0xea, 0x53, 0x0f, 0xd5, 0x27, 0x70, 0x51, - 0xad, 0x81, 0x32, 0x71, 0x1f, 0x35, 0x66, 0x34, 0x2d, 0xa0, 0x9a, 0xbd, 0x01, 0xde, 0x19, 0xea, - 0x0e, 0x39, 0xcd, 0x85, 0x2a, 0x85, 0xe5, 0xe7, 0x2c, 0x16, 0x18, 0x23, 0x6b, 0x4c, 0xc5, 0xb8, - 0xf2, 0xd5, 0x36, 0xbe, 0x87, 0xac, 0x94, 0xc5, 0xc2, 0xd9, 0xde, 0xaf, 0x1f, 0xb4, 0x8f, 0xba, - 0x87, 0xeb, 0xcd, 0x3c, 0x3c, 0x67, 0x31, 0xd1, 0xa2, 0xf7, 0xc7, 0x36, 0xaa, 0x9f, 0xb3, 0x18, - 0x3b, 0xa8, 0xa9, 0x76, 0x10, 0x84, 0xa8, 0x62, 0xac, 0x20, 0xbe, 0x8d, 0x76, 0x24, 0x9b, 0x26, - 0xa1, 0x09, 0xd4, 0x22, 0x15, 0x52, 0x29, 0x23, 0x2a, 0xa9, 0x1e, 0x67, 0x87, 0x68, 0x5b, 0xb5, - 0x62, 0x94, 0xb2, 0x70, 0x12, 0xe4, 0x45, 0x36, 0x02, 0xee, 0x58, 0xfb, 0xb5, 0x03, 0xcb, 0xef, - 0x2e, 0x4a, 0xb7, 0xad, 0xf9, 0xe7, 0x9a, 0x26, 0x9b, 0x00, 0xdf, 0x47, 0x4d, 0x39, 0x0f, 0x74, - 0xf5, 0x0d, 0xbd, 0x8d, 0xb7, 0x16, 0xa5, 0xdb, 0x95, 0xeb, 0x0f, 0xfc, 0x8e, 0x8a, 0x31, 0xd9, - 0x91, 0x73, 0xf5, 0x8b, 0x07, 0xc8, 0x96, 0xf3, 0x20, 0xc9, 0x23, 0x98, 0xeb, 0x11, 0x5a, 0x7e, - 0x7f, 0x51, 0xba, 0xbd, 0x8d, 0xe3, 0x4f, 0x95, 0x46, 0x9a, 0x72, 0xae, 0x0d, 0x7c, 0x1f, 0x21, - 0x53, 0x92, 0xce, 0xd0, 0xd4, 0x19, 0x76, 0x17, 0xa5, 0xdb, 0xd2, 0xac, 0x8e, 0xbd, 0x36, 0xb1, - 0x87, 0x1a, 0x26, 0xb6, 0xad, 0x63, 0x77, 0x16, 0xa5, 0x6b, 0xa7, 0x2c, 0x36, 0x31, 0x8d, 0xa4, - 0x5a, 0xc5, 0x21, 0x63, 0x33, 0x88, 0x9c, 0x96, 0x5e, 0xa2, 0x15, 0xf4, 0x7e, 0xd9, 0x46, 0xf6, - 0x70, 0x4e, 0x40, 0x14, 0xa9, 0xc4, 0x4f, 0x50, 0x2f, 0x64, 0xb9, 0xe4, 0x34, 0x94, 0xc1, 0xb5, - 0xd6, 0xfa, 0x77, 0x97, 0xa5, 0xfb, 0xb1, 0xd9, 0xda, 0x0f, 0x4f, 0x78, 0xa4, 0xbb, 0xa2, 0x8e, - 0xab, 0xfe, 0xf7, 0x51, 0x63, 0x94, 0xb2, 0xea, 0xfe, 0x77, 0x88, 0x01, 0xf8, 0x5c, 0x77, 0x4d, - 0xcf, 0x57, 0x0d, 0xa0, 0x7d, 0x74, 0x77, 0x73, 0xbe, 0x1f, 0xac, 0x87, 0x7f, 0xfb, 0x6d, 0xe9, - 0x6e, 0x2d, 0x4b, 0xf7, 0x86, 0xc9, 0x5a, 0x79, 0x7a, 0xaa, 0xab, 0x7a, 0x7d, 0x7a, 0xa8, 0xce, - 0x41, 0xea, 0x71, 0x75, 0x88, 0x32, 0xf1, 0x1d, 0x64, 0x73, 0x98, 0x01, 0x97, 0x10, 0xe9, 0xb1, - 0xd8, 0xe4, 0x0a, 0xe3, 0x4f, 0x90, 0x1d, 0x53, 0x11, 0x14, 0x02, 0x22, 0x33, 0x03, 0xd2, 0x8c, - 0xa9, 0x78, 0x25, 0x20, 0x7a, 0x68, 0xfd, 0xfa, 0xc6, 0xdd, 0xf2, 0x28, 0x6a, 0x1f, 0x87, 0x21, - 0x08, 0x31, 0x2c, 0xa6, 0x29, 0xfc, 0xcf, 0x6e, 0x1d, 0xa1, 0x8e, 0x90, 0x8c, 0xd3, 0x18, 0x82, - 0x09, 0x5c, 0x54, 0x1b, 0x66, 0xf6, 0xa5, 0xe2, 0xbf, 0x87, 0x0b, 0x41, 0x36, 0x41, 0x95, 0xe2, - 0x9f, 0x3a, 0x6a, 0x0f, 0x39, 0x0d, 0xe1, 0x84, 0xe5, 0xaf, 0x93, 0x58, 0x6f, 0xa9, 0x82, 0xab, - 0x57, 0xb4, 0x42, 0x2a, 0xb7, 0x4c, 0x32, 0x60, 0x85, 0xac, 0xee, 0xd0, 0x0a, 0x2a, 0x0f, 0x0e, - 0x30, 0x87, 0x50, 0x37, 0xd0, 0x22, 0x15, 0xc2, 0x5f, 0xa1, 0xdd, 0x28, 0x11, 0xfa, 0x45, 0x12, - 0x92, 0x86, 0x13, 0xf3, 0xf9, 0x7e, 0x6f, 0x51, 0xba, 0x9d, 0x4a, 0x78, 0xa9, 0x78, 0x72, 0x0d, - 0xe1, 0x6f, 0x50, 0x77, 0xed, 0xa6, 0xab, 0x35, 0x4f, 0x8c, 0x8f, 0x17, 0xa5, 0x7b, 0xe3, 0xea, - 0xa8, 0x56, 0xc8, 0x07, 0x58, 0xcd, 0x38, 0x82, 0x51, 0x11, 0xeb, 0xb5, 0xb3, 0x89, 0x01, 0x8a, - 0x4d, 0x93, 0x2c, 0x91, 0x7a, 0xcd, 0x1a, 0xc4, 0x00, 0x55, 0x5f, 0xf5, 0x60, 0x66, 0x90, 0x31, - 0x7e, 0xe1, 0xb4, 0xd7, 0xf5, 0x19, 0xe1, 0x99, 0xe6, 0xc9, 0x35, 0x84, 0x7d, 0x84, 0x2b, 0x37, - 0x0e, 0xb2, 0xe0, 0x79, 0xa0, 0x2f, 0x6f, 0x47, 0xfb, 0xea, 0x2b, 0x64, 0x54, 0xa2, 0xc5, 0xc7, - 0x54, 0x52, 0xf2, 0x1f, 0x06, 0x7f, 0x8b, 0xb0, 0x69, 0x6b, 0xf0, 0x93, 0x60, 0x79, 0x10, 0xea, - 0xd6, 0x3b, 0xbb, 0x7a, 0xa9, 0x75, 0x7e, 0xa3, 0x9a, 0x91, 0x90, 0x9e, 0x41, 0x67, 0x82, 0xe5, - 0x86, 0x39, 0xb3, 0x6c, 0xab, 0xd7, 0x38, 0xb3, 0xec, 0x66, 0xcf, 0x3e, 0xb3, 0x6c, 0xd4, 0x6b, - 0x5f, 0x35, 0xa2, 0xfa, 0x16, 0x72, 0x6b, 0x85, 0x37, 0x8a, 0xf4, 0x1f, 0xbd, 0xbd, 0xdc, 0xab, - 0xbd, 0xbb, 0xdc, 0xab, 0xfd, 0x75, 0xb9, 0x57, 0xfb, 0xed, 0xfd, 0xde, 0xd6, 0xbb, 0xf7, 0x7b, - 0x5b, 0x7f, 0xbe, 0xdf, 0xdb, 0xfa, 0xf1, 0x5e, 0x9c, 0xc8, 0x71, 0x31, 0x3a, 0x0c, 0x59, 0x36, - 0x78, 0x9e, 0x8c, 0x12, 0x5e, 0x9c, 0x8c, 0x69, 0x92, 0x0f, 0x72, 0x6d, 0x0f, 0xe6, 0xea, 0x8f, - 0x79, 0xb4, 0xa3, 0xff, 0x77, 0xbf, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x18, 0xc6, 0x36, - 0xb1, 0x07, 0x00, 0x00, + // 1135 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x55, 0xcf, 0x6e, 0xdb, 0xc6, + 0x13, 0xb6, 0x2c, 0xca, 0xa2, 0x56, 0x72, 0xa4, 0x6c, 0xf4, 0xcb, 0x8f, 0x4d, 0x50, 0xd3, 0x60, + 0x2e, 0x0e, 0x90, 0x5a, 0xb5, 0x8b, 0xa2, 0x40, 0x8a, 0x14, 0x30, 0x1d, 0x07, 0x89, 0xeb, 0x04, + 0xc6, 0xc6, 0xe9, 0xa1, 0x17, 0x62, 0x45, 0x4e, 0x28, 0xd6, 0x24, 0x57, 0xd8, 0x5d, 0xaa, 0xf4, + 0x03, 0x14, 0xe8, 0xb1, 0xd7, 0xde, 0x72, 0xea, 0xb3, 0x04, 0x3d, 0xe5, 0x58, 0xf4, 0x40, 0x14, + 0xce, 0xa5, 0xd5, 0xd1, 0x4f, 0x50, 0xec, 0x2e, 0x65, 0xd9, 0x29, 0x90, 0x13, 0xe7, 0xfb, 0xbe, + 0x9d, 0x3f, 0x9c, 0x19, 0x2e, 0xd1, 0x10, 0xe4, 0x64, 0x04, 0xb3, 0x6c, 0x34, 0xdb, 0x51, 0x8f, + 0xed, 0x29, 0x67, 0x92, 0x61, 0x04, 0x72, 0xb2, 0xad, 0xe0, 0x6c, 0xe7, 0xce, 0x30, 0x66, 0x31, + 0xd3, 0xf4, 0x48, 0x59, 0xe6, 0x84, 0xf7, 0x5b, 0x03, 0xd9, 0x4f, 0x8a, 0xfc, 0x84, 0x9d, 0x42, + 0x8e, 0x8f, 0x11, 0x02, 0x1e, 0xee, 0x7e, 0x1e, 0xd0, 0x28, 0xe2, 0x4e, 0x63, 0xb3, 0xb1, 0xd5, + 0xf1, 0x77, 0xde, 0x56, 0xee, 0xca, 0x9f, 0x95, 0x7b, 0x3f, 0x4e, 0xe4, 0xa4, 0x18, 0x6f, 0x87, + 0x2c, 0x1b, 0xbd, 0x48, 0xc6, 0x09, 0x2f, 0xf6, 0x27, 0x34, 0xc9, 0x47, 0xb9, 0xb6, 0x47, 0x2a, + 0xd1, 0x53, 0x28, 0xf7, 0xa2, 0x88, 0x93, 0x8e, 0x0e, 0xa2, 0x4c, 0xfc, 0x29, 0x42, 0x63, 0x9a, + 0x9f, 0x06, 0x11, 0xe4, 0x2c, 0x73, 0x56, 0x55, 0x44, 0xd2, 0x51, 0xcc, 0x63, 0x45, 0xe0, 0xfb, + 0xe8, 0x66, 0x22, 0x82, 0x8c, 0x46, 0x10, 0xbc, 0xe6, 0x2c, 0x0b, 0x42, 0x96, 0xe4, 0x4e, 0x73, + 0xb3, 0xb1, 0x65, 0x93, 0x1b, 0x89, 0x78, 0x4e, 0x23, 0x78, 0xc2, 0x59, 0xb6, 0xcf, 0x92, 0xdc, + 0xfb, 0xb5, 0x89, 0xd6, 0x8e, 0x29, 0xa7, 0x99, 0xc0, 0x3b, 0xa8, 0x03, 0xb3, 0xac, 0x8e, 0x69, + 0xaa, 0x1c, 0x5e, 0x54, 0xee, 0xe0, 0x8c, 0x66, 0xe9, 0x43, 0xef, 0x52, 0xf2, 0x88, 0x0d, 0xb3, + 0xcc, 0x24, 0x7a, 0x84, 0xd6, 0x21, 0xa7, 0xe3, 0x14, 0x82, 0x90, 0x03, 0x95, 0xa0, 0x4b, 0xb1, + 0x7d, 0xe7, 0xa2, 0x72, 0x87, 0xb5, 0xdb, 0x55, 0xd9, 0x23, 0x3d, 0x83, 0xf7, 0x35, 0xc4, 0x5f, + 0xa1, 0xee, 0x42, 0xa7, 0x69, 0x6a, 0x2a, 0xf4, 0x6f, 0x5f, 0x54, 0x2e, 0xbe, 0xee, 0x4c, 0xd3, + 0xd4, 0x23, 0xa8, 0x76, 0xa5, 0x69, 0x8a, 0xf7, 0x10, 0x82, 0x52, 0x72, 0x1a, 0x40, 0x32, 0x15, + 0x8e, 0xb5, 0xd9, 0xdc, 0x6a, 0xfa, 0xde, 0x79, 0xe5, 0x76, 0x0e, 0x14, 0x7b, 0xf0, 0xec, 0x58, + 0x5c, 0x54, 0xee, 0xcd, 0x3a, 0xc8, 0xe5, 0x41, 0x8f, 0x74, 0x34, 0x38, 0x48, 0xa6, 0x02, 0xef, + 0xa2, 0xff, 0xd1, 0x34, 0x65, 0x3f, 0x06, 0x45, 0xae, 0x46, 0x06, 0xa1, 0x84, 0x28, 0x90, 0xa5, + 0x70, 0xd6, 0x74, 0x9f, 0x6e, 0x69, 0xf1, 0xd5, 0x52, 0x3b, 0x29, 0x05, 0xfe, 0x0c, 0x61, 0x1a, + 0xca, 0x64, 0x06, 0xc1, 0x94, 0x43, 0xc8, 0xb2, 0x69, 0x92, 0x82, 0x70, 0xda, 0x9b, 0xcd, 0xad, + 0x0e, 0xb9, 0x69, 0x94, 0xe3, 0xa5, 0x80, 0x77, 0x51, 0x4f, 0x75, 0x2d, 0x9c, 0xd0, 0x3c, 0x87, + 0x54, 0x38, 0xb6, 0x3a, 0xe8, 0xf7, 0xcf, 0x2b, 0xb7, 0x7b, 0xf0, 0xdd, 0xf3, 0xfd, 0x9a, 0x26, + 0x5d, 0x98, 0x65, 0x0b, 0xf0, 0xd0, 0xfa, 0xfb, 0x8d, 0xdb, 0x38, 0xb4, 0xec, 0xd6, 0x60, 0xcd, + 0x1b, 0xa1, 0xd6, 0x4b, 0xa9, 0xfa, 0x34, 0x40, 0xcd, 0x53, 0x38, 0x33, 0x33, 0x21, 0xca, 0xc4, + 0x43, 0xd4, 0x9a, 0xd1, 0xb4, 0x80, 0x7a, 0xf6, 0x06, 0x78, 0x87, 0xa8, 0x7f, 0xc2, 0x69, 0x2e, + 0x54, 0x29, 0x2c, 0x3f, 0x62, 0xb1, 0xc0, 0x18, 0x59, 0x13, 0x2a, 0x26, 0xb5, 0xaf, 0xb6, 0xf1, + 0x3d, 0x64, 0xa5, 0x2c, 0x16, 0xce, 0xea, 0x66, 0x73, 0xab, 0xbb, 0xdb, 0xdf, 0x5e, 0x6e, 0xf3, + 0xf6, 0x11, 0x8b, 0x89, 0x16, 0xbd, 0xdf, 0x57, 0x51, 0xf3, 0x88, 0xc5, 0xd8, 0x41, 0x6d, 0xb5, + 0xb6, 0x20, 0x44, 0x1d, 0x63, 0x01, 0xf1, 0x6d, 0xb4, 0x26, 0xd9, 0x34, 0x09, 0x4d, 0xa0, 0x0e, + 0xa9, 0x91, 0x4a, 0x19, 0x51, 0x49, 0xf5, 0x38, 0x7b, 0x44, 0xdb, 0xaa, 0x15, 0xe3, 0x94, 0x85, + 0xa7, 0x41, 0x5e, 0x64, 0x63, 0xe0, 0x8e, 0xb5, 0xd9, 0xd8, 0xb2, 0xfc, 0xfe, 0xbc, 0x72, 0xbb, + 0x9a, 0x7f, 0xa1, 0x69, 0x72, 0x15, 0xe0, 0x07, 0xa8, 0x2d, 0xcb, 0x40, 0x57, 0xdf, 0xd2, 0xdb, + 0x78, 0x6b, 0x5e, 0xb9, 0x7d, 0xb9, 0x7c, 0xc1, 0xa7, 0x54, 0x4c, 0xc8, 0x9a, 0x2c, 0xd5, 0x13, + 0x8f, 0x90, 0x2d, 0xcb, 0x20, 0xc9, 0x23, 0x28, 0xf5, 0x08, 0x2d, 0x7f, 0x38, 0xaf, 0xdc, 0xc1, + 0x95, 0xe3, 0xcf, 0x94, 0x46, 0xda, 0xb2, 0xd4, 0x06, 0x7e, 0x80, 0x90, 0x29, 0x49, 0x67, 0x68, + 0xeb, 0x0c, 0xeb, 0xf3, 0xca, 0xed, 0x68, 0x56, 0xc7, 0x5e, 0x9a, 0xd8, 0x43, 0x2d, 0x13, 0xdb, + 0xd6, 0xb1, 0x7b, 0xf3, 0xca, 0xb5, 0x53, 0x16, 0x9b, 0x98, 0x46, 0x52, 0xad, 0xe2, 0x90, 0xb1, + 0x19, 0x44, 0x4e, 0x47, 0x2f, 0xd1, 0x02, 0x7a, 0x3f, 0xad, 0x22, 0xfb, 0xa4, 0x24, 0x20, 0x8a, + 0x54, 0xe2, 0x27, 0x68, 0x10, 0xb2, 0x5c, 0x72, 0x1a, 0xca, 0xe0, 0x5a, 0x6b, 0xfd, 0xbb, 0x17, + 0x95, 0xfb, 0x7f, 0xb3, 0xb5, 0x1f, 0x9e, 0xf0, 0x48, 0x7f, 0x41, 0xed, 0xd5, 0xfd, 0x1f, 0xa2, + 0xd6, 0x38, 0x65, 0xf5, 0xf7, 0xdf, 0x23, 0x06, 0xe0, 0x23, 0xdd, 0x35, 0x3d, 0x5f, 0x35, 0x80, + 0xee, 0xee, 0xdd, 0xab, 0xf3, 0xfd, 0x60, 0x3d, 0xfc, 0xdb, 0xea, 0x1a, 0xba, 0xa8, 0xdc, 0x1b, + 0x26, 0x6b, 0xed, 0xe9, 0xa9, 0xae, 0xea, 0xf5, 0x19, 0xa0, 0x26, 0x07, 0xa9, 0xc7, 0xd5, 0x23, + 0xca, 0xc4, 0x77, 0x90, 0xcd, 0x61, 0x06, 0x5c, 0x42, 0xa4, 0xc7, 0x62, 0x93, 0x4b, 0x8c, 0x3f, + 0x41, 0x76, 0x4c, 0x45, 0x50, 0x08, 0x88, 0xcc, 0x0c, 0x48, 0x3b, 0xa6, 0xe2, 0x95, 0x80, 0xe8, + 0xa1, 0xf5, 0xf3, 0x1b, 0x77, 0xc5, 0xa3, 0xa8, 0xbb, 0x17, 0x86, 0x20, 0xc4, 0x49, 0x31, 0x4d, + 0xe1, 0x23, 0xbb, 0xb5, 0x8b, 0x7a, 0x42, 0x32, 0x4e, 0x63, 0x08, 0x4e, 0xe1, 0xac, 0xde, 0x30, + 0xb3, 0x2f, 0x35, 0xff, 0x2d, 0x9c, 0x09, 0x72, 0x15, 0xd4, 0x29, 0xfe, 0x69, 0xa2, 0xee, 0x09, + 0xa7, 0x21, 0xec, 0xb3, 0xfc, 0x75, 0x12, 0xeb, 0x2d, 0x55, 0xb0, 0xbe, 0x78, 0x49, 0x8d, 0x54, + 0x6e, 0x99, 0x64, 0xc0, 0x0a, 0x59, 0x7f, 0x43, 0x0b, 0xa8, 0x3c, 0x38, 0x40, 0x09, 0xa1, 0x6e, + 0xa0, 0x45, 0x6a, 0x84, 0xbf, 0x44, 0xeb, 0x51, 0x22, 0xf4, 0x8d, 0x24, 0x24, 0x0d, 0x4f, 0xcd, + 0xeb, 0xfb, 0x83, 0x79, 0xe5, 0xf6, 0x6a, 0xe1, 0xa5, 0xe2, 0xc9, 0x35, 0x84, 0xbf, 0x46, 0xfd, + 0xa5, 0x9b, 0xae, 0xd6, 0x5c, 0x31, 0x3e, 0x9e, 0x57, 0xee, 0x8d, 0xcb, 0xa3, 0x5a, 0x21, 0x1f, + 0x60, 0x35, 0xe3, 0x08, 0xc6, 0x45, 0xac, 0xd7, 0xce, 0x26, 0x06, 0x28, 0x36, 0x4d, 0xb2, 0x44, + 0xea, 0x35, 0x6b, 0x11, 0x03, 0x54, 0x7d, 0xf5, 0x85, 0x99, 0x41, 0xc6, 0xf8, 0x99, 0xd3, 0x5d, + 0xd6, 0x67, 0x84, 0xe7, 0x9a, 0x27, 0xd7, 0x10, 0xf6, 0x11, 0xae, 0xdd, 0x38, 0xc8, 0x82, 0xe7, + 0x81, 0xfe, 0x78, 0x7b, 0xda, 0x57, 0x7f, 0x42, 0x46, 0x25, 0x5a, 0x7c, 0x4c, 0x25, 0x25, 0xff, + 0x61, 0xf0, 0x37, 0x08, 0x9b, 0xb6, 0x06, 0x3f, 0x08, 0x96, 0x07, 0xa1, 0x6e, 0xbd, 0xb3, 0xae, + 0x97, 0x5a, 0xe7, 0x37, 0xaa, 0x19, 0x09, 0x19, 0x18, 0x74, 0x28, 0x58, 0x6e, 0x98, 0x43, 0xcb, + 0xb6, 0x06, 0xad, 0x43, 0xcb, 0x6e, 0x0f, 0xec, 0x43, 0xcb, 0x46, 0x83, 0xee, 0x65, 0x23, 0xea, + 0x77, 0x21, 0xb7, 0x16, 0xf8, 0x4a, 0x91, 0xfe, 0xa3, 0xb7, 0xe7, 0x1b, 0x8d, 0x77, 0xe7, 0x1b, + 0x8d, 0xbf, 0xce, 0x37, 0x1a, 0xbf, 0xbc, 0xdf, 0x58, 0x79, 0xf7, 0x7e, 0x63, 0xe5, 0x8f, 0xf7, + 0x1b, 0x2b, 0xdf, 0xdf, 0xfb, 0xf8, 0x6f, 0xb5, 0x54, 0x3f, 0xf3, 0xf1, 0x9a, 0xfe, 0x57, 0x7f, + 0xf1, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x94, 0x04, 0x70, 0x58, 0xe5, 0x07, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -834,13 +829,16 @@ func (m *FunToken) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - if len(m.Erc20Addr) > 0 { - i -= len(m.Erc20Addr) - copy(dAtA[i:], m.Erc20Addr) - i = encodeVarintEvm(dAtA, i, uint64(len(m.Erc20Addr))) - i-- - dAtA[i] = 0xa + { + size := m.Erc20Addr.Size() + i -= size + if _, err := m.Erc20Addr.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvm(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -1336,10 +1334,8 @@ func (m *FunToken) Size() (n int) { } var l int _ = l - l = len(m.Erc20Addr) - if l > 0 { - n += 1 + l + sovEvm(uint64(l)) - } + l = m.Erc20Addr.Size() + n += 1 + l + sovEvm(uint64(l)) l = len(m.BankDenom) if l > 0 { n += 1 + l + sovEvm(uint64(l)) @@ -1625,7 +1621,9 @@ func (m *FunToken) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Erc20Addr = string(dAtA[iNdEx:postIndex]) + if err := m.Erc20Addr.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 2: if wireType != 2 { diff --git a/x/evm/evm_test.go b/x/evm/evm_test.go index bbbbe2ce1..8c6156a15 100644 --- a/x/evm/evm_test.go +++ b/x/evm/evm_test.go @@ -5,7 +5,6 @@ import ( "strconv" "testing" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" "github.com/NibiruChain/nibiru/eth" @@ -23,32 +22,43 @@ func TestSuite_RunAll(t *testing.T) { func (s *TestSuite) TestFunToken() { for testIdx, tc := range []struct { bankDenom string - erc20Addr string + erc20Addr eth.HexAddr wantErr string }{ { + // sad: Invalid bank denom bankDenom: "", - erc20Addr: "", + erc20Addr: eth.HexAddr(""), wantErr: "FunTokenError", }, { bankDenom: "unibi", - erc20Addr: "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", - wantErr: "not encoded as expected", + erc20Addr: eth.MustNewHexAddrFromStr("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"), + wantErr: "", }, { bankDenom: "unibi", - erc20Addr: eth.NewHexAddr(gethcommon.HexToAddress("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")).String(), + erc20Addr: eth.MustNewHexAddrFromStr("5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED"), wantErr: "", }, + { + // NOTE: notice how this one errors using the same happy path + // input as above because an unsafe constructor was used. + // Naked type overrides should not be used with eth.HexAddr. + // Always use NewHexAddr, NewHexAddrFromStr, or MustNewHexAddr... + bankDenom: "unibi", + erc20Addr: eth.HexAddr("5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"), + wantErr: "not encoded as expected", + }, + { bankDenom: "ibc/AAA/BBB", - erc20Addr: "0xE1aA1500b962528cBB42F05bD6d8A6032a85602f", + erc20Addr: eth.MustNewHexAddrFromStr("0xE1aA1500b962528cBB42F05bD6d8A6032a85602f"), wantErr: "", }, { bankDenom: "tf/contract-addr/subdenom", - erc20Addr: "0x6B2e60f1030aFa69F584829f1d700b47eE5Fc74a", + erc20Addr: eth.MustNewHexAddrFromStr("0x6B2e60f1030aFa69F584829f1d700b47eE5Fc74a"), wantErr: "", }, } { @@ -59,7 +69,7 @@ func (s *TestSuite) TestFunToken() { } err := funtoken.Validate() if tc.wantErr != "" { - s.Require().Error(err) + s.Require().Error(err, "funtoken %s", funtoken) return } s.Require().NoError(err) @@ -93,10 +103,10 @@ func (s *TestSuite) TestFunToken() { }, } { s.Run(tc.name, func() { - funA := evm.FunToken{Erc20Addr: tc.A} - funB := evm.FunToken{Erc20Addr: tc.B} + funA := evm.FunToken{Erc20Addr: eth.HexAddr(tc.A)} + funB := evm.FunToken{Erc20Addr: eth.HexAddr(tc.B)} - s.EqualValues(funA.ERC20Addr(), funB.ERC20Addr()) + s.EqualValues(funA.Erc20Addr.ToAddr(), funB.Erc20Addr.ToAddr()) }) } } diff --git a/x/evm/keeper/funtoken_state.go b/x/evm/keeper/funtoken_state.go index b4f1a1981..c713c1fc3 100644 --- a/x/evm/keeper/funtoken_state.go +++ b/x/evm/keeper/funtoken_state.go @@ -36,9 +36,11 @@ func NewFunTokenState( IndexesFunToken{ ERC20Addr: collections.NewMultiIndex( storeKey, evm.KeyPrefixFunTokenIdxErc20, - collections.StringKeyEncoder, // indexing key (IK): ERC-20 addr + eth.KeyEncoderEthAddr, // indexing key (IK): ERC-20 addr primaryKeyEncoder, - func(v evm.FunToken) string { return v.Erc20Addr }, + func(v evm.FunToken) gethcommon.Address { + return v.Erc20Addr.ToAddr() + }, ), BankDenom: collections.NewMultiIndex( storeKey, evm.KeyPrefixFunTokenIdxBankDenom, @@ -64,7 +66,7 @@ type IndexesFunToken struct { // - indexing key (IK): ERC-20 addr // - primary key (PK): FunToken ID // - value (V): FunToken value - ERC20Addr collections.MultiIndex[string, funtokenPrimaryKeyType, funtokenValueType] + ERC20Addr collections.MultiIndex[gethcommon.Address, funtokenPrimaryKeyType, funtokenValueType] // BankDenom (MultiIndex): Index FunToken by coin denomination // - indexing key (IK): Coin denom From ae624cb6dbb36234e562096240847193ae776f26 Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Tue, 25 Jun 2024 18:40:55 -0500 Subject: [PATCH 7/7] chore: small typos in comments --- eth/hex.go | 2 +- x/evm/keeper/evm_state.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/hex.go b/eth/hex.go index 3c5c502af..3e6cf0cde 100644 --- a/eth/hex.go +++ b/eth/hex.go @@ -10,7 +10,7 @@ import ( /////////// HexAddr -// HexAddr: An ERC55-comlpiant hexadecimal-encoded string representing the 20 +// HexAddr: An ERC55-compliant hexadecimal-encoded string representing the 20 // byte address of an Ethereum account. type HexAddr string diff --git a/x/evm/keeper/evm_state.go b/x/evm/keeper/evm_state.go index d7ee7f3ab..0f0013f1c 100644 --- a/x/evm/keeper/evm_state.go +++ b/x/evm/keeper/evm_state.go @@ -128,7 +128,7 @@ func (k Keeper) SetParams(ctx sdk.Context, params evm.Params) { k.EvmState.ModuleParams.Set(ctx, params) } -// SetState updates contract storage and delete if value is empty. +// SetState updates contract storage and deletes if the value is empty. func (state EvmState) SetAccState( ctx sdk.Context, addr eth.EthAddr, stateKey eth.EthHash, stateValue []byte, ) {