upgrade to ethermint v0.21.0 #99

Closed
0xmuralik wants to merge 384 commits from murali/update-fork into main
10 changed files with 1110 additions and 107 deletions
Showing only changes of commit f04b289e75 - Show all commits

View File

@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (cli) [#1360](https://github.com/evmos/ethermint/pull/1360) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag. * (cli) [#1360](https://github.com/evmos/ethermint/pull/1360) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag.
* (rpc) [#1378](https://github.com/evmos/ethermint/pull/1378) Add support for EVM RPC metrics * (rpc) [#1378](https://github.com/evmos/ethermint/pull/1378) Add support for EVM RPC metrics
* (ante) [#1390](https://github.com/evmos/ethermint/pull/1390) Added multisig tx support. * (ante) [#1390](https://github.com/evmos/ethermint/pull/1390) Added multisig tx support.
* (test) [#1396](https://github.com/evmos/ethermint/pull/1396) Increase test coverage for the EVM module `keeper`
### Bug Fixes ### Bug Fixes

18
x/evm/keeper/abci_test.go Normal file
View File

@ -0,0 +1,18 @@
package keeper_test
import (
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/tendermint/tendermint/abci/types"
)
func (suite *KeeperTestSuite) TestEndBlock() {
em := suite.ctx.EventManager()
suite.Require().Equal(0, len(em.Events()))
res := suite.app.EvmKeeper.EndBlock(suite.ctx, types.RequestEndBlock{})
suite.Require().Equal([]types.ValidatorUpdate{}, res)
// should emit 1 EventTypeBlockBloom event on EndBlock
suite.Require().Equal(1, len(em.Events()))
suite.Require().Equal(evmtypes.EventTypeBlockBloom, em.Events()[0].Type)
}

View File

@ -13,11 +13,11 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
ethlogger "github.com/ethereum/go-ethereum/eth/tracers/logger" ethlogger "github.com/ethereum/go-ethereum/eth/tracers/logger"
ethparams "github.com/ethereum/go-ethereum/params" ethparams "github.com/ethereum/go-ethereum/params"
"github.com/evmos/ethermint/tests"
"github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/statedb"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
"github.com/evmos/ethermint/server/config" "github.com/evmos/ethermint/server/config"
ethermint "github.com/evmos/ethermint/types" ethermint "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/types" "github.com/evmos/ethermint/x/evm/types"
@ -491,9 +491,11 @@ func (suite *KeeperTestSuite) TestQueryValidatorAccount() {
func (suite *KeeperTestSuite) TestEstimateGas() { func (suite *KeeperTestSuite) TestEstimateGas() {
gasHelper := hexutil.Uint64(20000) gasHelper := hexutil.Uint64(20000)
higherGas := hexutil.Uint64(25000)
hexBigInt := hexutil.Big(*big.NewInt(1))
var ( var (
args types.TransactionArgs args interface{}
gasCap uint64 gasCap uint64
) )
testCases := []struct { testCases := []struct {
@ -504,78 +506,223 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
enableFeemarket bool enableFeemarket bool
}{ }{
// should success, because transfer value is zero // should success, because transfer value is zero
{"default args", func() { {
args = types.TransactionArgs{To: &common.Address{}} "default args - special case for ErrIntrinsicGas on contract creation, raise gas limit",
}, true, 21000, false}, func() {
args = types.TransactionArgs{}
},
true,
ethparams.TxGasContractCreation,
false,
},
// should success, because transfer value is zero
{
"default args with 'to' address",
func() {
args = types.TransactionArgs{To: &common.Address{}}
},
true,
ethparams.TxGas,
false,
},
// should fail, because the default From address(zero address) don't have fund // should fail, because the default From address(zero address) don't have fund
{"not enough balance", func() { {
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))} "not enough balance",
}, false, 0, false}, func() {
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
},
false,
0,
false,
},
// should success, enough balance now // should success, enough balance now
{"enough balance", func() { {
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))} "enough balance",
}, false, 0, false}, func() {
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0, false},
// should success, because gas limit lower than 21000 is ignored // should success, because gas limit lower than 21000 is ignored
{"gas exceed allowance", func() { {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper} "gas exceed allowance",
}, true, 21000, false}, func() {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
},
true,
ethparams.TxGas,
false,
},
// should fail, invalid gas cap // should fail, invalid gas cap
{"gas exceed global allowance", func() { {
args = types.TransactionArgs{To: &common.Address{}} "gas exceed global allowance",
gasCap = 20000 func() {
}, false, 0, false}, args = types.TransactionArgs{To: &common.Address{}}
gasCap = 20000
},
false,
0,
false,
},
// estimate gas of an erc20 contract deployment, the exact gas number is checked with geth // estimate gas of an erc20 contract deployment, the exact gas number is checked with geth
{"contract deployment", func() { {
ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt()) "contract deployment",
suite.Require().NoError(err) func() {
data := append(types.ERC20Contract.Bin, ctorArgs...) ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
args = types.TransactionArgs{ suite.Require().NoError(err)
From: &suite.address, data := append(types.ERC20Contract.Bin, ctorArgs...)
Data: (*hexutil.Bytes)(&data), args = types.TransactionArgs{
} From: &suite.address,
}, true, 1186778, false}, Data: (*hexutil.Bytes)(&data),
}
},
true,
1186778,
false,
},
// estimate gas of an erc20 transfer, the exact gas number is checked with geth // estimate gas of an erc20 transfer, the exact gas number is checked with geth
{"erc20 transfer", func() { {
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt()) "erc20 transfer",
suite.Commit() func() {
transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000)) contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
suite.Require().NoError(err) suite.Commit()
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)} transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
}, true, 51880, false}, suite.Require().NoError(err)
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
},
true,
51880,
false,
},
// repeated tests with enableFeemarket // repeated tests with enableFeemarket
{"default args w/ enableFeemarket", func() { {
args = types.TransactionArgs{To: &common.Address{}} "default args w/ enableFeemarket",
}, true, 21000, true}, func() {
{"not enough balance w/ enableFeemarket", func() { args = types.TransactionArgs{To: &common.Address{}}
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))} },
}, false, 0, true}, true,
{"enough balance w/ enableFeemarket", func() { ethparams.TxGas,
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))} true,
}, false, 0, true}, },
{"gas exceed allowance w/ enableFeemarket", func() { {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper} "not enough balance w/ enableFeemarket",
}, true, 21000, true}, func() {
{"gas exceed global allowance w/ enableFeemarket", func() { args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
args = types.TransactionArgs{To: &common.Address{}} },
gasCap = 20000 false,
}, false, 0, true}, 0,
{"contract deployment w/ enableFeemarket", func() { true,
ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt()) },
suite.Require().NoError(err) {
data := append(types.ERC20Contract.Bin, ctorArgs...) "enough balance w/ enableFeemarket",
args = types.TransactionArgs{ func() {
From: &suite.address, args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
Data: (*hexutil.Bytes)(&data), },
} false,
}, true, 1186778, true}, 0,
{"erc20 transfer w/ enableFeemarket", func() { true,
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt()) },
suite.Commit() {
transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000)) "gas exceed allowance w/ enableFeemarket",
suite.Require().NoError(err) func() {
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)} args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
}, true, 51880, true}, },
true,
ethparams.TxGas,
true,
},
{
"gas exceed global allowance w/ enableFeemarket",
func() {
args = types.TransactionArgs{To: &common.Address{}}
gasCap = 20000
},
false,
0,
true,
},
{
"contract deployment w/ enableFeemarket",
func() {
ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
suite.Require().NoError(err)
data := append(types.ERC20Contract.Bin, ctorArgs...)
args = types.TransactionArgs{
From: &suite.address,
Data: (*hexutil.Bytes)(&data),
}
},
true,
1186778,
true,
},
{
"erc20 transfer w/ enableFeemarket",
func() {
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
suite.Commit()
transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
suite.Require().NoError(err)
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
},
true,
51880,
true,
},
{
"contract creation but 'create' param disabled",
func() {
ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdkmath.NewIntWithDecimal(1000, 18).BigInt())
suite.Require().NoError(err)
data := append(types.ERC20Contract.Bin, ctorArgs...)
args = types.TransactionArgs{
From: &suite.address,
Data: (*hexutil.Bytes)(&data),
}
params := suite.app.EvmKeeper.GetParams(suite.ctx)
params.EnableCreate = false
suite.app.EvmKeeper.SetParams(suite.ctx, params)
},
false,
0,
false,
},
{
"specified gas in args higher than ethparams.TxGas (21,000)",
func() {
args = types.TransactionArgs{
To: &common.Address{},
Gas: &higherGas,
}
},
true,
ethparams.TxGas,
false,
},
{
"specified gas in args higher than request gasCap",
func() {
gasCap = 22_000
args = types.TransactionArgs{
To: &common.Address{},
Gas: &higherGas,
}
},
true,
ethparams.TxGas,
false,
},
{
"invalid args - specified both gasPrice and maxFeePerGas",
func() {
args = types.TransactionArgs{
To: &common.Address{},
GasPrice: &hexBigInt,
MaxFeePerGas: &hexBigInt,
}
},
false,
0,
false,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -702,6 +849,88 @@ func (suite *KeeperTestSuite) TestTraceTx() {
traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":", traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
enableFeemarket: false, enableFeemarket: false,
}, },
{
msg: "invalid trace config - Negative Limit",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Limit: -1,
}
},
expPass: false,
},
{
msg: "invalid trace config - Invalid Tracer",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Tracer: "invalid_tracer",
}
},
expPass: false,
},
{
msg: "invalid trace config - Invalid Timeout",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Timeout: "wrong_time",
}
},
expPass: false,
},
{
msg: "trace config - Execution Timeout",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Timeout: "0s",
}
},
expPass: false,
},
{
msg: "default tracer with contract creation tx as predecessor but 'create' param disabled",
malleate: func() {
traceConfig = nil
// increase nonce to avoid address collision
vmdb := suite.StateDB()
vmdb.SetNonce(suite.address, vmdb.GetNonce(suite.address)+1)
suite.Require().NoError(vmdb.Commit())
chainID := suite.app.EvmKeeper.ChainID()
nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address)
data := types.ERC20Contract.Bin
contractTx := types.NewTxContract(
chainID,
nonce,
nil, // amount
ethparams.TxGasContractCreation, // gasLimit
nil, // gasPrice
nil, nil,
data, // input
nil, // accesses
)
predecessors = append(predecessors, contractTx)
suite.Commit()
params := suite.app.EvmKeeper.GetParams(suite.ctx)
params.EnableCreate = false
suite.app.EvmKeeper.SetParams(suite.ctx, params)
},
expPass: true,
traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -722,7 +951,6 @@ func (suite *KeeperTestSuite) TestTraceTx() {
Predecessors: predecessors, Predecessors: predecessors,
} }
res, err := suite.queryClient.TraceTx(sdk.WrapSDKContext(suite.ctx), &traceReq) res, err := suite.queryClient.TraceTx(sdk.WrapSDKContext(suite.ctx), &traceReq)
suite.Require().NoError(err)
if tc.expPass { if tc.expPass {
suite.Require().NoError(err) suite.Require().NoError(err)
@ -836,6 +1064,31 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU", traceResponse: "[{\"result\":{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PU",
enableFeemarket: false, enableFeemarket: false,
}, },
{
msg: "invalid trace config - Negative Limit",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Limit: -1,
}
},
expPass: false,
},
{
msg: "invalid trace config - Invalid Tracer",
malleate: func() {
traceConfig = &types.TraceConfig{
DisableStack: true,
DisableStorage: true,
EnableMemory: false,
Tracer: "invalid_tracer",
}
},
expPass: true,
traceResponse: "[]",
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -877,10 +1130,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
} }
func (suite *KeeperTestSuite) TestNonceInQuery() { func (suite *KeeperTestSuite) TestNonceInQuery() {
suite.SetupTest() address := tests.GenerateAddress()
priv, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
suite.Require().Equal(uint64(0), suite.app.EvmKeeper.GetNonce(suite.ctx, address)) suite.Require().Equal(uint64(0), suite.app.EvmKeeper.GetNonce(suite.ctx, address))
supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt() supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt()
@ -981,3 +1231,158 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() {
suite.enableFeemarket = false suite.enableFeemarket = false
suite.enableLondonHF = true suite.enableLondonHF = true
} }
func (suite *KeeperTestSuite) TestEthCall() {
var (
req *types.EthCallRequest
)
address := tests.GenerateAddress()
suite.Require().Equal(uint64(0), suite.app.EvmKeeper.GetNonce(suite.ctx, address))
supply := sdkmath.NewIntWithDecimal(1000, 18).BigInt()
hexBigInt := hexutil.Big(*big.NewInt(1))
ctorArgs, err := types.ERC20Contract.ABI.Pack("", address, supply)
suite.Require().NoError(err)
data := append(types.ERC20Contract.Bin, ctorArgs...)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"invalid args",
func() {
req = &types.EthCallRequest{Args: []byte("invalid args"), GasCap: uint64(config.DefaultGasCap)}
},
false,
},
{
"invalid args - specified both gasPrice and maxFeePerGas",
func() {
args, err := json.Marshal(&types.TransactionArgs{
From: &address,
Data: (*hexutil.Bytes)(&data),
GasPrice: &hexBigInt,
MaxFeePerGas: &hexBigInt,
})
suite.Require().NoError(err)
req = &types.EthCallRequest{Args: args, GasCap: uint64(config.DefaultGasCap)}
},
false,
},
{
"set param EnableCreate = false",
func() {
args, err := json.Marshal(&types.TransactionArgs{
From: &address,
Data: (*hexutil.Bytes)(&data),
})
suite.Require().NoError(err)
req = &types.EthCallRequest{Args: args, GasCap: uint64(config.DefaultGasCap)}
params := suite.app.EvmKeeper.GetParams(suite.ctx)
params.EnableCreate = false
suite.app.EvmKeeper.SetParams(suite.ctx, params)
},
false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
res, err := suite.queryClient.EthCall(suite.ctx, req)
if tc.expPass {
suite.Require().NotNil(res)
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestEmptyRequest() {
k := suite.app.EvmKeeper
testCases := []struct {
name string
queryFunc func() (interface{}, error)
}{
{
"Account method",
func() (interface{}, error) {
return k.Account(suite.ctx, nil)
},
},
{
"CosmosAccount method",
func() (interface{}, error) {
return k.CosmosAccount(suite.ctx, nil)
},
},
{
"ValidatorAccount method",
func() (interface{}, error) {
return k.ValidatorAccount(suite.ctx, nil)
},
},
{
"Balance method",
func() (interface{}, error) {
return k.Balance(suite.ctx, nil)
},
},
{
"Storage method",
func() (interface{}, error) {
return k.Storage(suite.ctx, nil)
},
},
{
"Code method",
func() (interface{}, error) {
return k.Code(suite.ctx, nil)
},
},
{
"EthCall method",
func() (interface{}, error) {
return k.EthCall(suite.ctx, nil)
},
},
{
"EstimateGas method",
func() (interface{}, error) {
return k.EstimateGas(suite.ctx, nil)
},
},
{
"TraceTx method",
func() (interface{}, error) {
return k.TraceTx(suite.ctx, nil)
},
},
{
"TraceBlock method",
func() (interface{}, error) {
return k.TraceBlock(suite.ctx, nil)
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
_, err := tc.queryFunc()
suite.Require().Error(err)
})
}
}

View File

@ -200,6 +200,7 @@ func (suite *KeeperTestSuite) SetupApp(checkTx bool) {
valAddr := sdk.ValAddress(suite.address.Bytes()) valAddr := sdk.ValAddress(suite.address.Bytes())
validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{}) validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
require.NoError(t, err)
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator) err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
require.NoError(t, err) require.NoError(t, err)
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator) err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
@ -434,3 +435,88 @@ func (suite *KeeperTestSuite) TestBaseFee() {
suite.enableFeemarket = false suite.enableFeemarket = false
suite.enableLondonHF = true suite.enableLondonHF = true
} }
func (suite *KeeperTestSuite) TestGetAccountStorage() {
testCases := []struct {
name string
malleate func()
expRes []int
}{
{
"Only one account that's not a contract (no storage)",
func() {},
[]int{0},
},
{
"Two accounts - one contract (with storage), one wallet",
func() {
supply := big.NewInt(100)
suite.DeployTestContract(suite.T(), suite.address, supply)
},
[]int{2, 0},
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
i := 0
suite.app.AccountKeeper.IterateAccounts(suite.ctx, func(account authtypes.AccountI) bool {
ethAccount, ok := account.(ethermint.EthAccountI)
if !ok {
// ignore non EthAccounts
return false
}
addr := ethAccount.EthAddress()
storage := suite.app.EvmKeeper.GetAccountStorage(suite.ctx, addr)
suite.Require().Equal(tc.expRes[i], len(storage))
i++
return false
})
})
}
}
func (suite *KeeperTestSuite) TestGetAccountOrEmpty() {
empty := statedb.Account{
Balance: new(big.Int),
CodeHash: types.EmptyCodeHash,
}
supply := big.NewInt(100)
contractAddr := suite.DeployTestContract(suite.T(), suite.address, supply)
testCases := []struct {
name string
addr common.Address
expEmpty bool
}{
{
"unexisting account - get empty",
common.Address{},
true,
},
{
"existing contract account",
contractAddr,
false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
res := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, tc.addr)
if tc.expEmpty {
suite.Require().Equal(empty, res)
} else {
suite.Require().NotEqual(empty, res)
}
})
}
}

