tests: improve x/evm/types coverage (#1302)

* modifying x/evm/types tests v1

* modifying x/evm/types tests v2

* modifying x/evm/types test v3

Co-authored-by: Freddy Caceres <facs95@gmail.com>
This commit is contained in:
Adi Saravanan 2022-09-01 07:59:01 -07:00 committed by GitHub
parent ca070e21ef
commit 3e4544d818
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 632 additions and 2 deletions

View File

@ -57,6 +57,25 @@ func (suite *TxDataTestSuite) TestAccessListTxGetGasFeeCap() {
}
}
func (suite *TxDataTestSuite) TestEmptyAccessList() {
testCases := []struct {
name string
tx AccessListTx
}{
{
"empty access list tx",
AccessListTx{
Accesses: nil,
},
},
}
for _, tc := range testCases {
actual := tc.tx.GetAccessList()
suite.Require().Nil(actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestAccessListTxCost() {
testCases := []struct {
name string
@ -81,6 +100,28 @@ func (suite *TxDataTestSuite) TestAccessListTxCost() {
}
}
func (suite *TxDataTestSuite) TestAccessListEffectiveGasPrice() {
testCases := []struct {
name string
tx AccessListTx
baseFee *big.Int
}{
{
"non-empty access list tx",
AccessListTx{
GasPrice: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveGasPrice(tc.baseFee)
suite.Require().Equal(tc.tx.GetGasPrice(), actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestAccessListTxEffectiveCost() {
testCases := []struct {
name string

View File

@ -235,6 +235,69 @@ func TestChainConfigValidate(t *testing.T) {
},
true,
},
{
"invalid ArrowGlacierBlock",
ChainConfig{
HomesteadBlock: newIntPtr(0),
DAOForkBlock: newIntPtr(0),
EIP150Block: newIntPtr(0),
EIP150Hash: defaultEIP150Hash,
EIP155Block: newIntPtr(0),
EIP158Block: newIntPtr(0),
ByzantiumBlock: newIntPtr(0),
ConstantinopleBlock: newIntPtr(0),
PetersburgBlock: newIntPtr(0),
IstanbulBlock: newIntPtr(0),
MuirGlacierBlock: newIntPtr(0),
BerlinBlock: newIntPtr(0),
LondonBlock: newIntPtr(0),
ArrowGlacierBlock: newIntPtr(-1),
},
true,
},
{
"invalid GrayGlacierBlock",
ChainConfig{
HomesteadBlock: newIntPtr(0),
DAOForkBlock: newIntPtr(0),
EIP150Block: newIntPtr(0),
EIP150Hash: defaultEIP150Hash,
EIP155Block: newIntPtr(0),
EIP158Block: newIntPtr(0),
ByzantiumBlock: newIntPtr(0),
ConstantinopleBlock: newIntPtr(0),
PetersburgBlock: newIntPtr(0),
IstanbulBlock: newIntPtr(0),
MuirGlacierBlock: newIntPtr(0),
BerlinBlock: newIntPtr(0),
LondonBlock: newIntPtr(0),
ArrowGlacierBlock: newIntPtr(0),
GrayGlacierBlock: newIntPtr(-1),
},
true,
},
{
"invalid MergeNetsplitBlock",
ChainConfig{
HomesteadBlock: newIntPtr(0),
DAOForkBlock: newIntPtr(0),
EIP150Block: newIntPtr(0),
EIP150Hash: defaultEIP150Hash,
EIP155Block: newIntPtr(0),
EIP158Block: newIntPtr(0),
ByzantiumBlock: newIntPtr(0),
ConstantinopleBlock: newIntPtr(0),
PetersburgBlock: newIntPtr(0),
IstanbulBlock: newIntPtr(0),
MuirGlacierBlock: newIntPtr(0),
BerlinBlock: newIntPtr(0),
LondonBlock: newIntPtr(0),
ArrowGlacierBlock: newIntPtr(0),
GrayGlacierBlock: newIntPtr(0),
MergeNetsplitBlock: newIntPtr(-1),
},
true,
},
{
"invalid fork order - skip HomesteadBlock",
ChainConfig{

View File

@ -8,6 +8,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/evmos/ethermint/tests"
"github.com/stretchr/testify/suite"
@ -18,25 +19,33 @@ type TxDataTestSuite struct {
sdkInt sdkmath.Int
uint64 uint64
hexUint64 hexutil.Uint64
bigInt *big.Int
hexBigInt hexutil.Big
overflowBigInt *big.Int
sdkZeroInt sdkmath.Int
sdkMinusOneInt sdkmath.Int
invalidAddr string
addr common.Address
hexAddr string
hexDataBytes hexutil.Bytes
hexInputBytes hexutil.Bytes
}
func (suite *TxDataTestSuite) SetupTest() {
suite.sdkInt = sdkmath.NewInt(100)
suite.uint64 = suite.sdkInt.Uint64()
suite.hexUint64 = hexutil.Uint64(100)
suite.bigInt = big.NewInt(1)
suite.hexBigInt = hexutil.Big(*big.NewInt(1))
suite.overflowBigInt = big.NewInt(0).Exp(big.NewInt(10), big.NewInt(256), nil)
suite.sdkZeroInt = sdk.ZeroInt()
suite.sdkMinusOneInt = sdkmath.NewInt(-1)
suite.invalidAddr = "123456"
suite.addr = tests.GenerateAddress()
suite.hexAddr = suite.addr.Hex()
suite.hexDataBytes = hexutil.Bytes([]byte("data"))
suite.hexInputBytes = hexutil.Bytes([]byte("input"))
}
func TestTxDataTestSuite(t *testing.T) {
@ -581,6 +590,84 @@ func (suite *TxDataTestSuite) TestDynamicFeeTxValidate() {
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveGasPrice() {
testCases := []struct {
name string
tx DynamicFeeTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty dynamic fee tx",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveGasPrice(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveFee() {
testCases := []struct {
name string
tx DynamicFeeTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty dynamic fee tx",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
GasLimit: uint64(1),
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveFee(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxEffectiveCost() {
testCases := []struct {
name string
tx DynamicFeeTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty dynamic fee tx",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
GasLimit: uint64(1),
Amount: &suite.sdkZeroInt,
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveCost(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxFeeCost() {
tx := &DynamicFeeTx{}
suite.Require().Panics(func() { tx.Fee() }, "should panic")

View File

@ -115,6 +115,11 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
genState: &GenesisState{},
expPass: false,
},
{
name: "copied genesis",
genState: NewGenesisState(DefaultGenesisState().Params, DefaultGenesisState().Accounts),
expPass: true,
},
{
name: "invalid genesis",
genState: &GenesisState{

View File

@ -349,9 +349,84 @@ func (suite *TxDataTestSuite) TestLegacyTxValidate() {
}
}
func (suite *TxDataTestSuite) TestLegacyTxEffectiveGasPrice() {
testCases := []struct {
name string
tx LegacyTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty legacy tx",
LegacyTx{
GasPrice: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveGasPrice(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxEffectiveFee() {
testCases := []struct {
name string
tx LegacyTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty legacy tx",
LegacyTx{
GasPrice: &suite.sdkInt,
GasLimit: uint64(1),
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveFee(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxEffectiveCost() {
testCases := []struct {
name string
tx LegacyTx
baseFee *big.Int
exp *big.Int
}{
{
"non-empty legacy tx",
LegacyTx{
GasPrice: &suite.sdkInt,
GasLimit: uint64(1),
Amount: &suite.sdkZeroInt,
},
(&suite.sdkInt).BigInt(),
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.EffectiveCost(tc.baseFee)
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxFeeCost() {
tx := &LegacyTx{}
suite.Require().Panics(func() { tx.Fee() }, "should panice")
suite.Require().Panics(func() { tx.Cost() }, "should panice")
suite.Require().Panics(func() { tx.Fee() }, "should panic")
suite.Require().Panics(func() { tx.Cost() }, "should panic")
}

View File

@ -45,6 +45,14 @@ func TestTransactionLogsValidate(t *testing.T) {
},
false,
},
{
"nil log",
TransactionLogs{
Hash: common.BytesToHash([]byte("tx_hash")).String(),
Logs: []*Log{nil},
},
false,
},
{
"invalid log",
TransactionLogs{
@ -158,3 +166,36 @@ func TestValidateLog(t *testing.T) {
}
}
}
func TestConversionFunctions(t *testing.T) {
addr := tests.GenerateAddress().String()
txLogs := TransactionLogs{
Hash: common.BytesToHash([]byte("tx_hash")).String(),
Logs: []*Log{
{
Address: addr,
Topics: []string{common.BytesToHash([]byte("topic")).String()},
Data: []byte("data"),
BlockNumber: 1,
TxHash: common.BytesToHash([]byte("tx_hash")).String(),
TxIndex: 1,
BlockHash: common.BytesToHash([]byte("block_hash")).String(),
Index: 1,
Removed: false,
},
},
}
// convert valid log to eth logs and back (and validate)
conversionLogs := NewTransactionLogsFromEth(common.BytesToHash([]byte("tx_hash")), txLogs.EthLogs())
conversionErr := conversionLogs.Validate()
// create new transaction logs as copy of old valid one (and validate)
copyLogs := NewTransactionLogs(common.BytesToHash([]byte("tx_hash")), txLogs.Logs)
copyErr := copyLogs.Validate()
require.Nil(t, conversionErr)
require.Nil(t, copyErr)
}

288
x/evm/types/tx_args_test.go Normal file
View File

@ -0,0 +1,288 @@
package types
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
//"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func (suite *TxDataTestSuite) TestTxArgsString() {
testCases := []struct {
name string
txArgs TransactionArgs
expectedString string
}{
{
"empty tx args",
TransactionArgs{},
"TransactionArgs{From:<nil>, To:<nil>, Gas:<nil>, Nonce:<nil>, Data:<nil>, Input:<nil>, AccessList:<nil>}",
},
{
"tx args with fields",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
Nonce: &suite.hexUint64,
Input: &suite.hexInputBytes,
Data: &suite.hexDataBytes,
AccessList: &ethtypes.AccessList{},
},
fmt.Sprintf("TransactionArgs{From:%v, To:%v, Gas:%v, Nonce:%v, Data:%v, Input:%v, AccessList:%v}",
&suite.addr,
&suite.addr,
&suite.hexUint64,
&suite.hexUint64,
&suite.hexDataBytes,
&suite.hexInputBytes,
&ethtypes.AccessList{}),
},
}
for _, tc := range testCases {
outputString := tc.txArgs.String()
suite.Require().Equal(outputString, tc.expectedString)
}
}
func (suite *TxDataTestSuite) TestConvertTxArgsEthTx() {
testCases := []struct {
name string
txArgs TransactionArgs
}{
{
"empty tx args",
TransactionArgs{},
},
{
"no nil args",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: &suite.hexBigInt,
MaxPriorityFeePerGas: &suite.hexBigInt,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
},
{
"max fee per gas nil, but access list not nil",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: nil,
MaxPriorityFeePerGas: &suite.hexBigInt,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
},
}
for _, tc := range testCases {
res := tc.txArgs.ToTransaction()
suite.Require().NotNil(res)
}
}
func (suite *TxDataTestSuite) TestToMessageEVM() {
testCases := []struct {
name string
txArgs TransactionArgs
globalGasCap uint64
baseFee *big.Int
expError bool
}{
{
"empty tx args",
TransactionArgs{},
uint64(0),
nil,
false,
},
{
"specify gasPrice and (maxFeePerGas or maxPriorityFeePerGas)",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: &suite.hexBigInt,
MaxPriorityFeePerGas: &suite.hexBigInt,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
uint64(0),
nil,
true,
},
{
"non-1559 execution, zero gas cap",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: nil,
MaxPriorityFeePerGas: nil,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
uint64(0),
nil,
false,
},
{
"non-1559 execution, nonzero gas cap",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: nil,
MaxPriorityFeePerGas: nil,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
uint64(1),
nil,
false,
},
{
"1559-type execution, nil gas price",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: nil,
MaxFeePerGas: &suite.hexBigInt,
MaxPriorityFeePerGas: &suite.hexBigInt,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
uint64(1),
suite.bigInt,
false,
},
{
"1559-type execution, non-nil gas price",
TransactionArgs{
From: &suite.addr,
To: &suite.addr,
Gas: &suite.hexUint64,
GasPrice: &suite.hexBigInt,
MaxFeePerGas: nil,
MaxPriorityFeePerGas: nil,
Value: &suite.hexBigInt,
Nonce: &suite.hexUint64,
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
AccessList: &ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
ChainID: &suite.hexBigInt,
},
uint64(1),
suite.bigInt,
false,
},
}
for _, tc := range testCases {
res, err := tc.txArgs.ToMessage(tc.globalGasCap, tc.baseFee)
if tc.expError {
suite.Require().NotNil(err)
} else {
suite.Require().Nil(err)
suite.Require().NotNil(res)
}
}
}
func (suite *TxDataTestSuite) TestGetFrom() {
testCases := []struct {
name string
txArgs TransactionArgs
expAddress common.Address
}{
{
"empty from field",
TransactionArgs{},
common.Address{},
},
{
"non-empty from field",
TransactionArgs{
From: &suite.addr,
},
suite.addr,
},
}
for _, tc := range testCases {
retrievedAddress := tc.txArgs.GetFrom()
suite.Require().Equal(retrievedAddress, tc.expAddress)
}
}
func (suite *TxDataTestSuite) TestGetData() {
testCases := []struct {
name string
txArgs TransactionArgs
expectedOutput []byte
}{
{
"empty input and data fields",
TransactionArgs{
Data: nil,
Input: nil,
},
nil,
},
{
"empty input field, non-empty data field",
TransactionArgs{
Data: &suite.hexDataBytes,
Input: nil,
},
[]byte("data"),
},
{
"non-empty input and data fields",
TransactionArgs{
Data: &suite.hexDataBytes,
Input: &suite.hexInputBytes,
},
[]byte("input"),
},
}
for _, tc := range testCases {
retrievedData := tc.txArgs.GetData()
suite.Require().Equal(retrievedData, tc.expectedOutput)
}
}

View File

@ -14,6 +14,8 @@ import (
evmtypes "github.com/evmos/ethermint/x/evm/types"
proto "github.com/gogo/protobuf/proto"
"github.com/evmos/ethermint/tests"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
@ -84,3 +86,31 @@ func TestBinSearch(t *testing.T) {
require.Error(t, err)
require.Equal(t, gas, uint64(0))
}
func TestTransactionLogsEncodeDecode(t *testing.T) {
addr := tests.GenerateAddress().String()
txLogs := evmtypes.TransactionLogs{
Hash: common.BytesToHash([]byte("tx_hash")).String(),
Logs: []*evmtypes.Log{
{
Address: addr,
Topics: []string{common.BytesToHash([]byte("topic")).String()},
Data: []byte("data"),
BlockNumber: 1,
TxHash: common.BytesToHash([]byte("tx_hash")).String(),
TxIndex: 1,
BlockHash: common.BytesToHash([]byte("block_hash")).String(),
Index: 1,
Removed: false,
},
},
}
txLogsEncoded, encodeErr := evmtypes.EncodeTransactionLogs(&txLogs)
require.Nil(t, encodeErr)
txLogsEncodedDecoded, decodeErr := evmtypes.DecodeTransactionLogs(txLogsEncoded)
require.Nil(t, decodeErr)
require.Equal(t, txLogs, txLogsEncodedDecoded)
}