laconicd-deprecated/rpc/backend/evm_backend_test.go
yihuang b1cd16e5bf
feat!: Apply feemarket to native cosmos tx (#1194)
* Problem: feemarket's query cli has redundant height parameter

Soluton:
- remove the positional height parameter, since there's a flag already.

Update CHANGELOG.md

* Apply feemarket to native cosmos tx

- add tx extension option for user to input tip price
- apply feemarket's base fee to native tx

comments and cleanup

fallback to default sdk logic when london hardfork not enabled

integration test

cleanup feemarket query cli commands

Update CHANGELOG.md

update unit tests

disable feemarket in simulation tests for now

fix lint

Update app/simulation_test.go

fix python lint

fix lint

Update x/evm/types/extension_option.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

address review suggestions

* fix unit tests

* fix integration test

* improve unit test coverage

* fix go lint

* refactor

* fix integration test

* fix simulation tests

* fix go linter

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
2022-08-10 18:33:38 -04:00

983 lines
26 KiB
Go

package backend
import (
"fmt"
"math/big"
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/tendermint/tendermint/abci/types"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
"google.golang.org/grpc/metadata"
"github.com/evmos/ethermint/rpc/backend/mocks"
ethrpc "github.com/evmos/ethermint/rpc/types"
"github.com/evmos/ethermint/tests"
evmtypes "github.com/evmos/ethermint/x/evm/types"
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
)
func (suite *BackendTestSuite) TestBlockNumber() {
testCases := []struct {
name string
registerMock func()
expBlockNumber hexutil.Uint64
expPass bool
}{
{
"fail - invalid block header height",
func() {
height := int64(1)
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterParamsInvalidHeight(queryClient, &header, int64(height))
},
0x0,
false,
},
{
"fail - invalid block header",
func() {
height := int64(1)
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterParamsInvalidHeader(queryClient, &header, int64(height))
},
0x0,
false,
},
{
"pass - app state header height 1",
func() {
height := int64(1)
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterParams(queryClient, &header, int64(height))
},
0x1,
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
blockNumber, err := suite.backend.BlockNumber()
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expBlockNumber, blockNumber)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetBlockByNumber() {
var (
blockRes *tmrpctypes.ResultBlockResults
resBlock *tmrpctypes.ResultBlock
)
msgEthereumTx, bz := suite.buildEthereumTx()
testCases := []struct {
name string
blockNumber ethrpc.BlockNumber
fullTx bool
baseFee *big.Int
validator sdk.AccAddress
tx *evmtypes.MsgEthereumTx
txBz []byte
registerMock func(ethrpc.BlockNumber, sdk.Int, sdk.AccAddress, []byte)
expNoop bool
expPass bool
}{
{
"pass - tendermint block not found",
ethrpc.BlockNumber(1),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
nil,
nil,
func(blockNum ethrpc.BlockNumber, _ sdk.Int, _ sdk.AccAddress, _ []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, height)
},
true,
true,
},
{
"pass - block not found (e.g. request block height that is greater than current one)",
ethrpc.BlockNumber(1),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
nil,
nil,
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlockNotFound(client, height)
},
true,
true,
},
{
"pass - block results error",
ethrpc.BlockNumber(1),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
nil,
nil,
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
RegisterBlockResultsError(client, blockNum.Int64())
},
true,
true,
},
{
"pass - without tx",
ethrpc.BlockNumber(1),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
nil,
nil,
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
},
false,
true,
},
{
"pass - with tx",
ethrpc.BlockNumber(1),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
msgEthereumTx,
bz,
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlock(client, height, txBz)
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
},
false,
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock(tc.blockNumber, sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz)
block, err := suite.backend.GetBlockByNumber(tc.blockNumber, tc.fullTx)
if tc.expPass {
if tc.expNoop {
suite.Require().Nil(block)
} else {
expBlock := suite.buildFormattedBlock(
blockRes,
resBlock,
tc.fullTx,
tc.tx,
tc.validator,
tc.baseFee,
)
suite.Require().Equal(expBlock, block)
}
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetBlockByHash() {
var (
blockRes *tmrpctypes.ResultBlockResults
resBlock *tmrpctypes.ResultBlock
)
msgEthereumTx, bz := suite.buildEthereumTx()
block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil)
testCases := []struct {
name string
hash common.Hash
fullTx bool
baseFee *big.Int
validator sdk.AccAddress
tx *evmtypes.MsgEthereumTx
txBz []byte
registerMock func(common.Hash, sdk.Int, sdk.AccAddress, []byte)
expNoop bool
expPass bool
}{
{
"pass - without tx",
common.BytesToHash(block.Hash()),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
nil,
nil,
func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := int64(1)
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlockByHash(client, hash, txBz)
blockRes, _ = RegisterBlockResults(client, height)
RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
},
false,
true,
},
{
"pass - with tx",
common.BytesToHash(block.Hash()),
true,
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
msgEthereumTx,
bz,
func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
height := int64(1)
client := suite.backend.clientCtx.Client.(*mocks.Client)
resBlock, _ = RegisterBlockByHash(client, hash, txBz)
blockRes, _ = RegisterBlockResults(client, height)
RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
},
false,
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock(tc.hash, sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz)
block, err := suite.backend.GetBlockByHash(tc.hash, tc.fullTx)
if tc.expPass {
if tc.expNoop {
suite.Require().Nil(block)
} else {
expBlock := suite.buildFormattedBlock(
blockRes,
resBlock,
tc.fullTx,
tc.tx,
tc.validator,
tc.baseFee,
)
suite.Require().Equal(expBlock, block)
}
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetTendermintBlockByNumber() {
var expResultBlock *tmrpctypes.ResultBlock
testCases := []struct {
name string
blockNumber ethrpc.BlockNumber
registerMock func(ethrpc.BlockNumber)
found bool
expPass bool
}{
{
"fail - client error",
ethrpc.BlockNumber(1),
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, height)
},
false,
false,
},
{
"noop - block not found",
ethrpc.BlockNumber(1),
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockNotFound(client, height)
},
false,
true,
},
{
"fail - blockNum < 0 with app state height error",
ethrpc.BlockNumber(-1),
func(_ ethrpc.BlockNumber) {
appHeight := int64(1)
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterParamsError(queryClient, &header, appHeight)
},
false,
false,
},
{
"pass - blockNum < 0 with app state height >= 1",
ethrpc.BlockNumber(-1),
func(blockNum ethrpc.BlockNumber) {
appHeight := int64(1)
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterParams(queryClient, &header, appHeight)
tmHeight := appHeight
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, tmHeight, nil)
},
true,
true,
},
{
"pass - blockNum = 0 (defaults to blockNum = 1 due to a difference between tendermint heights and geth heights",
ethrpc.BlockNumber(0),
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, nil)
},
true,
true,
},
{
"pass - blockNum = 1",
ethrpc.BlockNumber(1),
func(blockNum ethrpc.BlockNumber) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, nil)
},
true,
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock(tc.blockNumber)
resultBlock, err := suite.backend.GetTendermintBlockByNumber(tc.blockNumber)
if tc.expPass {
suite.Require().NoError(err)
if !tc.found {
suite.Require().Nil(resultBlock)
} else {
suite.Require().Equal(expResultBlock, resultBlock)
suite.Require().Equal(expResultBlock.Block.Header.Height, resultBlock.Block.Header.Height)
}
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetTendermintBlockResultByNumber() {
var expBlockRes *tmrpctypes.ResultBlockResults
testCases := []struct {
name string
blockNumber int64
registerMock func(int64)
expPass bool
}{
{
"fail",
1,
func(blockNum int64) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockResultsError(client, blockNum)
},
false,
},
{
"pass",
1,
func(blockNum int64) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockResults(client, blockNum)
expBlockRes = &tmrpctypes.ResultBlockResults{
Height: blockNum,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock(tc.blockNumber)
blockRes, err := suite.backend.GetTendermintBlockResultByNumber(&tc.blockNumber)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(expBlockRes, blockRes)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestBlockBloom() {
testCases := []struct {
name string
blockRes *tmrpctypes.ResultBlockResults
expBlockBloom ethtypes.Bloom
expPass bool
}{
{
"fail - empty block result",
&tmrpctypes.ResultBlockResults{},
ethtypes.Bloom{},
false,
},
{
"fail - non block bloom event type",
&tmrpctypes.ResultBlockResults{
EndBlockEvents: []types.Event{{Type: evmtypes.EventTypeEthereumTx}},
},
ethtypes.Bloom{},
false,
},
{
"fail - nonblock bloom attribute key",
&tmrpctypes.ResultBlockResults{
EndBlockEvents: []types.Event{
{
Type: evmtypes.EventTypeBlockBloom,
Attributes: []types.EventAttribute{
{Key: []byte(evmtypes.AttributeKeyEthereumTxHash)},
},
},
},
},
ethtypes.Bloom{},
false,
},
{
"pass - nonblock bloom attribute key",
&tmrpctypes.ResultBlockResults{
EndBlockEvents: []types.Event{
{
Type: evmtypes.EventTypeBlockBloom,
Attributes: []types.EventAttribute{
{Key: []byte(bAttributeKeyEthereumBloom)},
},
},
},
},
ethtypes.Bloom{},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
blockBloom, err := suite.backend.BlockBloom(tc.blockRes)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expBlockBloom, blockBloom)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestEthBlockFromTendermint() {
msgEthereumTx, bz := suite.buildEthereumTx()
emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil)
testCases := []struct {
name string
baseFee *big.Int
validator sdk.AccAddress
height int64
resBlock *tmrpctypes.ResultBlock
blockRes *tmrpctypes.ResultBlockResults
fullTx bool
registerMock func(sdk.Int, sdk.AccAddress, int64)
expTxs bool
expPass bool
}{
{
"pass - block without tx",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(common.Address{}.Bytes()),
int64(1),
&tmrpctypes.ResultBlock{Block: emptyBlock},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
false,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
false,
true,
},
{
"pass - block with tx - with BaseFee error",
nil,
sdk.AccAddress(tests.GenerateAddress().Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
true,
true,
},
{
"pass - block with tx - with ValidatorAccount error",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(common.Address{}.Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccountError(queryClient)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
true,
true,
},
{
"pass - block with tx - with ConsensusParams error - BlockMaxGas defaults to max uint32",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParamsError(client, height)
},
true,
true,
},
{
"pass - block with tx - with ShouldIgnoreGasUsed - empty txs",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{
{
Code: 11,
GasUsed: 0,
Log: "no block gas left to run tx: out of gas",
},
},
},
true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
false,
true,
},
{
"pass - block with tx - non fullTx",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
false,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
true,
true,
},
{
"pass - block with tx",
sdk.NewInt(1).BigInt(),
sdk.AccAddress(tests.GenerateAddress().Bytes()),
int64(1),
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
Height: 1,
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
},
true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterConsensusParams(client, height)
},
true,
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock(sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.height)
block, err := suite.backend.EthBlockFromTendermint(tc.resBlock, tc.blockRes, tc.fullTx)
var expBlock map[string]interface{}
header := tc.resBlock.Block.Header
gasLimit := int64(^uint32(0)) // for `MaxGas = -1` (DefaultConsensusParams)
gasUsed := new(big.Int).SetUint64(uint64(tc.blockRes.TxsResults[0].GasUsed))
root := common.Hash{}.Bytes()
receipt := ethtypes.NewReceipt(root, false, gasUsed.Uint64())
bloom := ethtypes.CreateBloom(ethtypes.Receipts{receipt})
ethRPCTxs := []interface{}{}
if tc.expTxs {
if tc.fullTx {
rpcTx, err := ethrpc.NewRPCTransaction(
msgEthereumTx.AsTransaction(),
common.BytesToHash(header.Hash()),
uint64(header.Height),
uint64(0),
tc.baseFee,
)
suite.Require().NoError(err)
ethRPCTxs = []interface{}{rpcTx}
} else {
ethRPCTxs = []interface{}{common.HexToHash(msgEthereumTx.Hash)}
}
}
expBlock = ethrpc.FormatBlock(
header,
tc.resBlock.Block.Size(),
gasLimit,
gasUsed,
ethRPCTxs,
bloom,
common.BytesToAddress(tc.validator.Bytes()),
tc.baseFee,
)
if tc.expPass {
suite.Require().Equal(expBlock, block)
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestBaseFee() {
baseFee := sdk.NewInt(1)
testCases := []struct {
name string
blockRes *tmrpctypes.ResultBlockResults
registerMock func()
expBaseFee *big.Int
expPass bool
}{
{
"fail - grpc BaseFee error",
&tmrpctypes.ResultBlockResults{Height: 1},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
},
nil,
false,
},
{
"fail - grpc BaseFee error - with non feemarket block event",
&tmrpctypes.ResultBlockResults{
Height: 1,
BeginBlockEvents: []types.Event{
{
Type: evmtypes.EventTypeBlockBloom,
},
},
},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
},
nil,
false,
},
{
"fail - grpc BaseFee error - with feemarket block event",
&tmrpctypes.ResultBlockResults{
Height: 1,
BeginBlockEvents: []types.Event{
{
Type: feemarkettypes.EventTypeFeeMarket,
},
},
},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
},
nil,
false,
},
{
"fail - grpc BaseFee error - with feemarket block event with wrong attribute value",
&tmrpctypes.ResultBlockResults{
Height: 1,
BeginBlockEvents: []types.Event{
{
Type: feemarkettypes.EventTypeFeeMarket,
Attributes: []types.EventAttribute{
{Value: []byte{0x1}},
},
},
},
},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
},
nil,
false,
},
{
"fail - grpc baseFee error - with feemarket block event with baseFee attribute value",
&tmrpctypes.ResultBlockResults{
Height: 1,
BeginBlockEvents: []types.Event{
{
Type: feemarkettypes.EventTypeFeeMarket,
Attributes: []types.EventAttribute{
{Value: []byte(baseFee.String())},
},
},
},
},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeError(queryClient)
},
baseFee.BigInt(),
true,
},
{
"fail - base fee or london fork not enabled",
&tmrpctypes.ResultBlockResults{Height: 1},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFeeDisabled(queryClient)
},
nil,
true,
},
{
"pass",
&tmrpctypes.ResultBlockResults{Height: 1},
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
RegisterBaseFee(queryClient, baseFee)
},
baseFee.BigInt(),
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
baseFee, err := suite.backend.BaseFee(tc.blockRes)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expBaseFee, baseFee)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetEthereumMsgsFromTendermintBlock() {
msgEthereumTx, bz := suite.buildEthereumTx()
testCases := []struct {
name string
resBlock *tmrpctypes.ResultBlock
blockRes *tmrpctypes.ResultBlockResults
expMsgs []*evmtypes.MsgEthereumTx
}{
{
"tx in not included in block - unsuccessful tx without ExceedBlockGasLimit error",
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
TxsResults: []*types.ResponseDeliverTx{
{
Code: 1,
},
},
},
[]*evmtypes.MsgEthereumTx(nil),
},
{
"tx included in block - unsuccessful tx with ExceedBlockGasLimit error",
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
TxsResults: []*types.ResponseDeliverTx{
{
Code: 1,
Log: ExceedBlockGasLimitError,
},
},
},
[]*evmtypes.MsgEthereumTx{msgEthereumTx},
},
{
"pass",
&tmrpctypes.ResultBlock{
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
},
&tmrpctypes.ResultBlockResults{
TxsResults: []*types.ResponseDeliverTx{
{
Code: 0,
Log: ExceedBlockGasLimitError,
},
},
},
[]*evmtypes.MsgEthereumTx{msgEthereumTx},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
msgs := suite.backend.GetEthereumMsgsFromTendermintBlock(tc.resBlock, tc.blockRes)
suite.Require().Equal(tc.expMsgs, msgs)
})
}
}