upgrade to ethermint v0.21.0 #99
@ -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
18
x/evm/keeper/abci_test.go
Normal 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)
|
||||||
|
}
|
@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
31
x/evm/keeper/migrations_test.go
Normal file
31
x/evm/keeper/migrations_test.go
Normal 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
80
x/evm/keeper/msg_server_test.go
Normal file
80
x/evm/keeper/msg_server_test.go
Normal 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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 := ðtypes.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)
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.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: ðtypes.AccessList{},
|
accessList: ðtypes.AccessList{},
|
||||||
expectPass: true,
|
expectPass: true,
|
||||||
enableFeemarket: true,
|
enableFeemarket: true,
|
||||||
|
from: suite.address.String(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid from address",
|
||||||
|
gasLimit: 10,
|
||||||
|
gasPrice: &oneInt,
|
||||||
|
cost: &oneInt,
|
||||||
|
accessList: ðtypes.AccessList{},
|
||||||
|
expectPass: false,
|
||||||
|
from: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Enough balance - with access list",
|
||||||
|
gasLimit: 10,
|
||||||
|
gasPrice: &oneInt,
|
||||||
|
cost: &oneInt,
|
||||||
|
accessList: ðtypes.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: ðtypes.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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user