View File

@ -0,0 +1,31 @@
package keeper_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
)
func (suite *KeeperTestSuite) TestMigrations() {
migrator := evmkeeper.NewMigrator(*suite.app.EvmKeeper)
testCases := []struct {
name string
migrateFunc func(ctx sdk.Context) error
}{
{
"Run Migrate1to2",
migrator.Migrate1to2,
},
{
"Run Migrate2to3",
migrator.Migrate2to3,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
err := tc.migrateFunc(suite.ctx)
suite.Require().NoError(err)
})
}
}

View File

@ -0,0 +1,80 @@
package keeper_test
import (
"math/big"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/evmos/ethermint/x/evm/types"
)
func (suite *KeeperTestSuite) TestEthereumTx() {
var (
err error
msg *types.MsgEthereumTx
signer ethtypes.Signer
vmdb *statedb.StateDB
chainCfg *params.ChainConfig
expectedGasUsed uint64
)
testCases := []struct {
name string
malleate func()
expErr bool
}{
{
"Deploy contract tx - insufficient gas",
func() {
msg, err = suite.createContractMsgTx(
vmdb.GetNonce(suite.address),
signer,
chainCfg,
big.NewInt(1),
)
suite.Require().NoError(err)
},
true,
},
{
"Transfer funds tx",
func() {
msg, _, err = newEthMsgTx(
vmdb.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
chainCfg,
suite.signer,
signer,
ethtypes.AccessListTxType,
nil,
nil,
)
suite.Require().NoError(err)
expectedGasUsed = params.TxGas
},
false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
chainCfg = keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
vmdb = suite.StateDB()
tc.malleate()
res, err := suite.app.EvmKeeper.EthereumTx(suite.ctx, msg)
if tc.expErr {
suite.Require().Error(err)
return
}
suite.Require().NoError(err)
suite.Require().Equal(expectedGasUsed, res.GasUsed)
suite.Require().False(res.Failed())
})
}
}

