8000 chore(evm): adjust extra decimals on stateDB methods by GAtom22 · Pull Request #2897 · evmos/evmos · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

chore(evm): adjust extra decimals on stateDB methods #2897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (evm) [#2872](https://github.com/evmos/evmos/pull/2872) Change `BankKeeper` for `BankWrapper` to manage EVM coin with different decimals.
- (evm) [#2873](https://github.com/evmos/evmos/pull/2873) Remove `BeginBlock` and replace `ChainID` with global config.
- (api) [#2884](https://github.com/evmos/evmos/pull/2884) Refactor to use a function to return `TxDataV2` in custom `GetSingers`.
- (evm) [#2897](https://github.com/evmos/evmos/pull/2897) Adjust extra decimals in `AddBalance` and `SubBalance` methods on `stateObject` in state DB.

## [v19.2.1](https://github.com/evmos/evmos/releases/tag/v19.2.1) - 2024-09-27

Expand Down
3 changes: 3 additions & 0 deletions x/evm/statedb/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/evmos/evmos/v20/x/evm/types"
"github.com/evmos/evmos/v20/x/evm/wrappers"
)

// Account is the Ethereum consensus representation of accounts.
Expand Down Expand Up @@ -100,6 +101,7 @@ func (s *stateObject) markSuicided() {
// AddBalance adds amount to s's balance.
// It is used to add funds to the destination account of a transfer.
func (s *stateObject) AddBalance(amount *big.Int) {
amount = wrappers.AdjustExtraDecimalsBigInt(amount)
if amount.Sign() == 0 {
return
}
Expand All @@ -109,6 +111,7 @@ func (s *stateObject) AddBalance(amount *big.Int) {
// SubBalance removes amount from s's balance.
// It is used to remove funds from the origin account of a transfer.
func (s *stateObject) SubBalance(amount *big.Int) {
amount = wrappers.AdjustExtraDecimalsBigInt(amount)
if amount.Sign() == 0 {
return
}
Expand Down
10 changes: 5 additions & 5 deletions x/evm/wrappers/bank.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func NewBankWrapper(
func (w BankWrapper) MintAmountToAccount(ctx context.Context, recipientAddr sdk.AccAddress, amt *big.Int) error {
coin := sdk.Coin{Denom: config.GetEVMCoinDenom(), Amount: sdkmath.NewIntFromBigInt(amt)}

convertedCoin, err := convertEvmCoinFrom18Decimals(coin)
convertedCoin, err := ConvertEvmCoinFrom18Decimals(coin)
if err != nil {
return errors.Wrap(err, "failed to mint coin to account in bank wrapper")
}
Expand All @@ -60,7 +60,7 @@ func (w BankWrapper) MintAmountToAccount(ctx context.Context, recipientAddr sdk.
func (w BankWrapper) BurnAmountFromAccount(ctx context.Context, account sdk.AccAddress, amt *big.Int) error {
coin := sdk.Coin{Denom: config.GetEVMCoinDenom(), Amount: sdkmath.NewIntFromBigInt(amt)}

convertedCoin, err := convertEvmCoinFrom18Decimals(coin)
convertedCoin, err := ConvertEvmCoinFrom18Decimals(coin)
if err != nil {
return errors.Wrap(err, "failed to burn coins from account in bank wrapper")
}
Expand All @@ -83,14 +83,14 @@ func (w BankWrapper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom
// representation used in the evm.
coin := w.BankKeeper.GetBalance(ctx, addr, denom)

return mustConvertEvmCoinTo18Decimals(coin)
return MustConvertEvmCoinTo18Decimals(coin)
}

// SendCoinsFromAccountToModule wraps around the Cosmos SDK x/bank module's
// SendCoinsFromAccountToModule method to convert the evm coin, if present in
// the input, to its original representation.
func (w BankWrapper) SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, coins sdk.Coins) error {
convertedCoins := convertCoinsFrom18Decimals(coins)
convertedCoins := ConvertCoinsFrom18Decimals(coins)

return w.BankKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, convertedCoins)
}
Expand All @@ -99,7 +99,7 @@ func (w BankWrapper) SendCoinsFromAccountToModule(ctx context.Context, senderAdd
// SendCoinsFromModuleToAccount method to convert the evm coin, if present in
// the input, to its original representation.
func (w BankWrapper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, coins sdk.Coins) error {
convertedCoins := convertCoinsFrom18Decimals(coins)
convertedCoins := ConvertCoinsFrom18Decimals(coins)

return w.BankKeeper.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, convertedCoins)
}
27 changes: 21 additions & 6 deletions x/evm/wrappers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ package wrappers

import (
"fmt"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/evmos/evmos/v20/x/evm/config"
)

// mustConvertEvmCoinTo18Decimals converts the coin's Amount from its original
// MustConvertEvmCoinTo18Decimals converts the coin's Amount from its original
// representation into a 18 decimals. The function panics if coin denom is
// not the evm denom or in case of overflow.
func mustConvertEvmCoinTo18Decimals(coin sdk.Coin) sdk.Coin {
func MustConvertEvmCoinTo18Decimals(coin sdk.Coin) sdk.Coin {
if coin.Denom != config.GetEVMCoinDenom() {
panic(fmt.Sprintf("expected evm denom %s, received %s", config.GetEVMCoinDenom(), coin.Denom))
}
Expand All @@ -25,9 +26,9 @@ func mustConvertEvmCoinTo18Decimals(coin sdk.Coin) sdk.Coin {
return sdk.Coin{Denom: coin.Denom, Amount: newAmount}
}

// convertEvmCoinFrom18Decimals converts the coin's Amount from 18 decimals to its
// ConvertEvmCoinFrom18Decimals converts the coin's Amount from 18 decimals to its
// original representation. Return an error if the coin denom is not the EVM.
func convertEvmCoinFrom18Decimals(coin sdk.Coin) (sdk.Coin, error) {
func ConvertEvmCoinFrom18Decimals(coin sdk.Coin) (sdk.Coin, error) {
if coin.Denom != config.GetEVMCoinDenom() {
return sdk.Coin{}, fmt.Errorf("expected coin denom %s, received %s", config.GetEVMCoinDenom(), coin.Denom)
}
Expand All @@ -38,9 +39,9 @@ func convertEvmCoinFrom18Decimals(coin sdk.Coin) (sdk.Coin, error) {
return sdk.Coin{Denom: coin.Denom, Amount: newAmount}, nil
}

// convertCoinsFrom18Decimals returns the given coins with the Amount of the evm
// ConvertCoinsFrom18Decimals returns the given coins with the Amount of the evm
// coin converted from the 18 decimals representation to the original one.
func convertCoinsFrom18Decimals(coins sdk.Coins) sdk.Coins {
func ConvertCoinsFrom18Decimals(coins sdk.Coins) sdk.Coins {
evmDenom := config.GetEVMCoinDenom()

convertedCoins := make(sdk.Coins, len(coins))
Expand All @@ -56,3 +57,17 @@ func convertCoinsFrom18Decimals(coins sdk.Coins) sdk.Coins {
}
return convertedCoins
}

// AdjustExtraDecimalsBigInt replaces all extra decimals by zero of an amount with 18 decimals in big.Int when having a decimal configuration different than 18 decimals
func AdjustExtraDecimalsBigInt(amt *big.Int) *big.Int {
if amt.Sign() == 0 {
return amt
}
dec := config.GetEVMCoinDecimals()
if dec == config.EighteenDecimals {
return amt
}
scaleFactor := dec.ConversionFactor()
scaledDown := new(big.Int).Quo(amt, scaleFactor.BigInt())
return new(big.Int).Mul(scaledDown, scaleFactor.BigInt())
}
66 changes: 62 additions & 4 deletions x/evm/wrappers/utils_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Copyright Tharsis Labs Ltd.(Evmos)
// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE)

package wrappers
package wrappers_test

import (
5D32 "fmt"
"math/big"
"testing"

"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/evmos/evmos/v20/types"
"github.com/evmos/evmos/v20/x/evm/config"
"github.com/evmos/evmos/v20/x/evm/wrappers"

"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -76,7 +79,7 @@ func TestMustConvertEvmCoinTo18Decimals(t *testing.T) {

config.SetEVMCoinTEST(tc.evmCoinInfo)

coinConverted := mustConvertEvmCoinTo18Decimals(tc.coin)
coinConverted := wrappers.MustConvertEvmCoinTo18Decimals(tc.coin)

if !tc.expPanic {
require.Equal(t, tc.expCoin, coinConverted, "expected a different coin")
Expand Down Expand Up @@ -140,7 +143,7 @@ func TestConvertEvmCoinFrom18Decimals(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
config.SetEVMCoinTEST(tc.evmCoinInfo)

coinConverted, err := convertEvmCoinFrom18Decimals(tc.coin)
coinConverted, err := wrappers.ConvertEvmCoinFrom18Decimals(tc.coin)

if !tc.expErr {
require.NoError(t, err)
Expand Down Expand Up @@ -198,8 +201,63 @@ func TestConvertCoinsFrom18Decimals(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
config.SetEVMCoinTEST(tc.evmCoinInfo)

coinConverted := convertCoinsFrom18Decimals(tc.coins)
coinConverted := wrappers.ConvertCoinsFrom18Decimals(tc.coins)
require.Equal(t, tc.expCoins, coinConverted, "expected a different coin")
})
}
}

func TestZeroExtraDecimalsBigInt(t *testing.T) {
testCases := []struct {
name string
amt *big.Int
exp *big.Int
}{
{
name: "almost 1: 0.99999...",
amt: big.NewInt(999999999999),
exp: big.NewInt(0),
},
{
name: "decimal < 5: 1.4",
amt: big.NewInt(14e11),
exp: big.NewInt(1e12),
},
{
name: "decimal < 5: 1.499999999999",
amt: big.NewInt(1499999999999),
exp: big.NewInt(1e12),
},
{
name: "decimal == 5: 1.5",
amt: big.NewInt(15e11),
exp: big.NewInt(1e12),
},
{
name: "decimal > 5: 1.9",
amt: big.NewInt(19e11),
exp: big.NewInt(1e12),
},
{
name: "1 wei",
amt: big.NewInt(1),
exp: big.NewInt(0),
},
}

for _, cfg := range []config.EvmCoinInfo{
{Denom: types.BaseDenom, Decimals: config.SixDecimals},
{Denom: types.BaseDenom, Decimals: config.EighteenDecimals},
} {
for _, tc := range testCases {
t.Run(fmt.Sprintf("%d dec - %s", cfg.Decimals, tc.name), func(t *testing.T) {
config.SetEVMCoinTEST(cfg)
res := wrappers.AdjustExtraDecimalsBigInt(tc.amt)
if cfg.Decimals == config.EighteenDecimals {
tc.exp = tc.amt
}
require.Equal(t, tc.exp, res)
})
}
}
}
Loading
0