accounts/abi/bind: fix bounded contracts and sim backend for 1559 (#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 <martin@swende.se>
This commit is contained in:
Péter Szilágyi
2021-06-15 13:56:14 +03:00
committed by GitHub
parent 087ed9c92e
commit 7a7abe3de8
40 changed files with 449 additions and 236 deletions

View File

@ -49,9 +49,11 @@ type TransactOpts struct {
Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
Signer SignerFn // Method to use for signing the transaction (mandatory)
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle)
GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle)
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
@ -223,12 +225,45 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
} else {
nonce = opts.Nonce.Uint64()
}
// Figure out the gas allowance and gas price values
gasPrice := opts.GasPrice
if gasPrice == nil {
gasPrice, err = c.transactor.SuggestGasPrice(ensureContext(opts.Context))
if err != nil {
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
// Figure out reasonable gas price values
if opts.GasPrice != nil && (opts.GasFeeCap != nil || opts.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
head, err := c.transactor.HeaderByNumber(opts.Context, nil)
if err != nil {
return nil, err
}
if head.BaseFee != nil && opts.GasPrice == nil {
if opts.GasTipCap == nil {
tip, err := c.transactor.SuggestGasTipCap(opts.Context)
if err != nil {
return nil, err
}
opts.GasTipCap = tip
}
if opts.GasFeeCap == nil {
gasFeeCap := new(big.Int).Add(
opts.GasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
)
opts.GasFeeCap = gasFeeCap
}
if opts.GasFeeCap.Cmp(opts.GasTipCap) < 0 {
return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", opts.GasFeeCap, opts.GasTipCap)
}
} else {
if opts.GasFeeCap != nil || opts.GasTipCap != nil {
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
}
if opts.GasPrice == nil {
price, err := c.transactor.SuggestGasTipCap(opts.Context)
if err != nil {
return nil, err
}
if head.BaseFee != nil {
price.Add(price, head.BaseFee)
}
opts.GasPrice = price
}
}
gasLimit := opts.GasLimit
@ -242,7 +277,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
}
// If the contract surely has code (or code is not needed), estimate the transaction
msg := ethereum.CallMsg{From: opts.From, To: contract, GasPrice: gasPrice, Value: value, Data: input}
msg := ethereum.CallMsg{From: opts.From, To: contract, GasPrice: opts.GasPrice, GasTipCap: opts.GasTipCap, GasFeeCap: opts.GasFeeCap, Value: value, Data: input}
gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg)
if err != nil {
return nil, fmt.Errorf("failed to estimate gas needed: %v", err)
@ -250,10 +285,31 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
// Create the transaction, sign it and schedule it for execution
var rawTx *types.Transaction
if contract == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
if opts.GasFeeCap == nil {
baseTx := &types.LegacyTx{
Nonce: nonce,
GasPrice: opts.GasPrice,
Gas: gasLimit,
Value: value,
Data: input,
}
if contract != nil {
baseTx.To = &c.address
}
rawTx = types.NewTx(baseTx)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
baseTx := &types.DynamicFeeTx{
Nonce: nonce,
GasFeeCap: opts.GasFeeCap,
GasTipCap: opts.GasTipCap,
Gas: gasLimit,
Value: value,
Data: input,
}
if contract != nil {
baseTx.To = &c.address
}
rawTx = types.NewTx(baseTx)
}
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")