evm: unit tests (#619)

* evm: unit tests

* Add unit tests for DynamicFeeTx.Validate()

* Start get and set signature values tests

* get set values

* Add tests for GetTo()

* Add GetNonce test

* Add GetValue test

* Start copy test

* Add WIP newDynamicFeeTx test

* Add WIP legacy_tx_test

* pair programming session

* Add TestLegacyTxValidate

* Add TestLegacyTxSetSignatureValues & GetSignatureValues

* Add legacyTx tests

* Merge main, forgot to save one file

* Add AccessList tests

* Add chain Config (fork order)

* Add invalid genesis account test

* Add params tests

* Add WIP tracer test

* tracer tests

* Add FormatLogs tests

* Add NewNoOpTracer test

* Refactor to test suite

* Refactor Tx Test suits to only use TxDataTestSuite

* Update link to geth interpreter

* Update x/evm/types/params.go

* Refactor accessListTx Test suits to  use TxDataTestSuite

Co-authored-by: Daniel Burckhardt <daniel.m.burckhardt@gmail.com>
This commit is contained in:
Federico Kunze Küllmer 2021-10-08 13:11:19 +02:00 committed by GitHub
parent f69c887276
commit 516972119c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1111 additions and 14 deletions

View File

@ -0,0 +1,38 @@
package types
import (
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func (suite *TxDataTestSuite) TestTestNewAccessList() {
testCases := []struct {
name string
ethAccessList *ethtypes.AccessList
expAl AccessList
}{
{
"ethAccessList is nil",
nil,
nil,
},
{
"non-empty ethAccessList",
&ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}},
AccessList{{Address: suite.hexAddr, StorageKeys: []string{common.Hash{}.Hex()}}},
},
}
for _, tc := range testCases {
al := NewAccessList(tc.ethAccessList)
suite.Require().Equal(tc.expAl, al)
}
}
func (suite *TxDataTestSuite) TestAccessListToEthAccessList() {
ethAccessList := ethtypes.AccessList{{Address: suite.addr, StorageKeys: []common.Hash{{0}}}}
al := NewAccessList(&ethAccessList)
actual := al.ToEthAccessList()
suite.Require().Equal(&ethAccessList, actual)
}

View File

