Skip to content

Commit a879c42

Browse files
internal/ethapi, accounts/abi/bind: cap highest gas limit by account balance for 1559 fee parameters (#23309)
* internal/ethapi/api: cap highest gas limit by account balance for 1559 fee parameters * accounts/abi/bind: port gas limit cap for 1559 parameters to simulated backend * accounts/abi/bind: add test for 1559 gas estimates for the simulated backend * internal/ethapi/api: fix comment * accounts/abi/bind/backends, internal/ethapi: unify naming style Co-authored-by: Péter Szilágyi <[email protected]>
1 parent 39fe7ec commit a879c42

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,19 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
488488
} else {
489489
hi = b.pendingBlock.GasLimit()
490490
}
491+
// Normalize the max fee per gas the call is willing to spend.
492+
var feeCap *big.Int
493+
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
494+
return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
495+
} else if call.GasPrice != nil {
496+
feeCap = call.GasPrice
497+
} else if call.GasFeeCap != nil {
498+
feeCap = call.GasFeeCap
499+
} else {
500+
feeCap = common.Big0
501+
}
491502
// Recap the highest gas allowance with account's balance.
492-
if call.GasPrice != nil && call.GasPrice.BitLen() != 0 {
503+
if feeCap.BitLen() != 0 {
493504
balance := b.pendingState.GetBalance(call.From) // from can't be nil
494505
available := new(big.Int).Set(balance)
495506
if call.Value != nil {
@@ -498,14 +509,14 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
498509
}
499510
available.Sub(available, call.Value)
500511
}
501-
allowance := new(big.Int).Div(available, call.GasPrice)
512+
allowance := new(big.Int).Div(available, feeCap)
502513
if allowance.IsUint64() && hi > allowance.Uint64() {
503514
transfer := call.Value
504515
if transfer == nil {
505516
transfer = new(big.Int)
506517
}
507518
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
508-
"sent", transfer, "gasprice", call.GasPrice, "fundable", allowance)
519+
"sent", transfer, "feecap", feeCap, "fundable", allowance)
509520
hi = allowance.Uint64()
510521
}
511522
}

accounts/abi/bind/backends/simulated_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,26 @@ func TestEstimateGasWithPrice(t *testing.T) {
580580
Value: big.NewInt(100000000000),
581581
Data: nil,
582582
}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
583+
584+
{"EstimateEIP1559WithHighFees", ethereum.CallMsg{
585+
From: addr,
586+
To: &addr,
587+
Gas: 0,
588+
GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
589+
GasTipCap: big.NewInt(1),
590+
Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
591+
Data: nil,
592+
}, params.TxGas, nil},
593+
594+
{"EstimateEIP1559WithSuperHighFees", ethereum.CallMsg{
595+
From: addr,
596+
To: &addr,
597+
Gas: 0,
598+
GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
599+
GasTipCap: big.NewInt(1),
600+
Value: big.NewInt(1e17 + 1), // the remaining balance for fee is 2.1ether
601+
Data: nil,
602+
}, params.TxGas, errors.New("gas required exceeds allowance (20999)")}, // 20999=(2.2ether-0.1ether-1wei)/(1e14)
583603
}
584604
for i, c := range cases {
585605
got, err := sim.EstimateGas(context.Background(), c.message)
@@ -592,6 +612,9 @@ func TestEstimateGasWithPrice(t *testing.T) {
592612
}
593613
continue
594614
}
615+
if c.expectError == nil && err != nil {
616+
t.Fatalf("test %d: didn't expect error, got %v", i, err)
617+
}
595618
if got != c.expect {
596619
t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
597620
}

internal/ethapi/api.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args Transactio
477477
if args.Nonce == nil {
478478
return nil, fmt.Errorf("nonce not specified")
479479
}
480-
// Before actually sign the transaction, ensure the transaction fee is reasonable.
480+
// Before actually signing the transaction, ensure the transaction fee is reasonable.
481481
tx := args.toTransaction()
482482
if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
483483
return nil, err
@@ -1008,8 +1008,19 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
10081008
}
10091009
hi = block.GasLimit()
10101010
}
1011+
// Normalize the max fee per gas the call is willing to spend.
1012+
var feeCap *big.Int
1013+
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
1014+
return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
1015+
} else if args.GasPrice != nil {
1016+
feeCap = args.GasPrice.ToInt()
1017+
} else if args.MaxFeePerGas != nil {
1018+
feeCap = args.MaxFeePerGas.ToInt()
1019+
} else {
1020+
feeCap = common.Big0
1021+
}
10111022
// Recap the highest gas limit with account's available balance.
1012-
if args.GasPrice != nil && args.GasPrice.ToInt().BitLen() != 0 {
1023+
if feeCap.BitLen() != 0 {
10131024
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
10141025
if err != nil {
10151026
return 0, err
@@ -1022,7 +1033,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
10221033
}
10231034
available.Sub(available, args.Value.ToInt())
10241035
}
1025-
allowance := new(big.Int).Div(available, args.GasPrice.ToInt())
1036+
allowance := new(big.Int).Div(available, feeCap)
10261037

10271038
// If the allowance is larger than maximum uint64, skip checking
10281039
if allowance.IsUint64() && hi > allowance.Uint64() {
@@ -1031,7 +1042,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
10311042
transfer = new(hexutil.Big)
10321043
}
10331044
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
1034-
"sent", transfer.ToInt(), "gasprice", args.GasPrice.ToInt(), "fundable", allowance)
1045+
"sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance)
10351046
hi = allowance.Uint64()
10361047
}
10371048
}

0 commit comments

Comments
 (0)