github.com/MetalBlockchain/subnet-evm@v0.4.9/internal/ethapi/transaction_args_test.go (about)

     1  // (c) 2022, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2022 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package ethapi
    28  
    29  import (
    30  	"context"
    31  	"fmt"
    32  	"math/big"
    33  	"reflect"
    34  	"testing"
    35  
    36  	"github.com/MetalBlockchain/subnet-evm/core/types"
    37  	"github.com/MetalBlockchain/subnet-evm/params"
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/common/hexutil"
    40  )
    41  
    42  var _ feeBackend = &backendMock{}
    43  
    44  // TestSetFeeDefaults tests the logic for filling in default fee values works as expected.
    45  func TestSetFeeDefaults(t *testing.T) {
    46  	type test struct {
    47  		name     string
    48  		isLondon bool
    49  		in       *TransactionArgs
    50  		want     *TransactionArgs
    51  		err      error
    52  	}
    53  
    54  	var (
    55  		b        = newBackendMock()
    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  			false,
    66  			&TransactionArgs{},
    67  			&TransactionArgs{GasPrice: fortytwo},
    68  			nil,
    69  		},
    70  		{
    71  			"legacy tx post-London, explicit gas price",
    72  			true,
    73  			&TransactionArgs{GasPrice: fortytwo},
    74  			&TransactionArgs{GasPrice: fortytwo},
    75  			nil,
    76  		},
    77  
    78  		// Access list txs
    79  		{
    80  			"access list tx pre-London",
    81  			false,
    82  			&TransactionArgs{AccessList: al},
    83  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    84  			nil,
    85  		},
    86  		{
    87  			"access list tx post-London, explicit gas price",
    88  			false,
    89  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    90  			&TransactionArgs{AccessList: al, GasPrice: fortytwo},
    91  			nil,
    92  		},
    93  		{
    94  			"access list tx post-London",
    95  			true,
    96  			&TransactionArgs{AccessList: al},
    97  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
    98  			nil,
    99  		},
   100  		{
   101  			"access list tx post-London, only max fee",
   102  			true,
   103  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   104  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   105  			nil,
   106  		},
   107  		{
   108  			"access list tx post-London, only priority fee",
   109  			true,
   110  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
   111  			&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   112  			nil,
   113  		},
   114  
   115  		// Dynamic fee txs
   116  		{
   117  			"dynamic tx post-London",
   118  			true,
   119  			&TransactionArgs{},
   120  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   121  			nil,
   122  		},
   123  		{
   124  			"dynamic tx post-London, only max fee",
   125  			true,
   126  			&TransactionArgs{MaxFeePerGas: maxFee},
   127  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   128  			nil,
   129  		},
   130  		{
   131  			"dynamic tx post-London, only priority fee",
   132  			true,
   133  			&TransactionArgs{MaxFeePerGas: maxFee},
   134  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   135  			nil,
   136  		},
   137  		{
   138  			"dynamic fee tx pre-London, maxFee set",
   139  			false,
   140  			&TransactionArgs{MaxFeePerGas: maxFee},
   141  			nil,
   142  			fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   143  		},
   144  		{
   145  			"dynamic fee tx pre-London, priorityFee set",
   146  			false,
   147  			&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
   148  			nil,
   149  			fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
   150  		},
   151  		{
   152  			"dynamic fee tx, maxFee < priorityFee",
   153  			true,
   154  			&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
   155  			nil,
   156  			fmt.Errorf("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
   157  		},
   158  		{
   159  			"dynamic fee tx, maxFee < priorityFee while setting default",
   160  			true,
   161  			&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
   162  			nil,
   163  			fmt.Errorf("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
   164  		},
   165  
   166  		// Misc
   167  		{
   168  			"set all fee parameters",
   169  			false,
   170  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
   171  			nil,
   172  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   173  		},
   174  		{
   175  			"set gas price and maxPriorityFee",
   176  			false,
   177  			&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
   178  			nil,
   179  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   180  		},
   181  		{
   182  			"set gas price and maxFee",
   183  			true,
   184  			&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
   185  			nil,
   186  			fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
   187  		},
   188  	}
   189  
   190  	ctx := context.Background()
   191  	for i, test := range tests {
   192  		if test.isLondon {
   193  			b.activateLondon()
   194  		} else {
   195  			b.deactivateLondon()
   196  		}
   197  		got := test.in
   198  		err := got.setFeeDefaults(ctx, b)
   199  		if err != nil && err.Error() == test.err.Error() {
   200  			// Test threw expected error.
   201  			continue
   202  		} else if err != nil {
   203  			t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
   204  		}
   205  		if !reflect.DeepEqual(got, test.want) {
   206  			t.Fatalf("test %d (%s): did not fill defaults as expected: (got: %v, want: %v)", i, test.name, got, test.want)
   207  		}
   208  	}
   209  }
   210  
   211  type backendMock struct {
   212  	current *types.Header
   213  	config  *params.ChainConfig
   214  }
   215  
   216  func newBackendMock() *backendMock {
   217  	config := &params.ChainConfig{
   218  		ChainID:             big.NewInt(42),
   219  		HomesteadBlock:      big.NewInt(0),
   220  		EIP150Block:         big.NewInt(0),
   221  		EIP155Block:         big.NewInt(0),
   222  		EIP158Block:         big.NewInt(0),
   223  		ByzantiumBlock:      big.NewInt(0),
   224  		ConstantinopleBlock: big.NewInt(0),
   225  		PetersburgBlock:     big.NewInt(0),
   226  		IstanbulBlock:       big.NewInt(0),
   227  		MuirGlacierBlock:    big.NewInt(0),
   228  		NetworkUpgrades: params.NetworkUpgrades{
   229  			SubnetEVMTimestamp: big.NewInt(1000),
   230  		},
   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.Time = uint64(1100)
   248  }
   249  
   250  func (b *backendMock) deactivateLondon() {
   251  	b.current.Time = uint64(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 }