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