github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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  	"errors"
    22  	"math/big"
    23  	"reflect"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum"
    28  	"github.com/ethereum/go-ethereum/accounts"
    29  	"github.com/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/common/hexutil"
    31  	"github.com/ethereum/go-ethereum/consensus"
    32  	"github.com/ethereum/go-ethereum/core"
    33  	"github.com/ethereum/go-ethereum/core/bloombits"
    34  	"github.com/ethereum/go-ethereum/core/state"
    35  	"github.com/ethereum/go-ethereum/core/types"
    36  	"github.com/ethereum/go-ethereum/core/vm"
    37  	"github.com/ethereum/go-ethereum/ethdb"
    38  	"github.com/ethereum/go-ethereum/event"
    39  	"github.com/ethereum/go-ethereum/params"
    40  	"github.com/ethereum/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  		fork string // options: legacy, london, cancun
    48  		in   *TransactionArgs
    49  		want *TransactionArgs
    50  		err  error
    51  	}
    52  
    53  	var (
    54  		b        = newBackendMock()
    55  		zero     = (*hexutil.Big)(big.NewInt(0))
    56  		fortytwo = (*hexutil.Big)(big.NewInt(42))
    57  		maxFee   = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
    58  		al       = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
    59  	)
    60  
    61  	tests := []test{
    62  		// Legacy txs
    63  		{
    64  			"legacy tx pre-London",
    65  			"legacy",
    66  			&TransactionArgs{},
    67  			&TransactionArgs{GasPrice: fortytwo},
    68  			nil,
    69  		},
    70  		{
    71  			"legacy tx pre-London with zero price",
    72  			"legacy",
    73  			&TransactionArgs{GasPrice: zero},
    74  			&TransactionArgs{GasPrice: zero},
    75  			nil,
    76  		},
    77  		{
    78  			"legacy tx post-London, explicit gas price",
    79  			"london",
    80  			&TransactionArgs{GasPrice: fortytwo},
    81  			&TransactionArgs{GasPrice: fortytwo},
    82  			nil,
    83  		},
    84  		{
    85  			"legacy tx post-London with zero price",
    86  			"london",
    87  			&TransactionArgs{GasPrice: zero},
    88  			nil,
    89  			errors.New("gasPrice must be non-zero after london fork"),
    90  		},
    91  
    92  		// Access list txs
    93  		{
    94  			"access list tx pre-London",
    95  			"legacy",
    96  			&TransactionArgs{AccessList: al},
    97  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    98  			nil,
    99  		},
   100  		{
   101  			"access list tx post-London, explicit gas price",
   102  			"legacy",
   103  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
   104  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
   105  			nil,
   106  		},
   107  		{
   108  			"access list tx post-London",
   109  			"london",
   110  			&TransactionArgs{AccessList: al},
   111  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   112  			nil,
   113  		},
   114  		{
   115  			"access list tx post-London, only max fee",
   116  			"london",
   117  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   118  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   119  			nil,
   120  		},
   121  		{
   122  			"access list tx post-London, only priority fee",
   123  			"london",
   124  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   125  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   126  			nil,
   127  		},
   128  
   129  		// Dynamic fee txs
   130  		{
   131  			"dynamic tx post-London",
   132  			"london",
   133  			&TransactionArgs{},
   134  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   135  			nil,
   136  		},
   137  		{
   138  			"dynamic tx post-London, only max fee",
   139  			"london",
   140  			&TransactionArgs{MaxFeePerGas: maxFee},
   141  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   142  			nil,
   143  		},
   144  		{
   145  			"dynamic tx post-London, only priority fee",
   146  			"london",
   147  			&TransactionArgs{MaxFeePerGas: maxFee},
   148  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   149  			nil,
   150  		},
   151  		{
   152  			"dynamic fee tx pre-London, maxFee set",
   153  			"legacy",
   154  			&TransactionArgs{MaxFeePerGas: maxFee},
   155  			nil,
   156  			errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   157  		},
   158  		{
   159  			"dynamic fee tx pre-London, priorityFee set",
   160  			"legacy",
   161  			&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
   162  			nil,
   163  			errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   164  		},
   165  		{
   166  			"dynamic fee tx, maxFee < priorityFee",
   167  			"london",
   168  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
   169  			nil,
   170  			errors.New("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
   171  		},
   172  		{
   173  			"dynamic fee tx, maxFee < priorityFee while setting default",
   174  			"london",
   175  			&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
   176  			nil,
   177  			errors.New("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
   178  		},
   179  		{
   180  			"dynamic fee tx post-London, explicit gas price",
   181  			"london",
   182  			&TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
   183  			nil,
   184  			errors.New("maxFeePerGas must be non-zero"),
   185  		},
   186  
   187  		// Misc
   188  		{
   189  			"set all fee parameters",
   190  			"legacy",
   191  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   192  			nil,
   193  			errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   194  		},
   195  		{
   196  			"set gas price and maxPriorityFee",
   197  			"legacy",
   198  			&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
   199  			nil,
   200  			errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   201  		},
   202  		{
   203  			"set gas price and maxFee",
   204  			"london",
   205  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
   206  			nil,
   207  			errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   208  		},
   209  		// EIP-4844
   210  		{
   211  			"set gas price and maxFee for blob transaction",
   212  			"cancun",
   213  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, BlobHashes: []common.Hash{}},
   214  			nil,
   215  			errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   216  		},
   217  		{
   218  			"fill maxFeePerBlobGas",
   219  			"cancun",
   220  			&TransactionArgs{BlobHashes: []common.Hash{}},
   221  			&TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   222  			nil,
   223  		},
   224  		{
   225  			"fill maxFeePerBlobGas when dynamic fees are set",
   226  			"cancun",
   227  			&TransactionArgs{BlobHashes: []common.Hash{}, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   228  			&TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   229  			nil,
   230  		},
   231  	}
   232  
   233  	ctx := context.Background()
   234  	for i, test := range tests {
   235  		if err := b.setFork(test.fork); err != nil {
   236  			t.Fatalf("failed to set fork: %v", err)
   237  		}
   238  		got := test.in
   239  		err := got.setFeeDefaults(ctx, b)
   240  		if err != nil {
   241  			if test.err == nil {
   242  				t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
   243  			} else if err.Error() != test.err.Error() {
   244  				t.Fatalf("test %d (%s): unexpected error: (got: %s, want: %s)", i, test.name, err, test.err)
   245  			}
   246  			// Matching error.
   247  			continue
   248  		} else if test.err != nil {
   249  			t.Fatalf("test %d (%s): expected error: %s", i, test.name, test.err)
   250  		}
   251  		if !reflect.DeepEqual(got, test.want) {
   252  			t.Fatalf("test %d (%s): did not fill defaults as expected: (got: %v, want: %v)", i, test.name, got, test.want)
   253  		}
   254  	}
   255  }
   256  
   257  type backendMock struct {
   258  	current *types.Header
   259  	config  *params.ChainConfig
   260  }
   261  
   262  func newBackendMock() *backendMock {
   263  	var cancunTime uint64 = 600
   264  	config := &params.ChainConfig{
   265  		ChainID:             big.NewInt(42),
   266  		HomesteadBlock:      big.NewInt(0),
   267  		DAOForkBlock:        nil,
   268  		DAOForkSupport:      true,
   269  		EIP150Block:         big.NewInt(0),
   270  		EIP155Block:         big.NewInt(0),
   271  		EIP158Block:         big.NewInt(0),
   272  		ByzantiumBlock:      big.NewInt(0),
   273  		ConstantinopleBlock: big.NewInt(0),
   274  		PetersburgBlock:     big.NewInt(0),
   275  		IstanbulBlock:       big.NewInt(0),
   276  		MuirGlacierBlock:    big.NewInt(0),
   277  		BerlinBlock:         big.NewInt(0),
   278  		LondonBlock:         big.NewInt(1000),
   279  		CancunTime:          &cancunTime,
   280  	}
   281  	return &backendMock{
   282  		current: &types.Header{
   283  			Difficulty: big.NewInt(10000000000),
   284  			Number:     big.NewInt(1100),
   285  			GasLimit:   8_000_000,
   286  			GasUsed:    8_000_000,
   287  			Time:       555,
   288  			Extra:      make([]byte, 32),
   289  			BaseFee:    big.NewInt(10),
   290  		},
   291  		config: config,
   292  	}
   293  }
   294  
   295  func (b *backendMock) setFork(fork string) error {
   296  	if fork == "legacy" {
   297  		b.current.Number = big.NewInt(900)
   298  		b.current.Time = 555
   299  	} else if fork == "london" {
   300  		b.current.Number = big.NewInt(1100)
   301  		b.current.Time = 555
   302  	} else if fork == "cancun" {
   303  		b.current.Number = big.NewInt(1100)
   304  		b.current.Time = 700
   305  		// Blob base fee will be 2
   306  		excess := uint64(2314058)
   307  		b.current.ExcessBlobGas = &excess
   308  	} else {
   309  		return errors.New("invalid fork")
   310  	}
   311  	return nil
   312  }
   313  
   314  func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   315  	return big.NewInt(42), nil
   316  }
   317  func (b *backendMock) BlobBaseFee(ctx context.Context) *big.Int { return big.NewInt(42) }
   318  
   319  func (b *backendMock) CurrentHeader() *types.Header     { return b.current }
   320  func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
   321  
   322  // Other methods needed to implement Backend interface.
   323  func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
   324  func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
   325  	return nil, nil, nil, nil, nil, nil, nil
   326  }
   327  func (b *backendMock) ChainDb() ethdb.Database           { return nil }
   328  func (b *backendMock) AccountManager() *accounts.Manager { return nil }
   329  func (b *backendMock) ExtRPCEnabled() bool               { return false }
   330  func (b *backendMock) RPCGasCap() uint64                 { return 0 }
   331  func (b *backendMock) RPCEVMTimeout() time.Duration      { return time.Second }
   332  func (b *backendMock) RPCTxFeeCap() float64              { return 0 }
   333  func (b *backendMock) UnprotectedAllowed() bool          { return false }
   334  func (b *backendMock) SetHead(number uint64)             {}
   335  func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
   336  	return nil, nil
   337  }
   338  func (b *backendMock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   339  	return nil, nil
   340  }
   341  func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
   342  	return nil, nil
   343  }
   344  func (b *backendMock) CurrentBlock() *types.Header { return nil }
   345  func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   346  	return nil, nil
   347  }
   348  func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   349  	return nil, nil
   350  }
   351  func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   352  	return nil, nil
   353  }
   354  func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
   355  	return nil, nil
   356  }
   357  func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
   358  	return nil, nil, nil
   359  }
   360  func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
   361  	return nil, nil, nil
   362  }
   363  func (b *backendMock) Pending() (*types.Block, types.Receipts, *state.StateDB) { return nil, nil, nil }
   364  func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
   365  	return nil, nil
   366  }
   367  func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
   368  	return nil, nil
   369  }
   370  func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
   371  func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
   372  	return nil
   373  }
   374  func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
   375  func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
   376  	return nil
   377  }
   378  func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
   379  	return nil
   380  }
   381  func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
   382  func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
   383  	return false, nil, [32]byte{}, 0, 0, nil
   384  }
   385  func (b *backendMock) GetPoolTransactions() (types.Transactions, error)         { return nil, nil }
   386  func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
   387  func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
   388  	return 0, nil
   389  }
   390  func (b *backendMock) Stats() (pending int, queued int) { return 0, 0 }
   391  func (b *backendMock) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
   392  	return nil, nil
   393  }
   394  func (b *backendMock) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) {
   395  	return nil, nil
   396  }
   397  func (b *backendMock) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription      { return nil }
   398  func (b *backendMock) BloomStatus() (uint64, uint64)                                        { return 0, 0 }
   399  func (b *backendMock) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {}
   400  func (b *backendMock) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription         { return nil }
   401  func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   402  	return nil
   403  }
   404  
   405  func (b *backendMock) Engine() consensus.Engine { return nil }