From 0e6afd8e12d84998efff135c529f2a532fa6390d Mon Sep 17 00:00:00 2001 From: Unique-Divine Date: Thu, 24 Oct 2024 05:17:27 -0500 Subject: [PATCH] fix(precompile-funtoken): modify StateDB after bank send operations --- x/evm/precompile/funtoken.go | 68 +++++++++++++++++++++++++++++++++-- x/evm/statedb/journal.go | 23 ------------ x/evm/statedb/journal_test.go | 8 ++--- x/evm/statedb/statedb.go | 15 +++++--- 4 files changed, 79 insertions(+), 35 deletions(-) diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index 3b453d597..610ccab05 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -7,15 +7,18 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" gethabi "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/NibiruChain/nibiru/v2/app/keepers" + "github.com/NibiruChain/nibiru/v2/eth" "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" evmkeeper "github.com/NibiruChain/nibiru/v2/x/evm/keeper" + "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) var _ vm.PrecompiledContract = (*precompileFunToken)(nil) @@ -148,7 +151,7 @@ func (p precompileFunToken) bankSend( // EVM account mints FunToken.BankDenom to module account amt := math.NewIntFromBigInt(amount) - coins := sdk.NewCoins(sdk.NewCoin(funtoken.BankDenom, amt)) + coinToSend := sdk.NewCoin(funtoken.BankDenom, amt) if funtoken.IsMadeFromCoin { // If the FunToken mapping was created from a bank coin, then the EVM account // owns the ERC20 contract and was the original minter of the ERC20 tokens. @@ -160,7 +163,7 @@ func (p precompileFunToken) bankSend( return } } else { - err = p.bankKeeper.MintCoins(ctx, evm.ModuleName, coins) + err = SafeMintCoins(ctx, evm.ModuleName, coinToSend, p.bankKeeper, start.StateDB) if err != nil { return nil, fmt.Errorf("mint failed for module \"%s\" (%s): contract caller %s: %w", evm.ModuleName, evm.EVM_MODULE_ADDRESS.Hex(), caller.Hex(), err, @@ -169,7 +172,14 @@ func (p precompileFunToken) bankSend( } // Transfer the bank coin - err = p.bankKeeper.SendCoinsFromModuleToAccount(ctx, evm.ModuleName, toAddr, coins) + err = SafeSendCoinFromModuleToAccount( + ctx, + evm.ModuleName, + toAddr, + coinToSend, + p.bankKeeper, + start.StateDB, + ) if err != nil { return nil, fmt.Errorf("send failed for module \"%s\" (%s): contract caller %s: %w", evm.ModuleName, evm.EVM_MODULE_ADDRESS.Hex(), caller.Hex(), err, @@ -181,6 +191,58 @@ func (p precompileFunToken) bankSend( return method.Outputs.Pack() } +func SafeMintCoins( + ctx sdk.Context, + moduleName string, + amt sdk.Coin, + bk bankkeeper.Keeper, + db *statedb.StateDB, +) error { + err := bk.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(amt)) + if err != nil { + return err + } + if amt.Denom == evm.EVMBankDenom { + evmBech32Addr := auth.NewModuleAddress(evm.ModuleName) + balAfter := bk.GetBalance(ctx, evmBech32Addr, amt.Denom).Amount.BigInt() + db.SetBalanceWei( + evm.EVM_MODULE_ADDRESS, + evm.NativeToWei(balAfter), + ) + } + + return nil +} + +func SafeSendCoinFromModuleToAccount( + ctx sdk.Context, + senderModule string, + recipientAddr sdk.AccAddress, + amt sdk.Coin, + bk bankkeeper.Keeper, + db *statedb.StateDB, +) error { + err := bk.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, sdk.NewCoins(amt)) + if err != nil { + return err + } + if amt.Denom == evm.EVMBankDenom { + evmBech32Addr := auth.NewModuleAddress(evm.ModuleName) + balAfterFrom := bk.GetBalance(ctx, evmBech32Addr, amt.Denom).Amount.BigInt() + db.SetBalanceWei( + evm.EVM_MODULE_ADDRESS, + evm.NativeToWei(balAfterFrom), + ) + + balAfterTo := bk.GetBalance(ctx, recipientAddr, amt.Denom).Amount.BigInt() + db.SetBalanceWei( + eth.NibiruAddrToEthAddr(recipientAddr), + evm.NativeToWei(balAfterTo), + ) + } + return nil +} + func (p precompileFunToken) decomposeBankSendArgs(args []any) ( erc20 gethcommon.Address, amount *big.Int, diff --git a/x/evm/statedb/journal.go b/x/evm/statedb/journal.go index 2a6ffe953..ac041b617 100644 --- a/x/evm/statedb/journal.go +++ b/x/evm/statedb/journal.go @@ -100,29 +100,6 @@ func (s *StateDB) DirtiesCount() int { dirtiesCount += dirtyCount } return dirtiesCount - // for addr := range s.Journal.dirties { - // obj := s.stateObjects[addr] - // // suicided without deletion means obj is dirty - // if obj.Suicided { - // dirtiesCount++ - // // continue - // } - // // dirty code means obj is dirty - // if obj.code != nil && obj.DirtyCode { - // dirtiesCount++ - // // continue - // } - - // // mismatch between dirty storage and origin means obj is dirty - // for k, v := range obj.DirtyStorage { - // // All object (k,v) tuples matching between dirty and origin storage - // // signifies that the entry is committed. - // if v != obj.OriginStorage[k] { - // dirtiesCount++ - // } - // } - // } - // return dirtiesCount } func (s *StateDB) Dirties() map[common.Address]int { diff --git a/x/evm/statedb/journal_test.go b/x/evm/statedb/journal_test.go index b7894bb98..2c19af77f 100644 --- a/x/evm/statedb/journal_test.go +++ b/x/evm/statedb/journal_test.go @@ -10,13 +10,11 @@ import ( "github.com/ethereum/go-ethereum/core/vm" serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" - "github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp" "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" "github.com/NibiruChain/nibiru/v2/x/evm/evmtest" "github.com/NibiruChain/nibiru/v2/x/evm/precompile/test" - precompiletest "github.com/NibiruChain/nibiru/v2/x/evm/precompile/test" "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) @@ -32,10 +30,10 @@ func (s *Suite) TestPrecompileSnapshots() { s.T().Log("Set up helloworldcounter.wasm") - wasmContract := precompiletest.SetupWasmContracts(&deps, &s.Suite)[1] + wasmContract := test.SetupWasmContracts(&deps, &s.Suite)[1] fmt.Printf("wasmContract: %s\n", wasmContract) assertionsBeforeRun := func(deps *evmtest.TestDeps) { - precompiletest.AssertWasmCounterState( + test.AssertWasmCounterState( &s.Suite, *deps, wasmContract, 0, ) } @@ -45,7 +43,7 @@ func (s *Suite) TestPrecompileSnapshots() { ) } assertionsAfterRun := func(deps *evmtest.TestDeps) { - precompiletest.AssertWasmCounterState( + test.AssertWasmCounterState( &s.Suite, *deps, wasmContract, 7, ) } diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index a29371431..223e92edb 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -295,18 +295,25 @@ func (s *StateDB) setStateObject(object *stateObject) { */ // AddBalance adds amount to the account associated with addr. -func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { +func (s *StateDB) AddBalance(addr common.Address, wei *big.Int) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { - stateObject.AddBalance(amount) + stateObject.AddBalance(wei) } } // SubBalance subtracts amount from the account associated with addr. -func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { +func (s *StateDB) SubBalance(addr common.Address, wei *big.Int) { stateObject := s.getOrNewStateObject(addr) if stateObject != nil { - stateObject.SubBalance(amount) + stateObject.SubBalance(wei) + } +} + +func (s *StateDB) SetBalanceWei(addr common.Address, wei *big.Int) { + stateObject := s.getOrNewStateObject(addr) + if stateObject != nil { + stateObject.SetBalance(wei) } }