View File

@ -75,7 +75,7 @@ func newSignedEthTx(
return ethTx, nil return ethTx, nil
} }
func newNativeMessage( func newEthMsgTx(
nonce uint64, nonce uint64,
blockHeight int64, blockHeight int64,
address common.Address, address common.Address,
@ -85,14 +85,11 @@ func newNativeMessage(
txType byte, txType byte,
data []byte, data []byte,
accessList ethtypes.AccessList, accessList ethtypes.AccessList,
) (core.Message, error) { ) (*evmtypes.MsgEthereumTx, *big.Int, error) {
msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(blockHeight))
var ( var (
ethTx *ethtypes.Transaction ethTx *ethtypes.Transaction
baseFee *big.Int baseFee *big.Int
) )
switch txType { switch txType {
case ethtypes.LegacyTxType: case ethtypes.LegacyTxType:
templateLegacyTx.Nonce = nonce templateLegacyTx.Nonce = nonce
@ -122,14 +119,32 @@ func newNativeMessage(
ethTx = ethtypes.NewTx(templateDynamicFeeTx) ethTx = ethtypes.NewTx(templateDynamicFeeTx)
baseFee = big.NewInt(3) baseFee = big.NewInt(3)
default: default:
return nil, errors.New("unsupport tx type") return nil, baseFee, errors.New("unsupport tx type")
} }
msg := &evmtypes.MsgEthereumTx{} msg := &evmtypes.MsgEthereumTx{}
msg.FromEthereumTx(ethTx) msg.FromEthereumTx(ethTx)
msg.From = address.Hex() msg.From = address.Hex()
if err := msg.Sign(ethSigner, krSigner); err != nil { return msg, baseFee, msg.Sign(ethSigner, krSigner)
}
func newNativeMessage(
nonce uint64,
blockHeight int64,
address common.Address,
cfg *params.ChainConfig,
krSigner keyring.Signer,
ethSigner ethtypes.Signer,
txType byte,
data []byte,
accessList ethtypes.AccessList,
) (core.Message, error) {
msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(blockHeight))
msg, baseFee, err := newEthMsgTx(nonce, blockHeight, address, cfg, krSigner, ethSigner, txType, data, accessList)
if err != nil {
return nil, err return nil, err
} }

View File

@ -9,10 +9,12 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/evmos/ethermint/tests" "github.com/evmos/ethermint/tests"
"github.com/evmos/ethermint/x/evm/keeper" "github.com/evmos/ethermint/x/evm/keeper"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/evmos/ethermint/x/evm/types" "github.com/evmos/ethermint/x/evm/types"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@ -346,40 +348,63 @@ func (suite *KeeperTestSuite) TestGasToRefund() {
} }
func (suite *KeeperTestSuite) TestRefundGas() { func (suite *KeeperTestSuite) TestRefundGas() {
var (
m core.Message
err error
)
testCases := []struct { testCases := []struct {
name string name string
leftoverGas uint64 leftoverGas uint64
refundQuotient uint64 refundQuotient uint64
noError bool noError bool
expGasRefund uint64 expGasRefund uint64
malleate func()
}{ }{
{ {
"leftoverGas more than tx gas limit", name: "leftoverGas more than tx gas limit",
params.TxGas + 1, leftoverGas: params.TxGas + 1,
params.RefundQuotient, refundQuotient: params.RefundQuotient,
false, noError: false,
params.TxGas + 1, expGasRefund: params.TxGas + 1,
}, },
{ {
"leftoverGas equal to tx gas limit, insufficient fee collector account", name: "leftoverGas equal to tx gas limit, insufficient fee collector account",
params.TxGas, leftoverGas: params.TxGas,
params.RefundQuotient, refundQuotient: params.RefundQuotient,
true, noError: true,
0, expGasRefund: 0,
}, },
{ {
"leftoverGas less than to tx gas limit", name: "leftoverGas less than to tx gas limit",
params.TxGas - 1, leftoverGas: params.TxGas - 1,
params.RefundQuotient, refundQuotient: params.RefundQuotient,
true, noError: true,
0, expGasRefund: 0,
}, },
{ {
"no leftoverGas, refund half used gas ", name: "no leftoverGas, refund half used gas ",
0, leftoverGas: 0,
params.RefundQuotient, refundQuotient: params.RefundQuotient,
true, noError: true,
params.TxGas / params.RefundQuotient, expGasRefund: params.TxGas / params.RefundQuotient,
},
{
name: "invalid Gas value in msg",
leftoverGas: 0,
refundQuotient: params.RefundQuotient,
noError: false,
expGasRefund: params.TxGas,
malleate: func() {
keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
m, err = suite.createContractGethMsg(
suite.StateDB().GetNonce(suite.address),
ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()),
keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID()),
big.NewInt(-100),
)
suite.Require().NoError(err)
},
}, },
} }
@ -393,7 +418,7 @@ func (suite *KeeperTestSuite) TestRefundGas() {
signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()) signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
vmdb := suite.StateDB() vmdb := suite.StateDB()
m, err := newNativeMessage( m, err = newNativeMessage(
vmdb.GetNonce(suite.address), vmdb.GetNonce(suite.address),
suite.ctx.BlockHeight(), suite.ctx.BlockHeight(),
suite.address, suite.address,
@ -411,6 +436,11 @@ func (suite *KeeperTestSuite) TestRefundGas() {
if tc.leftoverGas > m.Gas() { if tc.leftoverGas > m.Gas() {
return return
} }
if tc.malleate != nil {
tc.malleate()
}
gasUsed := m.Gas() - tc.leftoverGas gasUsed := m.Gas() - tc.leftoverGas
refund := keeper.GasToRefund(vmdb.GetRefund(), gasUsed, tc.refundQuotient) refund := keeper.GasToRefund(vmdb.GetRefund(), gasUsed, tc.refundQuotient)
suite.Require().Equal(tc.expGasRefund, refund) suite.Require().Equal(tc.expGasRefund, refund)
@ -486,7 +516,6 @@ func (suite *KeeperTestSuite) TestResetGasMeterAndConsumeGas() {
} }
func (suite *KeeperTestSuite) TestEVMConfig() { func (suite *KeeperTestSuite) TestEVMConfig() {
suite.SetupTest()
cfg, err := suite.app.EvmKeeper.EVMConfig(suite.ctx) cfg, err := suite.app.EvmKeeper.EVMConfig(suite.ctx)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.Require().Equal(types.DefaultParams(), cfg.Params) suite.Require().Equal(types.DefaultParams(), cfg.Params)
@ -497,8 +526,165 @@ func (suite *KeeperTestSuite) TestEVMConfig() {
} }
func (suite *KeeperTestSuite) TestContractDeployment() { func (suite *KeeperTestSuite) TestContractDeployment() {
suite.SetupTest()
contractAddress := suite.DeployTestContract(suite.T(), suite.address, big.NewInt(10000000000000)) contractAddress := suite.DeployTestContract(suite.T(), suite.address, big.NewInt(10000000000000))
db := suite.StateDB() db := suite.StateDB()
suite.Require().Greater(db.GetCodeSize(contractAddress), 0) suite.Require().Greater(db.GetCodeSize(contractAddress), 0)
} }
func (suite *KeeperTestSuite) TestApplyMessage() {
expectedGasUsed := params.TxGas
var msg core.Message
config, err := suite.app.EvmKeeper.EVMConfig(suite.ctx)
suite.Require().NoError(err)
keeperParams := suite.app.EvmKeeper.GetParams(suite.ctx)
chainCfg := keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
tracer := suite.app.EvmKeeper.Tracer(suite.ctx, msg, config.ChainConfig)
vmdb := suite.StateDB()
msg, err = newNativeMessage(
vmdb.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
chainCfg,
suite.signer,
signer,
ethtypes.AccessListTxType,
nil,
nil,
)
suite.Require().NoError(err)
res, err := suite.app.EvmKeeper.ApplyMessage(suite.ctx, msg, tracer, true)
suite.Require().NoError(err)
suite.Require().Equal(expectedGasUsed, res.GasUsed)
suite.Require().False(res.Failed())
}
func (suite *KeeperTestSuite) TestApplyMessageWithConfig() {
var (
msg core.Message
err error
expectedGasUsed uint64
config *types.EVMConfig
keeperParams types.Params
signer ethtypes.Signer
vmdb *statedb.StateDB
txConfig statedb.TxConfig
chainCfg *params.ChainConfig
)
testCases := []struct {
name string
malleate func()
expErr bool
}{
{
"messsage applied ok",
func() {
msg, err = newNativeMessage(
vmdb.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
chainCfg,
suite.signer,
signer,
ethtypes.AccessListTxType,
nil,
nil,
)
suite.Require().NoError(err)
},
false,
},
{
"call contract tx with config param EnableCall = false",
func() {
config.Params.EnableCall = false
msg, err = newNativeMessage(
vmdb.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
chainCfg,
suite.signer,
signer,
ethtypes.AccessListTxType,
nil,
nil,
)
suite.Require().NoError(err)
},
true,
},
{
"create contract tx with config param EnableCreate = false",
func() {
msg, err = suite.createContractGethMsg(vmdb.GetNonce(suite.address), signer, chainCfg, big.NewInt(1))
suite.Require().NoError(err)
config.Params.EnableCreate = false
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
expectedGasUsed = params.TxGas
config, err = suite.app.EvmKeeper.EVMConfig(suite.ctx)
suite.Require().NoError(err)
keeperParams = suite.app.EvmKeeper.GetParams(suite.ctx)
chainCfg = keeperParams.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
vmdb = suite.StateDB()
txConfig = suite.app.EvmKeeper.TxConfig(suite.ctx, common.Hash{})
tc.malleate()
res, err := suite.app.EvmKeeper.ApplyMessageWithConfig(suite.ctx, msg, nil, true, config, txConfig)
if tc.expErr {
suite.Require().Error(err)
return
}
suite.Require().NoError(err)
suite.Require().False(res.Failed())
suite.Require().Equal(expectedGasUsed, res.GasUsed)
})
}
}
func (suite *KeeperTestSuite) createContractGethMsg(nonce uint64, signer ethtypes.Signer, cfg *params.ChainConfig, gasPrice *big.Int) (core.Message, error) {
ethMsg, err := suite.createContractMsgTx(nonce, signer, cfg, gasPrice)
if err != nil {
return nil, err
}
msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(suite.ctx.BlockHeight()))
return ethMsg.AsMessage(msgSigner, nil)
}
func (suite *KeeperTestSuite) createContractMsgTx(nonce uint64, signer ethtypes.Signer, cfg *params.ChainConfig, gasPrice *big.Int) (*types.MsgEthereumTx, error) {
contractCreateTx := &ethtypes.AccessListTx{
GasPrice: gasPrice,
Gas: params.TxGasContractCreation,
To: nil,
Data: []byte("contract_data"),
Nonce: nonce,
}
ethTx := ethtypes.NewTx(contractCreateTx)
ethMsg := &types.MsgEthereumTx{}
ethMsg.FromEthereumTx(ethTx)
ethMsg.From = suite.address.Hex()
return ethMsg, ethMsg.Sign(signer, suite.signer)
}

View File

@ -6,6 +6,7 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
@ -317,6 +318,40 @@ func (suite *KeeperTestSuite) TestSetCode() {
} }
} }
func (suite *KeeperTestSuite) TestKeeperSetCode() {
addr := tests.GenerateAddress()
baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
testCases := []struct {
name string
codeHash []byte
code []byte
}{
{
"set code",
[]byte("codeHash"),
[]byte("this is the code"),
},
{
"delete code",
[]byte("codeHash"),
nil,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.app.EvmKeeper.SetCode(suite.ctx, tc.codeHash, tc.code)
key := suite.app.GetKey(types.StoreKey)
store := prefix.NewStore(suite.ctx.KVStore(key), types.KeyPrefixCode)
code := store.Get(tc.codeHash)
suite.Require().Equal(tc.code, code)
})
}
}
func (suite *KeeperTestSuite) TestRefund() { func (suite *KeeperTestSuite) TestRefund() {
testCases := []struct { testCases := []struct {
name string name string
@ -384,8 +419,6 @@ func (suite *KeeperTestSuite) TestState() {
} }
func (suite *KeeperTestSuite) TestCommittedState() { func (suite *KeeperTestSuite) TestCommittedState() {
suite.SetupTest()
key := common.BytesToHash([]byte("key")) key := common.BytesToHash([]byte("key"))
value1 := common.BytesToHash([]byte("value1")) value1 := common.BytesToHash([]byte("value1"))
value2 := common.BytesToHash([]byte("value2")) value2 := common.BytesToHash([]byte("value2"))
@ -487,8 +520,6 @@ func (suite *KeeperTestSuite) TestExist() {
} }
func (suite *KeeperTestSuite) TestEmpty() { func (suite *KeeperTestSuite) TestEmpty() {
suite.SetupTest()
testCases := []struct { testCases := []struct {
name string name string
address common.Address address common.Address
@ -507,6 +538,7 @@ func (suite *KeeperTestSuite) TestEmpty() {
for _, tc := range testCases { for _, tc := range testCases {
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
suite.SetupTest()
vmdb := suite.StateDB() vmdb := suite.StateDB()
tc.malleate(vmdb) tc.malleate(vmdb)
@ -811,3 +843,102 @@ func (suite *KeeperTestSuite) _TestForEachStorage() {
storage = types.Storage{} storage = types.Storage{}
} }
} }
func (suite *KeeperTestSuite) TestSetBalance() {
amount := big.NewInt(-10)
testCases := []struct {
name string
addr common.Address
malleate func()
expErr bool
}{
{
"address without funds - invalid amount",
suite.address,
func() {},
true,
},
{
"mint to address",
suite.address,
func() {
amount = big.NewInt(100)
},
false,
},
{
"burn from address",
suite.address,
func() {
amount = big.NewInt(60)
},
false,
},
{
"address with funds - invalid amount",
suite.address,
func() {
amount = big.NewInt(-10)
},
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
tc.malleate()
err := suite.app.EvmKeeper.SetBalance(suite.ctx, tc.addr, amount)
if tc.expErr {
suite.Require().Error(err)
} else {
balance := suite.app.EvmKeeper.GetBalance(suite.ctx, tc.addr)
suite.Require().NoError(err)
suite.Require().Equal(amount, balance)
}
})
}
}
func (suite *KeeperTestSuite) TestDeleteAccount() {
supply := big.NewInt(100)
contractAddr := suite.DeployTestContract(suite.T(), suite.address, supply)
testCases := []struct {
name string
addr common.Address
expErr bool
}{
{
"remove address",
suite.address,
false,
},
{
"remove unexistent address - returns nil error",
common.HexToAddress("unexistent_address"),
false,
},
{
"remove deployed contract",
contractAddr,
false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
err := suite.app.EvmKeeper.DeleteAccount(suite.ctx, tc.addr)
if tc.expErr {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
balance := suite.app.EvmKeeper.GetBalance(suite.ctx, tc.addr)
suite.Require().Equal(new(big.Int), balance)
}
})
}
}

View File

@ -271,6 +271,8 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList *ethtypes.AccessList accessList *ethtypes.AccessList
expectPass bool expectPass bool
enableFeemarket bool enableFeemarket bool
from string
malleate func()
}{ }{
{ {
name: "Enough balance", name: "Enough balance",
@ -279,6 +281,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
from: suite.address.String(),
}, },
{ {
name: "Equal balance", name: "Equal balance",
@ -287,6 +290,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
from: suite.address.String(),
}, },
{ {
name: "Higher gas limit, not enough balance", name: "Higher gas limit, not enough balance",
@ -295,6 +299,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
from: suite.address.String(),
}, },
{ {
name: "Higher gas price, enough balance", name: "Higher gas price, enough balance",
@ -303,6 +308,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
from: suite.address.String(),
}, },
{ {
name: "Higher gas price, not enough balance", name: "Higher gas price, not enough balance",
@ -311,6 +317,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
from: suite.address.String(),
}, },
// This case is expected to be true because the fees can be deducted, but the tx // This case is expected to be true because the fees can be deducted, but the tx
// execution is going to fail because there is no more balance to pay the cost // execution is going to fail because there is no more balance to pay the cost
@ -321,6 +328,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
cost: &fiftyInt, cost: &fiftyInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
from: suite.address.String(),
}, },
// testcases with enableFeemarket enabled. // testcases with enableFeemarket enabled.
{ {
@ -332,6 +340,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
enableFeemarket: true, enableFeemarket: true,
from: suite.address.String(),
}, },
{ {
name: "empty tip fee is valid to deduct", name: "empty tip fee is valid to deduct",
@ -342,6 +351,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
enableFeemarket: true, enableFeemarket: true,
from: suite.address.String(),
}, },
{ {
name: "effectiveTip equal to gasTipCap", name: "effectiveTip equal to gasTipCap",
@ -351,6 +361,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
enableFeemarket: true, enableFeemarket: true,
from: suite.address.String(),
}, },
{ {
name: "effectiveTip equal to (gasFeeCap - baseFee)", name: "effectiveTip equal to (gasFeeCap - baseFee)",
@ -361,6 +372,42 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
enableFeemarket: true, enableFeemarket: true,
from: suite.address.String(),
},
{
name: "Invalid from address",
gasLimit: 10,
gasPrice: &oneInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: false,
from: "",
},
{
name: "Enough balance - with access list",
gasLimit: 10,
gasPrice: &oneInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{
ethtypes.AccessTuple{
Address: suite.address,
StorageKeys: []common.Hash{},
},
},
expectPass: true,
from: suite.address.String(),
},
{
name: "gasLimit < intrinsicGas during IsCheckTx",
gasLimit: 1,
gasPrice: &oneInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: false,
from: suite.address.String(),
malleate: func() {
suite.ctx = suite.ctx.WithIsCheckTx(true)
},
}, },
} }
@ -370,6 +417,9 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
suite.SetupTest() suite.SetupTest()
vmdb := suite.StateDB() vmdb := suite.StateDB()
if tc.malleate != nil {
tc.malleate()
}
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
if tc.cost != nil { if tc.cost != nil {
amount = tc.cost.BigInt() amount = tc.cost.BigInt()
@ -399,7 +449,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
vmdb.Commit() vmdb.Commit()
tx := evmtypes.NewTx(zeroInt.BigInt(), 1, &suite.address, amount, tc.gasLimit, gasPrice, gasFeeCap, gasTipCap, nil, tc.accessList) tx := evmtypes.NewTx(zeroInt.BigInt(), 1, &suite.address, amount, tc.gasLimit, gasPrice, gasFeeCap, gasTipCap, nil, tc.accessList)
tx.From = suite.address.String() tx.From = tc.from
txData, _ := evmtypes.UnpackTxData(tx.Data) txData, _ := evmtypes.UnpackTxData(tx.Data)