diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e501763ac..dde589e6cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (rpc) [#521](https://github.com/crypto-org-chain/ethermint/pull/521) Align hash and miner in subscribe newHeads with eth_getBlockByNumber. * (rpc) [#516](https://github.com/crypto-org-chain/ethermint/pull/516) Avoid method eth_chainId crashed due to nil pointer on IsEIP155 check. * (cli) [#524](https://github.com/crypto-org-chain/ethermint/pull/524) Allow tx evm raw run for generate only when offline with evm-denom flag. +* (rpc) [#527](https://github.com/crypto-org-chain/ethermint/pull/527) Fix balance consistency between trace-block and state machine. ### Improvements diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 02e534f822..21c503f4e0 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -322,33 +322,40 @@ func (k *Keeper) ApplyMessageWithConfig( return nil, errorsmod.Wrap(types.ErrCallDisabled, "failed to call contract") } - stateDB := statedb.NewWithParams(ctx, k, cfg.TxConfig, cfg.Params.EvmDenom) - var evm *vm.EVM - if cfg.Overrides != nil { - if err := cfg.Overrides.Apply(stateDB); err != nil { - return nil, errorsmod.Wrap(err, "failed to apply state override") - } - } - evm = k.NewEVM(ctx, msg, cfg, stateDB) - leftoverGas := msg.GasLimit - sender := vm.AccountRef(msg.From) // Allow the tracer captures the tx level events, mainly the gas consumption. - vmCfg := evm.Config - if vmCfg.Tracer != nil { + leftoverGas := msg.GasLimit + senderAddr := sdk.AccAddress(msg.From.Bytes()) + if cfg.Tracer != nil { if cfg.DebugTrace { // msg.GasPrice should have been set to effective gas price - stateDB.SubBalance(sender.Address(), new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(msg.GasLimit))) - stateDB.SetNonce(sender.Address(), stateDB.GetNonce(sender.Address())+1) + amount := new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(msg.GasLimit)) + if err := k.SubBalance(ctx, senderAddr, sdk.NewCoins(sdk.NewCoin(cfg.Params.EvmDenom, sdkmath.NewIntFromBigInt(amount)))); err != nil { + return nil, errorsmod.Wrap(err, "failed to subtract balance") + } + if err := k.incrNonce(ctx, senderAddr); err != nil { + return nil, errorsmod.Wrap(err, "failed to increment nonce") + } } - vmCfg.Tracer.CaptureTxStart(leftoverGas) + cfg.Tracer.CaptureTxStart(leftoverGas) defer func() { if cfg.DebugTrace { - stateDB.AddBalance(sender.Address(), new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(leftoverGas))) + amount := new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(leftoverGas)) + k.AddBalance(ctx, senderAddr, sdk.NewCoins(sdk.NewCoin(cfg.Params.EvmDenom, sdkmath.NewIntFromBigInt(amount)))) } - vmCfg.Tracer.CaptureTxEnd(leftoverGas) + cfg.Tracer.CaptureTxEnd(leftoverGas) }() } + stateDB := statedb.NewWithParams(ctx, k, cfg.TxConfig, cfg.Params.EvmDenom) + var evm *vm.EVM + if cfg.Overrides != nil { + if err := cfg.Overrides.Apply(stateDB); err != nil { + return nil, errorsmod.Wrap(err, "failed to apply state override") + } + } + evm = k.NewEVM(ctx, msg, cfg, stateDB) + sender := vm.AccountRef(msg.From) + rules := cfg.Rules contractCreation := msg.To == nil intrinsicGas, err := k.GetEthIntrinsicGas(msg, rules, contractCreation) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index e718de0148..e4e6f0d9ae 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -138,6 +138,20 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated return nil } +func (k *Keeper) incrNonce(ctx sdk.Context, addr sdk.AccAddress) error { + acct := k.accountKeeper.GetAccount(ctx, addr) + if acct == nil { + acct = k.accountKeeper.NewAccountWithAddress(ctx, addr) + } + + if err := acct.SetSequence(acct.GetSequence() + 1); err != nil { + return err + } + + k.accountKeeper.SetAccount(ctx, acct) + return nil +} + // SetState update contract storage, delete if value is empty. func (k *Keeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))