From 5aca2916cc8c90e6081b4c503746236a736412ad Mon Sep 17 00:00:00 2001 From: niceDeve Date: Thu, 28 Apr 2022 19:02:58 +0800 Subject: [PATCH] bugfix: Update utils.go (#530) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update utils.go bugfix: compare 2 DenomUnit variable wrong because they are pointers * Bugfix:fetch decimal from cosmos coin metadata decimals := uint8(coinMetadata.DenomUnits[0].Exponent) The original code maybe OK for evmos itself. However, it may causes incorrect decimal value 1. in the metadata validation func: cosmos-sdk/x/bank/types/metadata.go: Metadata.Validate() it makes sure Denomination units are sorted in ascending order. 2. https://docs.evmos.org/modules/erc20/01_concepts.html "Coin Metadata to ERC20 details" informaiton * add unit test code for compare 2 donom metadata * revise testing code Co-authored-by: Andy Wronski Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> --- x/erc20/keeper/proposals.go | 6 ++- x/erc20/types/utils.go | 20 ++++++++- x/erc20/types/utils_test.go | 89 +++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/x/erc20/keeper/proposals.go b/x/erc20/keeper/proposals.go index c2bf1866..c90c5fd1 100644 --- a/x/erc20/keeper/proposals.go +++ b/x/erc20/keeper/proposals.go @@ -73,7 +73,11 @@ func (k Keeper) DeployERC20Contract( ctx sdk.Context, coinMetadata banktypes.Metadata, ) (common.Address, error) { - decimals := uint8(coinMetadata.DenomUnits[0].Exponent) + decimals := uint8(0) + if len(coinMetadata.DenomUnits) > 0 { + decimalsIdx := len(coinMetadata.DenomUnits) - 1 + decimals = uint8(coinMetadata.DenomUnits[decimalsIdx].Exponent) + } ctorArgs, err := contracts.ERC20MinterBurnerDecimalsContract.ABI.Pack( "", coinMetadata.Name, diff --git a/x/erc20/types/utils.go b/x/erc20/types/utils.go index 9956b165..74ee34d8 100644 --- a/x/erc20/types/utils.go +++ b/x/erc20/types/utils.go @@ -2,6 +2,7 @@ package types import ( "fmt" + "sort" "strings" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -26,7 +27,7 @@ func EqualMetadata(a, b banktypes.Metadata) error { } for i, v := range a.DenomUnits { - if v != b.DenomUnits[i] { + if (v.Exponent != b.DenomUnits[i].Exponent) || (v.Denom != b.DenomUnits[i].Denom) || !EqualStringSlice(v.Aliases, b.DenomUnits[i].Aliases) { return fmt.Errorf("metadata provided has different denom unit from stored, %s ≠ %s", a.DenomUnits[i], b.DenomUnits[i]) } } @@ -35,3 +36,20 @@ func EqualMetadata(a, b banktypes.Metadata) error { } return fmt.Errorf("metadata provided is different from stored") } + +// EqualStringSlice checks if two string slices are equal. +func EqualStringSlice(a, b []string) bool { + if len(a) != len(b) { + return false + } + + sort.Strings(a) + sort.Strings(b) + for idx := len(a) - 1; idx > -1; idx-- { + if a[idx] != b[idx] { + return false + } + } + + return true +} diff --git a/x/erc20/types/utils_test.go b/x/erc20/types/utils_test.go index 3dbbc0f1..11de88e2 100644 --- a/x/erc20/types/utils_test.go +++ b/x/erc20/types/utils_test.go @@ -3,6 +3,7 @@ package types import ( "testing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" ) @@ -25,3 +26,91 @@ func TestSanitizeERC20Name(t *testing.T) { require.Equal(t, tc.expErc20Name, name, tc.name) } } + +func TestEqualMetadata(t *testing.T) { + + base := "CoinBase" + display := "CoinDisplay" + name := "CoinName" + symbol := "CoinATOM" + description := "ATOM Coin" + decimal := uint32(18) + + // for metadata_A + denomUnits_A := []*banktypes.DenomUnit{ + { + Denom: base, + Exponent: 0, + Aliases: []string{base, "moreInfo"}, + }, + { + Denom: display, + Exponent: decimal, + Aliases: []string{display, "moreInfo"}, + }} + metadata_A := banktypes.Metadata{ + Base: base, + Display: display, + Name: name, + Symbol: symbol, + Description: description, + DenomUnits: denomUnits_A, + } + + // for metadata_B + denomUnits_B := []*banktypes.DenomUnit{ + { + Denom: base, + Exponent: 0, + Aliases: []string{"moreInfo", base}, + }, + { + Denom: display, + Exponent: decimal, + Aliases: []string{display, "moreInfo"}, + }} + metadata_B := banktypes.Metadata{ + Base: base, + Display: display, + Name: name, + Symbol: symbol, + Description: description, + DenomUnits: denomUnits_B, + } + + // for metadata_C + denomUnits_C := []*banktypes.DenomUnit{ + { + Denom: base, + Exponent: 0, + Aliases: []string{"moreInfo_YES", base}, + }, + { + Denom: display, + Exponent: decimal, + Aliases: []string{display, "moreInfo"}, + }} + metadata_C := banktypes.Metadata{ + Base: base, + Display: display, + Name: name, + Symbol: symbol, + Description: description, + DenomUnits: denomUnits_C, + } + + // metadata list + metadataList := []*banktypes.Metadata{ + &metadata_A, + &metadata_B, + &metadata_C, + } + + // validate each metadata + for _, md := range metadataList { + require.NoError(t, md.Validate()) + } + + require.NoError(t, EqualMetadata(metadata_A, metadata_B)) + require.NotEqual(t, EqualMetadata(metadata_A, metadata_C), nil) +}