Skip to content

Commit 7a7abe3

Browse files
karalabeholiman
andauthored
accounts/abi/bind: fix bounded contracts and sim backend for 1559 (ethereum#23038)
* accounts/abi/bind: fix bounded contracts and sim backend for 1559 * accounts/abi/bind, ethclient: don't rely on chain config for gas prices * all: enable London for all internal tests * les: get receipt type info in les tests * les: fix weird test Co-authored-by: Martin Holst Swende <[email protected]>
1 parent 087ed9c commit 7a7abe3

40 files changed

+449
-236
lines changed

accounts/abi/bind/backend.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ var (
3232
// have any code associated with it (i.e. suicided).
3333
ErrNoCode = errors.New("no contract code at given address")
3434

35-
// This error is raised when attempting to perform a pending state action
35+
// ErrNoPendingState is raised when attempting to perform a pending state action
3636
// on a backend that doesn't implement PendingContractCaller.
3737
ErrNoPendingState = errors.New("backend does not support pending state")
3838

39-
// This error is returned by WaitDeployed if contract creation leaves an
40-
// empty contract behind.
39+
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
40+
// an empty contract behind.
4141
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
4242
)
4343

@@ -47,7 +47,8 @@ type ContractCaller interface {
4747
// CodeAt returns the code of the given account. This is needed to differentiate
4848
// between contract internal errors and the local chain being out of sync.
4949
CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error)
50-
// ContractCall executes an Ethereum contract call with the specified data as the
50+
51+
// CallContract executes an Ethereum contract call with the specified data as the
5152
// input.
5253
CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
5354
}
@@ -58,6 +59,7 @@ type ContractCaller interface {
5859
type PendingContractCaller interface {
5960
// PendingCodeAt returns the code of the given account in the pending state.
6061
PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error)
62+
6163
// PendingCallContract executes an Ethereum contract call against the pending state.
6264
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
6365
}
@@ -67,19 +69,31 @@ type PendingContractCaller interface {
6769
// used when the user does not provide some needed values, but rather leaves it up
6870
// to the transactor to decide.
6971
type ContractTransactor interface {
72+
// HeaderByNumber returns a block header from the current canonical chain. If
73+
// number is nil, the latest known header is returned.
74+
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
75+
7076
// PendingCodeAt returns the code of the given account in the pending state.
7177
PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)
78+
7279
// PendingNonceAt retrieves the current pending nonce associated with an account.
7380
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
81+
7482
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
7583
// execution of a transaction.
7684
SuggestGasPrice(ctx context.Context) (*big.Int, error)
85+
86+
// SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow
87+
// a timely execution of a transaction.
88+
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
89+
7790
// EstimateGas tries to estimate the gas needed to execute a specific
7891
// transaction based on the current pending state of the backend blockchain.
7992
// There is no guarantee that this is the true gas limit requirement as other
8093
// transactions may be added or removed by miners, but it should provide a basis
8194
// for setting a reasonable default.
8295
EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
96+
8397
// SendTransaction injects the transaction into the pending pool for execution.
8498
SendTransaction(ctx context.Context, tx *types.Transaction) error
8599
}

accounts/abi/bind/backends/simulated.go

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error
465465
return big.NewInt(1), nil
466466
}
467467

468+
// SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated
469+
// chain doesn't have miners, we just return a gas tip of 1 for any call.
470+
func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
471+
return big.NewInt(1), nil
472+
}
473+
468474
// EstimateGas executes the requested code against the currently pending block/state and
469475
// returns the used amount of gas.
470476
func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
@@ -561,10 +567,38 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
561567
// callContract implements common code between normal and pending contract calls.
562568
// state is modified during execution, make sure to copy it if necessary.
563569
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) {
564-
// Ensure message is initialized properly.
565-
if call.GasPrice == nil {
566-
call.GasPrice = big.NewInt(1)
570+
// Gas prices post 1559 need to be initialized
571+
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
572+
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
573+
}
574+
head := b.blockchain.CurrentHeader()
575+
if !b.blockchain.Config().IsLondon(head.Number) {
576+
// If there's no basefee, then it must be a non-1559 execution
577+
if call.GasPrice == nil {
578+
call.GasPrice = new(big.Int)
579+
}
580+
call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
581+
} else {
582+
// A basefee is provided, necessitating 1559-type execution
583+
if call.GasPrice != nil {
584+
// User specified the legacy gas field, convert to 1559 gas typing
585+
call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
586+
} else {
587+
// User specified 1559 gas feilds (or none), use those
588+
if call.GasFeeCap == nil {
589+
call.GasFeeCap = new(big.Int)
590+
}
591+
if call.GasTipCap == nil {
592+
call.GasTipCap = new(big.Int)
593+
}
594+
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
595+
call.GasPrice = new(big.Int)
596+
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
597+
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
598+
}
599+
}
567600
}
601+
// Ensure message is initialized properly.
568602
if call.Gas == 0 {
569603
call.Gas = 50000000
570604
}
@@ -581,7 +615,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
581615
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
582616
// Create a new environment which holds all relevant information
583617
// about the transaction and calling mechanisms.
584-
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{})
618+
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
585619
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
586620