@ -238,7 +238,6 @@ func TestChainConfigValidate(t *testing.T) {
}, },
true, true,
}, },
{ {
"invalid CatalystBlock", "invalid CatalystBlock",
ChainConfig{ ChainConfig{
@ -258,6 +257,25 @@ func TestChainConfigValidate(t *testing.T) {
}, },
true, true,
}, },
{
"invalid fork order - skip HomesteadBlock",
ChainConfig{
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),
CatalystBlock: newIntPtr(0),
},
true,
},
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -103,7 +103,7 @@ func (tx *DynamicFeeTx) GetGasPrice() *big.Int {
return tx.GetGasFeeCap() return tx.GetGasFeeCap()
} }
// GetGasTipCap returns the gas price field. // GetGasTipCap returns the gas tip cap field.
func (tx *DynamicFeeTx) GetGasTipCap() *big.Int { func (tx *DynamicFeeTx) GetGasTipCap() *big.Int {
if tx.GasTipCap == nil { if tx.GasTipCap == nil {
return nil return nil
@ -111,7 +111,7 @@ func (tx *DynamicFeeTx) GetGasTipCap() *big.Int {
return tx.GasTipCap.BigInt() return tx.GasTipCap.BigInt()
} }
// GetGasFeeCap returns the gas price field. // GetGasFeeCap returns the gas fee cap field.
func (tx *DynamicFeeTx) GetGasFeeCap() *big.Int { func (tx *DynamicFeeTx) GetGasFeeCap() *big.Int {
if tx.GasFeeCap == nil { if tx.GasFeeCap == nil {
return nil return nil

View File

@ -0,0 +1,501 @@
package types
import (
"math/big"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/suite"
"github.com/tharsis/ethermint/tests"
)
type TxDataTestSuite struct {
suite.Suite
sdkInt sdk.Int
uint64 uint64
bigInt *big.Int
sdkZeroInt sdk.Int
sdkMinusOneInt sdk.Int
invalidAddr string
addr common.Address
hexAddr string
}
func (suite *TxDataTestSuite) SetupTest() {
suite.sdkInt = sdk.NewInt(100)
suite.uint64 = suite.sdkInt.Uint64()
suite.bigInt = big.NewInt(1)
suite.sdkZeroInt = sdk.ZeroInt()
suite.sdkMinusOneInt = sdk.NewInt(-1)
suite.invalidAddr = "123456"
suite.addr = tests.GenerateAddress()
suite.hexAddr = suite.addr.Hex()
}
func TestTxDataTestSuite(t *testing.T) {
suite.Run(t, new(TxDataTestSuite))
}
func (suite *TxDataTestSuite) TestNewDynamicFeeTx() {
testCases := []struct {
name string
tx *ethtypes.Transaction
}{
{
"non-empty tx",
ethtypes.NewTx(&ethtypes.AccessListTx{ // TODO: change to DynamicFeeTx on Geth
Nonce: 1,
Data: []byte("data"),
Gas: 100,
Value: big.NewInt(1),
AccessList: ethtypes.AccessList{},
To: &suite.addr,
V: suite.bigInt,
R: suite.bigInt,
S: suite.bigInt,
}),
},
}
for _, tc := range testCases {
tx := newDynamicFeeTx(tc.tx)
suite.Require().NotEmpty(tx)
suite.Require().Equal(uint8(2), tx.TxType())
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxCopy() {
tx := &DynamicFeeTx{}
txCopy := tx.Copy()
suite.Require().Equal(&DynamicFeeTx{}, txCopy)
// TODO: Test for different pointers
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetChainID() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *big.Int
}{
{
"empty chainID",
DynamicFeeTx{
ChainID: nil,
},
nil,
},
{
"non-empty chainID",
DynamicFeeTx{
ChainID: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetChainID()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetAccessList() {
testCases := []struct {
name string
tx DynamicFeeTx
exp ethtypes.AccessList
}{
{
"empty accesses",
DynamicFeeTx{
Accesses: nil,
},
nil,
},
{
"nil",
DynamicFeeTx{
Accesses: NewAccessList(nil),
},
nil,
},
{
"non-empty accesses",
DynamicFeeTx{
Accesses: AccessList{
{
Address: suite.hexAddr,
StorageKeys: []string{},
},
},
},
ethtypes.AccessList{
{
Address: suite.addr,
StorageKeys: []common.Hash{},
},
},
},
}
for _, tc := range testCases {
actual := tc.tx.GetAccessList()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetData() {
testCases := []struct {
name string
tx DynamicFeeTx
}{
{
"non-empty transaction",
DynamicFeeTx{
Data: nil,
},
},
}
for _, tc := range testCases {
actual := tc.tx.GetData()
suite.Require().Equal(tc.tx.Data, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetGas() {
testCases := []struct {
name string
tx DynamicFeeTx
exp uint64
}{
{
"non-empty gas",
DynamicFeeTx{
GasLimit: suite.uint64,
},
suite.uint64,
},
}
for _, tc := range testCases {
actual := tc.tx.GetGas()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasPrice() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *big.Int
}{
{
"non-empty gasFeeCap",
DynamicFeeTx{
GasFeeCap: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasPrice()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasTipCap() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *big.Int
}{
{
"empty gasTipCap",
DynamicFeeTx{
GasTipCap: nil,
},
nil,
},
{
"non-empty gasTipCap",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasTipCap()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetGasFeeCap() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *big.Int
}{
{
"empty gasFeeCap",
DynamicFeeTx{
GasFeeCap: nil,
},
nil,
},
{
"non-empty gasFeeCap",
DynamicFeeTx{
GasFeeCap: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasFeeCap()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetValue() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *big.Int
}{
{
"empty amount",
DynamicFeeTx{
Amount: nil,
},
nil,
},
{
"non-empty amount",
DynamicFeeTx{
Amount: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetValue()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetNonce() {
testCases := []struct {
name string
tx DynamicFeeTx
exp uint64
}{
{
"non-empty nonce",
DynamicFeeTx{
Nonce: suite.uint64,
},
suite.uint64,
},
}
for _, tc := range testCases {
actual := tc.tx.GetNonce()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxGetTo() {
testCases := []struct {
name string
tx DynamicFeeTx
exp *common.Address
}{
{
"empty suite.address",
DynamicFeeTx{
To: "",
},
nil,
},
{
"non-empty suite.address",
DynamicFeeTx{
To: suite.hexAddr,
},
&suite.addr,
},
}
for _, tc := range testCases {
actual := tc.tx.GetTo()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxSetSignatureValues() {
testCases := []struct {
name string
chainID *big.Int
r *big.Int
v *big.Int
s *big.Int
}{
{
"empty values",
nil,
nil,
nil,
nil,
},
{
"non-empty values",
suite.bigInt,
suite.bigInt,
suite.bigInt,
suite.bigInt,
},
}
for _, tc := range testCases {
tx := &DynamicFeeTx{}
tx.SetSignatureValues(tc.chainID, tc.v, tc.r, tc.s)
v, r, s := tx.GetRawSignatureValues()
chainID := tx.GetChainID()
suite.Require().Equal(tc.v, v, tc.name)
suite.Require().Equal(tc.r, r, tc.name)
suite.Require().Equal(tc.s, s, tc.name)
suite.Require().Equal(tc.chainID, chainID, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxValidate() {
testCases := []struct {
name string
tx DynamicFeeTx
expError bool
}{
{
"empty",
DynamicFeeTx{},
true,
},
{
"gas tip cap is nil",
DynamicFeeTx{
GasTipCap: nil,
},
true,
},
{
"gas fee cap is nil",
DynamicFeeTx{
GasTipCap: &suite.sdkZeroInt,
},
true,
},
{
"gas tip cap is negative",
DynamicFeeTx{
GasTipCap: &suite.sdkMinusOneInt,
GasFeeCap: &suite.sdkZeroInt,
},
true,
},
{
"gas tip cap is negative",
DynamicFeeTx{
GasTipCap: &suite.sdkZeroInt,
GasFeeCap: &suite.sdkMinusOneInt,
},
true,
},
{
"gas fee cap < gas tip cap",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkZeroInt,
},
true,
},
{
"amount is negative",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
Amount: &suite.sdkMinusOneInt,
},
true,
},
{
"to suite.address is invalid",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
Amount: &suite.sdkInt,
To: suite.invalidAddr,
},
true,
},
{
"chain ID not present on AccessList txs",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
Amount: &suite.sdkInt,
To: suite.hexAddr,
ChainID: nil,
},
true,
},
{
"no errors",
DynamicFeeTx{
GasTipCap: &suite.sdkInt,
GasFeeCap: &suite.sdkInt,
Amount: &suite.sdkInt,
To: suite.hexAddr,
ChainID: &suite.sdkInt,
},
false,
},
}
for _, tc := range testCases {
err := tc.tx.Validate()
if tc.expError {
suite.Require().Error(err, tc.name)
continue
}
suite.Require().NoError(err, tc.name)
}
}
func (suite *TxDataTestSuite) TestDynamicFeeTxFeeCost() {
tx := &DynamicFeeTx{}
suite.Require().Panics(func() { tx.Fee() }, "should panic")
suite.Require().Panics(func() { tx.Cost() }, "should panic")
}

View File

@ -126,6 +126,23 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
}, },
expPass: false, expPass: false,
}, },
{
name: "invalid genesis account",
genState: &GenesisState{
Accounts: []GenesisAccount{
{
Address: "123456",
Code: suite.code,
Storage: Storage{
{Key: suite.hash.String()},
},
},
},
Params: DefaultParams(),
},
expPass: false,
},
{ {
name: "duplicated genesis account", name: "duplicated genesis account",
genState: &GenesisState{ genState: &GenesisState{

View File

@ -155,7 +155,7 @@ func (tx *LegacyTx) SetSignatureValues(_, v, r, s *big.Int) {
func (tx LegacyTx) Validate() error { func (tx LegacyTx) Validate() error {
gasPrice := tx.GetGasPrice() gasPrice := tx.GetGasPrice()
if gasPrice == nil { if gasPrice == nil {
return sdkerrors.Wrap(ErrInvalidGasPrice, "cannot be nil") return sdkerrors.Wrap(ErrInvalidGasPrice, "gas price cannot be nil")
} }
if gasPrice.Sign() == -1 { if gasPrice.Sign() == -1 {

View File

@ -0,0 +1,356 @@
package types
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func (suite *TxDataTestSuite) TestNewLegacyTx() {
testCases := []struct {
name string
tx *ethtypes.Transaction
}{
{
"non-empty Transaction",
ethtypes.NewTx(&ethtypes.AccessListTx{
Nonce: 1,
Data: []byte("data"),
Gas: 100,
Value: big.NewInt(1),
AccessList: ethtypes.AccessList{},
To: &suite.addr,
V: big.NewInt(1),
R: big.NewInt(1),
S: big.NewInt(1),
}),
},
}
for _, tc := range testCases {
tx := newLegacyTx(tc.tx)
suite.Require().NotEmpty(tc.tx)
suite.Require().Equal(uint8(0), tx.TxType())
}
}
func (suite *TxDataTestSuite) TestLegacyTxTxType() {
tx := LegacyTx{}
actual := tx.TxType()
suite.Require().Equal(uint8(0), actual)
}
func (suite *TxDataTestSuite) TestLegacyTxCopy() {
tx := &LegacyTx{}
txData := tx.Copy()
suite.Require().Equal(&LegacyTx{}, txData)
// TODO: Test for different pointers
}
func (suite *TxDataTestSuite) TestLegacyTxGetChainID() {
tx := LegacyTx{}
actual := tx.GetChainID()
suite.Require().Nil(actual)
}
func (suite *TxDataTestSuite) TestLegacyTxGetAccessList() {
tx := LegacyTx{}
actual := tx.GetAccessList()
suite.Require().Nil(actual)
}
func (suite *TxDataTestSuite) TestLegacyTxGetData() {
testCases := []struct {
name string
tx LegacyTx
}{
{
"non-empty transaction",
LegacyTx{
Data: nil,
},
},
}
for _, tc := range testCases {
actual := tc.tx.GetData()
suite.Require().Equal(tc.tx.Data, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetGas() {
testCases := []struct {
name string
tx LegacyTx
exp uint64
}{
{
"non-empty gas",
LegacyTx{
GasLimit: suite.uint64,
},
suite.uint64,
},
}
for _, tc := range testCases {
actual := tc.tx.GetGas()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetGasPrice() {
testCases := []struct {
name string
tx LegacyTx
exp *big.Int
}{
{
"empty gasPrice",
LegacyTx{
GasPrice: nil,
},
nil,
},
{
"non-empty gasPrice",
LegacyTx{
GasPrice: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasFeeCap()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetGasTipCap() {
testCases := []struct {
name string
tx LegacyTx
exp *big.Int
}{
{
"non-empty gasPrice",
LegacyTx{
GasPrice: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasTipCap()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetGasFeeCap() {
testCases := []struct {
name string
tx LegacyTx
exp *big.Int
}{
{
"non-empty gasPrice",
LegacyTx{
GasPrice: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetGasFeeCap()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetValue() {
testCases := []struct {
name string
tx LegacyTx
exp *big.Int
}{
{
"empty amount",
LegacyTx{
Amount: nil,
},
nil,
},
{
"non-empty amount",
LegacyTx{
Amount: &suite.sdkInt,
},
(&suite.sdkInt).BigInt(),
},
}
for _, tc := range testCases {
actual := tc.tx.GetValue()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetNonce() {
testCases := []struct {
name string
tx LegacyTx
exp uint64
}{
{
"none-empty nonce",
LegacyTx{
Nonce: suite.uint64,
},
suite.uint64,
},
}
for _, tc := range testCases {
actual := tc.tx.GetNonce()
suite.Require().Equal(tc.exp, actual)
}
}
func (suite *TxDataTestSuite) TestLegacyTxGetTo() {
testCases := []struct {
name string
tx LegacyTx
exp *common.Address
}{
{
"empty address",
LegacyTx{
To: "",
},
nil,
},
{
"non-empty address",
LegacyTx{
To: suite.hexAddr,
},
&suite.addr,
},
}
for _, tc := range testCases {
actual := tc.tx.GetTo()
suite.Require().Equal(tc.exp, actual, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxAsEthereumData() {
tx := &LegacyTx{}
txData := tx.AsEthereumData()
suite.Require().Equal(&ethtypes.LegacyTx{}, txData)
}
func (suite *TxDataTestSuite) TestLegacyTxSetSignatureValues() {
testCases := []struct {
name string
v *big.Int
r *big.Int
s *big.Int
}{
{
"non-empty values",
suite.bigInt,
suite.bigInt,
suite.bigInt,
},
}
for _, tc := range testCases {
tx := &LegacyTx{}
tx.SetSignatureValues(nil, tc.v, tc.r, tc.s)
v, r, s := tx.GetRawSignatureValues()
suite.Require().Equal(tc.v, v, tc.name)
suite.Require().Equal(tc.r, r, tc.name)
suite.Require().Equal(tc.s, s, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxValidate() {
testCases := []struct {
name string
tx LegacyTx
expError bool
}{
{
"empty",
LegacyTx{},
true,
},
{
"gas price is nil",
LegacyTx{
GasPrice: nil,
},
true,
},
{
"gas price is negative",
LegacyTx{
GasPrice: &suite.sdkMinusOneInt,
},
true,
},
{
"amount is negative",
LegacyTx{
GasPrice: &suite.sdkInt,
Amount: &suite.sdkMinusOneInt,
},
true,
},
{
"to address is invalid",
LegacyTx{
GasPrice: &suite.sdkInt,
Amount: &suite.sdkInt,
To: suite.invalidAddr,
},
true,
},
}
for _, tc := range testCases {
err := tc.tx.Validate()
if tc.expError {
suite.Require().Error(err, tc.name)
continue
}
suite.Require().NoError(err, tc.name)
}
}
func (suite *TxDataTestSuite) TestLegacyTxFeeCost() {
tx := &LegacyTx{}
suite.Require().Panics(func() { tx.Fee() }, "should panice")
suite.Require().Panics(func() { tx.Cost() }, "should panice")
}

View File

@ -42,8 +42,13 @@ func NewTx(
// NewTxContract returns a reference to a new Ethereum transaction // NewTxContract returns a reference to a new Ethereum transaction
// message designated for contract creation. // message designated for contract creation.
func NewTxContract( func NewTxContract(
chainID *big.Int, nonce uint64, amount *big.Int, chainID *big.Int,
gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, input []byte, accesses *ethtypes.AccessList, nonce uint64,
amount *big.Int,
gasLimit uint64,
gasPrice, gasFeeCap, gasTipCap *big.Int,
input []byte,
accesses *ethtypes.AccessList,
) *MsgEthereumTx { ) *MsgEthereumTx {
return newMsgEthereumTx(chainID, nonce, nil, amount, gasLimit, gasPrice, gasFeeCap, gasTipCap, input, accesses) return newMsgEthereumTx(chainID, nonce, nil, amount, gasLimit, gasPrice, gasFeeCap, gasTipCap, input, accesses)
} }

View File

@ -23,9 +23,11 @@ var (
ParamStoreKeyExtraEIPs = []byte("EnableExtraEIPs") ParamStoreKeyExtraEIPs = []byte("EnableExtraEIPs")
ParamStoreKeyChainConfig = []byte("ChainConfig") ParamStoreKeyChainConfig = []byte("ChainConfig")
// AvailableExtraEIPs define the list of all EIPs that can be enabled by the EVM interpreter. These EIPs are applied in // AvailableExtraEIPs define the list of all EIPs that can be enabled by the
// order and can override the instruction sets from the latest hard fork enabled by the ChainConfig. For more info // EVM interpreter. These EIPs are applied in order and can override the
// check: https://github.com/ethereum/go-ethereum/blob/v1.10.4/core/vm/interpreter.go#L122 // instruction sets from the latest hard fork enabled by the ChainConfig. For
// more info check:
// https://github.com/ethereum/go-ethereum/blob/master/core/vm/interpreter.go#L97
AvailableExtraEIPs = []int64{1344, 1884, 2200, 2929, 3198, 3529} AvailableExtraEIPs = []int64{1344, 1884, 2200, 2929, 3198, 3529}
) )

View File

@ -3,9 +3,14 @@ package types
import ( import (
"testing" "testing"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestParamKeyTable(t *testing.T) {
require.IsType(t, paramtypes.KeyTable{}, ParamKeyTable())
}
func TestParamsValidate(t *testing.T) { func TestParamsValidate(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
@ -56,6 +61,13 @@ func TestParamsValidate(t *testing.T) {
} }
} }
func TestParamsEIPs(t *testing.T) {
params := NewParams("ara", true, true, DefaultChainConfig(), 2929, 1884, 1344)
actual := params.EIPs()
require.Equal(t, []int([]int{2929, 1884, 1344}), actual)
}
func TestParamsValidatePriv(t *testing.T) { func TestParamsValidatePriv(t *testing.T) {
require.Error(t, validateEVMDenom(false)) require.Error(t, validateEVMDenom(false))
require.NoError(t, validateEVMDenom("inj")) require.NoError(t, validateEVMDenom("inj"))
@ -64,3 +76,31 @@ func TestParamsValidatePriv(t *testing.T) {
require.Error(t, validateEIPs("")) require.Error(t, validateEIPs(""))
require.NoError(t, validateEIPs([]int64{1884})) require.NoError(t, validateEIPs([]int64{1884}))
} }
func TestValidateChainConfig(t *testing.T) {
testCases := []struct {
name string
i interface{}
expError bool
}{
{
"invalid chain config type",
"string",
true,
},
{
"valid chain config type",
DefaultChainConfig(),
false,
},
}
for _, tc := range testCases {
err := validateChainConfig(tc.i)
if tc.expError {
require.Error(t, err, tc.name)
} else {
require.NoError(t, err, tc.name)
}
}
}

View File

@ -126,23 +126,60 @@ func NewNoOpTracer() *NoOpTracer {
} }
// CaptureStart implements vm.Tracer interface // CaptureStart implements vm.Tracer interface
func (dt NoOpTracer) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { func (dt NoOpTracer) CaptureStart(
env *vm.EVM,
from, to common.Address,
create bool,
input []byte,
gas uint64,
value *big.Int,
) {
} }
// CaptureEnter implements vm.Tracer interface // CaptureEnter implements vm.Tracer interface
func (dt NoOpTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { func (dt NoOpTracer) CaptureEnter(
typ vm.OpCode,
from common.Address,
to common.Address,
input []byte,
gas uint64,
value *big.Int,
) {
} }
// CaptureExit implements vm.Tracer interface // CaptureExit implements vm.Tracer interface
func (dt NoOpTracer) CaptureExit(output []byte, gasUsed uint64, err error) {} func (dt NoOpTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
// CaptureState implements vm.Tracer interface // CaptureState implements vm.Tracer interface
func (dt NoOpTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { func (dt NoOpTracer) CaptureState(
env *vm.EVM,
pc uint64,
op vm.OpCode,
gas, cost uint64,
scope *vm.ScopeContext,
rData []byte,
depth int,
err error,
) {
} }
// CaptureFault implements vm.Tracer interface // CaptureFault implements vm.Tracer interface
func (dt NoOpTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { func (dt NoOpTracer) CaptureFault(
env *vm.EVM,
pc uint64,
op vm.OpCode,
gas, cost uint64,
scope *vm.ScopeContext,
depth int,
err error,
) {
} }
// CaptureEnd implements vm.Tracer interface // CaptureEnd implements vm.Tracer interface
func (dt NoOpTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {} func (dt NoOpTracer) CaptureEnd(
output []byte,
gasUsed uint64,
t time.Duration,
err error,
) {
}

View File

@ -0,0 +1,83 @@
package types
import (
"fmt"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"
)
func TestFormatLogs(t *testing.T) {
zeroUint256 := []uint256.Int{*uint256.NewInt(0)}
zeroByte := []byte{5}
zeroStorage := make(map[string]string)
testCases := []struct {
name string
logs []vm.StructLog
exp []StructLogRes
}{
{
"empty logs",
[]vm.StructLog{},
[]StructLogRes{},
},
{
"non-empty stack",
[]vm.StructLog{
{
Stack: zeroUint256,
},
},
[]StructLogRes{
{
Pc: uint64(0),
Op: "STOP",
Stack: &[]string{fmt.Sprintf("%x", zeroUint256[0])},
},
},
},
{
"non-empty memory",
[]vm.StructLog{
{
Memory: zeroByte,
},
},
[]StructLogRes{
{
Pc: uint64(0),
Op: "STOP",
Memory: &[]string{},
},
},
},
{
"non-empty storage",
[]vm.StructLog{
{
Storage: make(map[common.Hash]common.Hash),
},
},
[]StructLogRes{
{
Pc: uint64(0),
Op: "STOP",
Storage: &zeroStorage,
},
},
},
}
for _, tc := range testCases {
actual := FormatLogs(tc.logs)
require.Equal(t, tc.exp, actual)
}
}
func TestNewNoOpTracer(t *testing.T) {
require.Equal(t, &NoOpTracer{}, NewNoOpTracer())
}