Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

- (test) [#150](https://github.com/EscanBE/evermint/pull/150) Improve readability for test
- (evm) [#154](https://github.com/EscanBE/evermint/pull/154) Simplify code, force all ETH hardfork enabled
- (evm) [#156](https://github.com/EscanBE/evermint/pull/156) Refactor `x/evm` state transition code, use go-ethereum code and make usage of `NoBaseFee` flag.

### Bug Fixes

Expand Down
1 change: 0 additions & 1 deletion rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
return nil
}

// TODO ES: recheck this logic, look like something wrong, are both fields required to be Dynamic fee tx?
if args.MaxPriorityFeePerGas != nil && args.MaxFeePerGas != nil {
if err := checkRelationMaxPriorityFeePerGasAndMaxFeePerGas(); err != nil {
return args, err
Expand Down
11 changes: 11 additions & 0 deletions x/erc20/keeper/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/big"

errorsmod "cosmossdk.io/errors"

"github.com/EscanBE/evermint/v12/server/config"
evmtypes "github.com/EscanBE/evermint/v12/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -207,6 +208,16 @@ func (k Keeper) CallEVMWithData(
!commit, // isFake
)

// enable NoBaseFee for system call
enabled := k.evmKeeper.IsNoBaseFeeEnabled(ctx)
if !enabled {
// enable and restore
k.evmKeeper.SetFlagEnableNoBaseFee(ctx, true)
defer func() {
k.evmKeeper.SetFlagEnableNoBaseFee(ctx, false)
}()
}

res, err := k.evmKeeper.ApplyMessage(ctx, msg, evmtypes.NewNoOpTracer(), commit)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion x/erc20/keeper/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ func (suite *KeeperTestSuite) TestCallEVMWithData() {

res, err := suite.app.Erc20Keeper.CallEVMWithData(suite.ctx, tc.from, contract, data, false)
if tc.expPass {
suite.Require().NotNil(res)
suite.Require().NoError(err)
suite.Require().NotNil(res)
} else {
suite.Require().Errorf(err, "result: %v", res)
}
Expand Down
9 changes: 9 additions & 0 deletions x/erc20/keeper/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var _ erc20types.EVMKeeper = &MockEVMKeeper{}

type MockEVMKeeper struct {
mock.Mock
noBaseFee bool
}

func (m *MockEVMKeeper) GetParams(_ sdk.Context) evmtypes.Params {
Expand Down Expand Up @@ -53,6 +54,14 @@ func (m *MockEVMKeeper) ApplyMessage(_ sdk.Context, _ core.Message, _ vm.EVMLogg
return args.Get(0).(*evmtypes.MsgEthereumTxResponse), args.Error(1)
}

func (m *MockEVMKeeper) SetFlagEnableNoBaseFee(_ sdk.Context, enable bool) {
m.noBaseFee = enable
}

func (m *MockEVMKeeper) IsNoBaseFeeEnabled(_ sdk.Context) bool {
return m.noBaseFee
}

var _ bankkeeper.Keeper = &MockBankKeeper{}

type MockBankKeeper struct {
Expand Down
4 changes: 2 additions & 2 deletions x/erc20/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (suite *KeeperTestSuite) TestConvertCoinNativeCoin() {
cosmosBalance := suite.app.BankKeeper.GetBalance(suite.ctx, sender, metadataCoin.Base)

if tc.expPass {
suite.Require().NoError(err, tc.name)
suite.Require().NoError(err)

acc := suite.app.EvmKeeper.GetAccountWithoutBalance(suite.ctx, erc20)
if tc.selfdestructed {
Expand All @@ -225,7 +225,7 @@ func (suite *KeeperTestSuite) TestConvertCoinNativeCoin() {
suite.Require().Equal(balance.(*big.Int).Int64(), big.NewInt(tc.burn).Int64())
}
} else {
suite.Require().Error(err, tc.name)
suite.Require().Error(err)
}
})
}
Expand Down
2 changes: 2 additions & 0 deletions x/erc20/types/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type EVMKeeper interface {
GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account
EstimateGas(c context.Context, req *evmtypes.EthCallRequest) (*evmtypes.EstimateGasResponse, error)
ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*evmtypes.MsgEthereumTxResponse, error)
SetFlagEnableNoBaseFee(ctx sdk.Context, enable bool)
IsNoBaseFeeEnabled(ctx sdk.Context) bool
}

type (
Expand Down
110 changes: 60 additions & 50 deletions x/evm/handler_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package evm_test

import (
"fmt"
"math/big"
"testing"
"time"

feemarkettypes "github.com/EscanBE/evermint/v12/x/feemarket/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"

storetypes "cosmossdk.io/store/types"

"github.com/EscanBE/evermint/v12/app/helpers"
Expand All @@ -17,10 +21,6 @@ import (
tmjson "github.com/cometbft/cometbft/libs/json"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

feemarkettypes "github.com/EscanBE/evermint/v12/x/feemarket/types"

stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -55,13 +55,11 @@ type EvmTestSuite struct {
ethSigner ethtypes.Signer
from common.Address
to sdk.AccAddress

dynamicTxFee bool
}

// DoSetupTest setup test environment
func (suite *EvmTestSuite) DoSetupTest() {
checkTx := false
const checkTx = false

// account key
priv, err := ethsecp256k1.GenerateKey()
Expand All @@ -75,33 +73,10 @@ func (suite *EvmTestSuite) DoSetupTest() {
consAddress := sdk.ConsAddress(priv.PubKey().Address())

suite.app = helpers.EthSetup(checkTx, func(chainApp *chainapp.Evermint, genesis chainapp.GenesisState) chainapp.GenesisState {
if suite.dynamicTxFee { // TODO ES: check this option
feemarketGenesis := feemarkettypes.DefaultGenesisState()
genesis[feemarkettypes.ModuleName] = chainApp.AppCodec().MustMarshalJSON(feemarketGenesis)
}
return genesis
})

coins := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100000000000000)))
genesisState := helpers.NewTestGenesisState(suite.app.AppCodec())
b32address := sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), priv.PubKey().Address().Bytes())
balances := []banktypes.Balance{
{
Address: b32address,
Coins: coins,
},
{
Address: suite.app.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName).String(),
Coins: coins,
},
}
var bankGenesis banktypes.GenesisState
suite.app.AppCodec().MustUnmarshalJSON(genesisState[banktypes.ModuleName], &bankGenesis)
// Update balances and total supply
bankGenesis.Balances = append(bankGenesis.Balances, balances...)
bankGenesis.Supply = bankGenesis.Supply.Add(coins...).Add(coins...)
genesisState[banktypes.ModuleName] = suite.app.AppCodec().MustMarshalJSON(&bankGenesis)

stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
suite.Require().NoError(err)

Expand Down Expand Up @@ -153,9 +128,20 @@ func (suite *EvmTestSuite) DoSetupTest() {
suite.Require().NoError(err)
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
suite.Require().NoError(err)
suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
err = suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
suite.Require().NoError(err)

suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())

coins := sdk.NewCoins(sdk.NewCoin(constants.BaseDenom, sdkmath.NewInt(100000000000000)))
err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, coins)
suite.Require().NoError(err)
err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, coins)
suite.Require().NoError(err)
err = suite.app.BankKeeper.SendCoinsFromModuleToModule(suite.ctx, minttypes.ModuleName, authtypes.FeeCollectorName, coins)
suite.Require().NoError(err)
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, suite.from.Bytes(), coins)
suite.Require().NoError(err)
}

