github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/internal/ethapi/transaction_args_test.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package ethapi
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"math/big"
    23  	"reflect"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/tirogen/go-ethereum"
    28  	"github.com/tirogen/go-ethereum/accounts"
    29  	"github.com/tirogen/go-ethereum/common"
    30  	"github.com/tirogen/go-ethereum/common/hexutil"
    31  	"github.com/tirogen/go-ethereum/consensus"
    32  	"github.com/tirogen/go-ethereum/core"
    33  	"github.com/tirogen/go-ethereum/core/bloombits"
    34  	"github.com/tirogen/go-ethereum/core/state"
    35  	"github.com/tirogen/go-ethereum/core/types"
    36  	"github.com/tirogen/go-ethereum/core/vm"
    37  	"github.com/tirogen/go-ethereum/ethdb"
    38  	"github.com/tirogen/go-ethereum/event"
    39  	"github.com/tirogen/go-ethereum/params"
    40  	"github.com/tirogen/go-ethereum/rpc"
    41  )
    42  
    43  // TestSetFeeDefaults tests the logic for filling in default fee values works as expected.
    44  func TestSetFeeDefaults(t *testing.T) {
    45  	type test struct {
    46  		name     string
    47  		isLondon bool
    48  		in       *TransactionArgs
    49  		want     *TransactionArgs
    50  		err      error
    51  	}
    52  
    53  	var (
    54  		b        = newBackendMock()
    55  		fortytwo = (*hexutil.Big)(big.NewInt(42))
    56  		maxFee   = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
    57  		al       = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
    58  	)
    59  
    60  	tests := []test{
    61  		// Legacy txs
    62  		{
    63  			"legacy tx pre-London",
    64  			false,
    65  			&TransactionArgs{},
    66  			&TransactionArgs{GasPrice: fortytwo},
    67  			nil,
    68  		},
    69  		{
    70  			"legacy tx post-London, explicit gas price",
    71  			true,
    72  			&TransactionArgs{GasPrice: fortytwo},
    73  			&TransactionArgs{GasPrice: fortytwo},
    74  			nil,
    75  		},
    76  
    77  		// Access list txs
    78  		{
    79  			"access list tx pre-London",
    80  			false,
    81  			&TransactionArgs{AccessList: al},
    82  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    83  			nil,
    84  		},
    85  		{
    86  			"access list tx post-London, explicit gas price",
    87  			false,
    88  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    89  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    90  			nil,
    91  		},
    92  		{
    93  			"access list tx post-London",
    94  			true,
    95  			&TransactionArgs{AccessList: al},
    96  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
    97  			nil,
    98  		},
    99  		{
   100  			"access list tx post-London, only max fee",
   101  			true,
   102  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   103  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   104  			nil,
   105  		},
   106  		{
   107  			"access list tx post-London, only priority fee",
   108  			true,
   109  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   110  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   111  			nil,
   112  		},
   113  
   114  		// Dynamic fee txs
   115  		{
   116  			"dynamic tx post-London",
   117  			true,
   118  			&TransactionArgs{},
   119  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   120  			nil,
   121  		},
   122  		{
   123  			"dynamic tx post-London, only max fee",
   124  			true,
   125  			&TransactionArgs{MaxFeePerGas: maxFee},
   126  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   127  			nil,
   128  		},
   129  		{
   130  			"dynamic tx post-London, only priority fee",
   131  			true,
   132  			&TransactionArgs{MaxFeePerGas: maxFee},
   133  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   134  			nil,
   135  		},
   136  		{
   137  			"dynamic fee tx pre-London, maxFee set",
   138  			false,
   139  			&TransactionArgs{MaxFeePerGas: maxFee},
   140  			nil,
   141  			fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   142  		},
   143  		{
   144  			"dynamic fee tx pre-London, priorityFee set",
   145  			false,
   146  			&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
   147  			nil,
   148  			fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   149  		},
   150  		{
   151  			"dynamic fee tx, maxFee < priorityFee",
   152  			true,
   153  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
   154  			nil,
   155  			fmt.Errorf("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
   156  		},
   157  		{
   158  			"dynamic fee tx, maxFee < priorityFee while setting default",
   159  			true,
   160  			&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
   161  			nil,
   162  			fmt.Errorf("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
   163  		},
   164  
   165  		// Misc
   166  		{
   167  			"set all fee parameters",
   168  			false,
   169  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   170  			nil,
   171  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   172  		},
   173  		{
   174  			"set gas price and maxPriorityFee",
   175  			false,
   176  			&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
   177  			nil,
   178  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   179  		},
   180  		{
   181  			"set gas price and maxFee",
   182  			true,
   183  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
   184  			nil,
   185  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   186  		},
   187  	}
   188  
   189  	ctx := context.Background()
   190  	for i, test := range tests {
   191  		if test.isLondon {
   192  			b.activateLondon()
   193  		} else {
   194  			b.deactivateLondon()
   195  		}
   196  		got := test.in
   197  		err := got.setFeeDefaults(ctx, b)
   198  		if err != nil && err.Error() == test.err.Error() {
   199  			// Test threw expected error.
   200  			continue
   201  		} else if err != nil {
   202  			t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
   203  		}
   204  		if !reflect.DeepEqual(got, test.want) {
   205  			t.Fatalf("test %d (%s): did not fill defaults as expected: (got: %v, want: %v)", i, test.name, got, test.want)
   206  		}
   207  	}
   208  }
   209  
   210  type backendMock struct {
   211  	current *types.Header
   212  	config  *params.ChainConfig
   213  }
   214  
   215  func newBackendMock() *backendMock {
   216  	config := &params.ChainConfig{
   217  		ChainID:             big.NewInt(42),
   218  		HomesteadBlock:      big.NewInt(0),
   219  		DAOForkBlock:        nil,
   220  		DAOForkSupport:      true,
   221  		EIP150Block:         big.NewInt(0),
   222  		EIP155Block:         big.NewInt(0),
   223  		EIP158Block:         big.NewInt(0),
   224  		ByzantiumBlock:      big.NewInt(0),
   225  		ConstantinopleBlock: big.NewInt(0),
   226  		PetersburgBlock:     big.NewInt(0),
   227  		IstanbulBlock:       big.NewInt(0),
   228  		MuirGlacierBlock:    big.NewInt(0),
   229  		BerlinBlock:         big.NewInt(0),
   230  		LondonBlock:         big.NewInt(1000),
   231  	}
   232  	return &backendMock{
   233  		current: &types.Header{
   234  			Difficulty: big.NewInt(10000000000),
   235  			Number:     big.NewInt(1100),
   236  			GasLimit:   8_000_000,
   237  			GasUsed:    8_000_000,
   238  			Time:       555,
   239  			Extra:      make([]byte, 32),
   240  			BaseFee:    big.NewInt(10),
   241  		},
   242  		config: config,
   243  	}
   244  }
   245  
   246  func (b *backendMock) activateLondon() {
   247  	b.current.Number = big.NewInt(1100)
   248  }
   249  
   250  func (b *backendMock) deactivateLondon() {
   251  	b.current.Number = big.NewInt(900)
   252  }
   253  func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   254  	return big.NewInt(42), nil
   255  }
   256  func (b *backendMock) CurrentHeader() *types.Header     { return b.current }
   257  func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
   258  
   259  // Other methods needed to implement Backend interface.
   260  func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
   261  func (b *backendMock) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
   262  	return nil, nil, nil, nil, nil
   263  }
   264  func (b *backendMock) ChainDb() ethdb.Database           { return nil }
   265  func (b *backendMock) AccountManager() *accounts.Manager { return nil }
   266  func (b *backendMock) ExtRPCEnabled() bool               { return false }
   267  func (b *backendMock) RPCGasCap() uint64                 { return 0 }
   268  func (b *backendMock) RPCEVMTimeout() time.Duration      { return time.Second }
   269  func (b *backendMock) RPCTxFeeCap() float64              { return 0 }
   270  func (b *backendMock) UnprotectedAllowed() bool          { return false }
   271  func (b *backendMock) SetHead(number uint64)             {}
   272  func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
   273  	return nil, nil
   274  }
   275  func (b *backendMock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   276  	return nil, nil
   277  }
   278  func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
   279  	return nil, nil
   280  }
   281  func (b *backendMock) CurrentBlock() *types.Block { return nil }
   282  func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   283  	return nil, nil
   284  }
   285  func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   286  	return nil, nil
   287  }
   288  func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   289  	return nil, nil
   290  }
   291  func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
   292  	return nil, nil, nil
   293  }
   294  func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
   295  	return nil, nil, nil
   296  }
   297  func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil }
   298  func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
   299  	return nil, nil
   300  }
   301  func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
   302  	return nil, nil
   303  }
   304  func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
   305  func (b *backendMock) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
   306  	return nil, nil, nil
   307  }
   308  func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
   309  func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
   310  	return nil
   311  }
   312  func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
   313  	return nil
   314  }
   315  func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
   316  func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
   317  	return nil, [32]byte{}, 0, 0, nil
   318  }
   319  func (b *backendMock) GetPoolTransactions() (types.Transactions, error)         { return nil, nil }
   320  func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
   321  func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
   322  	return 0, nil
   323  }
   324  func (b *backendMock) Stats() (pending int, queued int) { return 0, 0 }
   325  func (b *backendMock) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
   326  	return nil, nil
   327  }
   328  func (b *backendMock) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
   329  	return nil, nil
   330  }
   331  func (b *backendMock) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription      { return nil }
   332  func (b *backendMock) BloomStatus() (uint64, uint64)                                        { return 0, 0 }
   333  func (b *backendMock) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {}
   334  func (b *backendMock) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription         { return nil }
   335  func (b *backendMock) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
   336  	return nil
   337  }
   338  func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   339  	return nil
   340  }
   341  
   342  func (b *backendMock) Engine() consensus.Engine { return nil }