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 := ¶ms.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 }