func (suite *EvmTestSuite) SetupTest() {
Expand Down Expand Up @@ -247,6 +233,10 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset

suite.zeroFeeMarket()

fmt.Println("Bal", suite.app.BankKeeper.GetAllBalances(suite.ctx, suite.from.Bytes()))

tc.malleate()
res, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, tx)

Expand Down Expand Up @@ -289,7 +279,7 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
ethTxParams := &evmtypes.EvmTxArgs{
From: suite.from,
ChainID: suite.chainID,
Nonce: 1,
Nonce: 0,
Amount: big.NewInt(0),
GasPrice: gasPrice,
GasLimit: gasLimit,
Expand All @@ -298,6 +288,8 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
tx := evmtypes.NewTx(ethTxParams)
suite.SignTx(tx)

suite.zeroFeeMarket()

response, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, tx)
suite.Require().NoError(err, "failed to handle eth tx msg")

Expand Down Expand Up @@ -372,7 +364,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
ethTxParams := &evmtypes.EvmTxArgs{
From: suite.from,
ChainID: suite.chainID,
Nonce: 1,
Nonce: 0,
Amount: big.NewInt(0),
GasPrice: gasPrice,
GasLimit: gasLimit,
Expand All @@ -381,6 +373,8 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
tx := evmtypes.NewTx(ethTxParams)
suite.SignTx(tx)

suite.zeroFeeMarket()

response, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, tx)
suite.Require().NoError(err, "failed to handle eth tx msg")
suite.Require().Equal(response.VmError, "", "failed to handle eth tx msg")
Expand All @@ -396,7 +390,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
ethTxParams = &evmtypes.EvmTxArgs{
From: suite.from,
ChainID: suite.chainID,
Nonce: 2,
Nonce: 1,
To: &receiver,
Amount: big.NewInt(0),
GasPrice: gasPrice,
Expand Down Expand Up @@ -443,7 +437,7 @@ func (suite *EvmTestSuite) TestSendTransaction() {
ethTxParams := &evmtypes.EvmTxArgs{
From: suite.from,
ChainID: suite.chainID,
Nonce: 1,
Nonce: 0,
To: &common.Address{0x1},
Amount: big.NewInt(1),
GasPrice: gasPrice,
Expand Down Expand Up @@ -554,7 +548,7 @@ func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
ethTxParams := &evmtypes.EvmTxArgs{
From: suite.from,
ChainID: suite.chainID,
Nonce: 1,
Nonce: 0,
Amount: big.NewInt(0),
GasPrice: gasPrice,
GasLimit: gasLimit,
Expand All @@ -563,8 +557,12 @@ func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
tx := evmtypes.NewTx(ethTxParams)
suite.SignTx(tx)

result, _ := suite.app.EvmKeeper.EthereumTx(suite.ctx, tx)
suite.Require().Equal("invalid opcode: opcode 0xa6 not defined", result.VmError, "correct evm error")
suite.zeroFeeMarket()

result, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, tx)
suite.Require().NoError(err)
suite.Require().NotNil(result)
suite.Equal("invalid opcode: opcode 0xa6 not defined", result.VmError, "correct evm error")

// TODO: snapshot checking
}
Expand All @@ -575,17 +573,17 @@ func (suite *EvmTestSuite) deployERC20Contract() common.Address {
ctorArgs, err := evmtypes.ERC20Contract.ABI.Pack("", suite.from, big.NewInt(10000000000))
suite.Require().NoError(err)
msg := ethtypes.NewMessage(
suite.from,
nil,
nonce,
big.NewInt(0),
2000000,
big.NewInt(1),
nil,
nil,
append(evmtypes.ERC20Contract.Bin, ctorArgs...),
nil,
true,
suite.from, // from
nil, // to
nonce, // nonce
big.NewInt(0), // amount
2000000, // gas limit
big.NewInt(1), // gas price
big.NewInt(1), // gas fee cap
big.NewInt(1), // gas tip cap
append(evmtypes.ERC20Contract.Bin, ctorArgs...), // data
nil, // access list
true, // is fake
)
rsp, err := k.ApplyMessage(suite.ctx, msg, nil, true)
suite.Require().NoError(err)
Expand Down Expand Up @@ -619,6 +617,8 @@ func (suite *EvmTestSuite) TestERC20TransferReverted() {
err := k.SetBalance(suite.ctx, suite.from, big.NewInt(1000000000000001))
suite.Require().NoError(err)

suite.zeroFeeMarket()

contract := suite.deployERC20Contract()

data, err := evmtypes.ERC20Contract.ABI.Pack("transfer", suite.from, big.NewInt(10))
Expand All @@ -645,7 +645,7 @@ func (suite *EvmTestSuite) TestERC20TransferReverted() {

txData, err := evmtypes.UnpackTxData(tx.Data)
suite.Require().NoError(err)
fees, err := evmkeeper.VerifyFee(txData, evmtypes.DefaultEVMDenom, baseFee, suite.ctx.IsCheckTx())
fees, err := evmkeeper.VerifyFee(txData, constants.BaseDenom, baseFee, suite.ctx.IsCheckTx())
suite.Require().NoError(err)
err = k.DeductTxCostsFromUserBalance(suite.ctx, fees, sdk.MustAccAddressFromBech32(tx.From))
suite.Require().NoError(err)
Expand Down Expand Up @@ -698,6 +698,8 @@ func (suite *EvmTestSuite) TestContractDeploymentRevert() {
suite.SetupTest()
k := suite.app.EvmKeeper

k.SetFlagEnableNoBaseFee(suite.ctx, true)

nonce := k.GetNonce(suite.ctx, suite.from)
ctorArgs, err := evmtypes.ERC20Contract.ABI.Pack("", suite.from, big.NewInt(0))
suite.Require().NoError(err)
Expand Down Expand Up @@ -727,3 +729,11 @@ func (suite *EvmTestSuite) TestContractDeploymentRevert() {
})
}
}

func (suite *EvmTestSuite) zeroFeeMarket() {
err := suite.app.FeeMarketKeeper.SetParams(suite.ctx, feemarkettypes.Params{
BaseFee: sdkmath.ZeroInt(),
MinGasPrice: sdkmath.LegacyZeroDec(),
})
suite.Require().NoError(err)
}
5 changes: 3 additions & 2 deletions x/evm/keeper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, cha
ChainConfig: ethCfg,
CoinBase: coinbase,
BaseFee: baseFee.BigInt(),
NoBaseFee: k.IsNoBaseFeeEnabled(ctx),
}, nil
}

Expand All @@ -43,7 +44,7 @@ func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig

// VMConfig creates an EVM configuration from the debug setting and the extra EIPs enabled on the
// module parameters. The config generated uses the default JumpTable from the EVM.
func (k Keeper) VMConfig(cfg *statedb.EVMConfig, tracer vm.EVMLogger) vm.Config {
func (k Keeper) VMConfig(ctx sdk.Context, cfg *statedb.EVMConfig, tracer vm.EVMLogger) vm.Config {
var debug bool
if tracer != nil {
if _, ok := tracer.(evmtypes.NoOpTracer); !ok {
Expand All @@ -54,7 +55,7 @@ func (k Keeper) VMConfig(cfg *statedb.EVMConfig, tracer vm.EVMLogger) vm.Config
return vm.Config{
Debug: debug,
Tracer: tracer,
NoBaseFee: cfg.NoBaseFee,
NoBaseFee: cfg.NoBaseFee || k.IsNoBaseFeeEnabled(ctx),
ExtraEips: cfg.Params.EIPs(),
}
}
12 changes: 0 additions & 12 deletions x/evm/keeper/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,3 @@ func (k *Keeper) ResetGasMeterAndConsumeGas(ctx sdk.Context, gasUsed uint64) {
ctx.GasMeter().RefundGas(ctx.GasMeter().GasConsumed(), "reset the gas count")
ctx.GasMeter().ConsumeGas(gasUsed, "apply evm transaction")
}

// GasToRefund calculates the amount of gas the state machine should refund to the sender. It is
// capped by the refund quotient value.
// Note: do not pass 0 to refundQuotient
func GasToRefund(availableRefund, gasConsumed, refundQuotient uint64) uint64 {
// Apply refund counter
refund := gasConsumed / refundQuotient
if refund > availableRefund {
return availableRefund
}
return refund
}
Loading