587621
return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()

accounts/abi/bind/backends/simulated_test.go

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ func TestSimulatedBackend(t *testing.T) {
5959
}
6060

6161
// generate a transaction and confirm you can retrieve it
62+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
63+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
64+
6265
code := `6060604052600a8060106000396000f360606040526008565b00`
6366
var gas uint64 = 3000000
64-
tx := types.NewContractCreation(0, big.NewInt(0), gas, big.NewInt(1), common.FromHex(code))
67+
tx := types.NewContractCreation(0, big.NewInt(0), gas, gasPrice, common.FromHex(code))
6568
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key)
6669

6770
err = sim.SendTransaction(context.Background(), tx)
@@ -111,14 +114,14 @@ var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
111114
func simTestBackend(testAddr common.Address) *SimulatedBackend {
112115
return NewSimulatedBackend(
113116
core.GenesisAlloc{
114-
testAddr: {Balance: big.NewInt(10000000000)},
117+
testAddr: {Balance: big.NewInt(10000000000000000)},
115118
}, 10000000,
116119
)
117120
}
118121

119122
func TestNewSimulatedBackend(t *testing.T) {
120123
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
121-
expectedBal := big.NewInt(10000000000)
124+
expectedBal := big.NewInt(10000000000000000)
122125
sim := simTestBackend(testAddr)
123126
defer sim.Close()
124127

@@ -157,8 +160,12 @@ func TestAdjustTime(t *testing.T) {
157160
func TestNewAdjustTimeFail(t *testing.T) {
158161
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
159162
sim := simTestBackend(testAddr)
163+
160164
// Create tx and send
161-
tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
165+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
166+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
167+
168+
tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
162169
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
163170
if err != nil {
164171
t.Errorf("could not sign tx: %v", err)
@@ -179,7 +186,7 @@ func TestNewAdjustTimeFail(t *testing.T) {
179186
t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime)
180187
}
181188
// Put a transaction after adjusting time
182-
tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
189+
tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
183190
signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey)
184191
if err != nil {
185192
t.Errorf("could not sign tx: %v", err)
@@ -194,7 +201,7 @@ func TestNewAdjustTimeFail(t *testing.T) {
194201

195202
func TestBalanceAt(t *testing.T) {
196203
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
197-
expectedBal := big.NewInt(10000000000)
204+
expectedBal := big.NewInt(10000000000000000)
198205
sim := simTestBackend(testAddr)
199206
defer sim.Close()
200207
bgCtx := context.Background()
@@ -282,7 +289,10 @@ func TestNonceAt(t *testing.T) {
282289
}
283290

284291
// create a signed transaction to send
285-
tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
292+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
293+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
294+
295+
tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
286296
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
287297
if err != nil {
288298
t.Errorf("could not sign tx: %v", err)
@@ -323,7 +333,10 @@ func TestSendTransaction(t *testing.T) {
323333
bgCtx := context.Background()
324334

325335
// create a signed transaction to send
326-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
336+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
337+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
338+
339+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
327340
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
328341
if err != nil {
329342
t.Errorf("could not sign tx: %v", err)
@@ -351,14 +364,17 @@ func TestTransactionByHash(t *testing.T) {
351364

352365
sim := NewSimulatedBackend(
353366
core.GenesisAlloc{
354-
testAddr: {Balance: big.NewInt(10000000000)},
367+
testAddr: {Balance: big.NewInt(10000000000000000)},
355368
}, 10000000,
356369
)
357370
defer sim.Close()
358371
bgCtx := context.Background()
359372

360373
// create a signed transaction to send
361-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
374+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
375+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
376+
377+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
362378
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
363379
if err != nil {
364380
t.Errorf("could not sign tx: %v", err)
@@ -534,16 +550,16 @@ func TestEstimateGasWithPrice(t *testing.T) {
534550
To: &recipient,
535551
Gas: 0,
536552
GasPrice: big.NewInt(0),
537-
Value: big.NewInt(1000),
553+
Value: big.NewInt(100000000000),
538554
Data: nil,
539555
}, 21000, nil},
540556

541557
{"EstimateWithPrice", ethereum.CallMsg{
542558
From: addr,
543559
To: &recipient,
544560
Gas: 0,
545-
GasPrice: big.NewInt(1000),
546-
Value: big.NewInt(1000),
561+
GasPrice: big.NewInt(100000000000),
562+
Value: big.NewInt(100000000000),
547563
Data: nil,
548564
}, 21000, nil},
549565

@@ -561,23 +577,23 @@ func TestEstimateGasWithPrice(t *testing.T) {
561577
To: &recipient,
562578
Gas: 0,
563579
GasPrice: big.NewInt(2e14), // gascost = 4.2ether
564-
Value: big.NewInt(1000),
580+
Value: big.NewInt(100000000000),
565581
Data: nil,
566582
}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
567583
}
568-
for _, c := range cases {
584+
for i, c := range cases {
569585
got, err := sim.EstimateGas(context.Background(), c.message)
570586
if c.expectError != nil {
571587
if err == nil {
572-
t.Fatalf("Expect error, got nil")
588+
t.Fatalf("test %d: expect error, got nil", i)
573589
}
574590
if c.expectError.Error() != err.Error() {
575-
t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
591+
t.Fatalf("test %d: expect error, want %v, got %v", i, c.expectError, err)
576592
}
577593
continue
578594
}
579595
if got != c.expect {
580-
t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
596+
t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
581597
}
582598
}
583599
}
@@ -669,9 +685,11 @@ func TestTransactionCount(t *testing.T) {
669685
if count != 0 {
670686
t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count)
671687
}
672-
673688
// create a signed transaction to send
674-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
689+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
690+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
691+
692+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
675693
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
676694
if err != nil {
677695
t.Errorf("could not sign tx: %v", err)
@@ -724,9 +742,11 @@ func TestTransactionInBlock(t *testing.T) {
724742
if pendingNonce != uint64(0) {
725743
t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
726744
}
727-
728745
// create a signed transaction to send
729-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
746+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
747+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
748+
749+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
730750
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
731751
if err != nil {
732752
t.Errorf("could not sign tx: %v", err)
@@ -781,7 +801,10 @@ func TestPendingNonceAt(t *testing.T) {
781801
}
782802

783803
// create a signed transaction to send
784-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
804+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
805+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
806+
807+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
785808
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
786809
if err != nil {
787810
t.Errorf("could not sign tx: %v", err)
@@ -804,7 +827,7 @@ func TestPendingNonceAt(t *testing.T) {
804827
}
805828

806829
// make a new transaction with a nonce of 1
807-
tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
830+
tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
808831
signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
809832
if err != nil {
810833
t.Errorf("could not sign tx: %v", err)
@@ -833,7 +856,10 @@ func TestTransactionReceipt(t *testing.T) {
833856
bgCtx := context.Background()
834857

835858
// create a signed transaction to send
836-
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
859+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
860+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
861+
862+
tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
837863
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
838864
if err != nil {
839865
t.Errorf("could not sign tx: %v", err)
@@ -1259,7 +1285,10 @@ func TestForkResendTx(t *testing.T) {
12591285
// 1.
12601286
parent := sim.blockchain.CurrentBlock()
12611287
// 2.
1262-
_tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
1288+
head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
1289+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
1290+
1291+
_tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
12631292
tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
12641293
sim.SendTransaction(context.Background(), tx)
12651294
sim.Commit()

0 commit comments

Comments
 (0)