fix: Metamask keeps failing sending transactions (#968)

* Problem: Metamask keeps failing sending transactions

Closes: #967
Solution:
- add 1/8 buffer on top of base fee for default gas price

* changelog

* fix typo

Co-authored-by: Freddy Caceres <freddy.caceres@crypto.com>
Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
yihuang 2022-03-04 04:50:40 +08:00 committed by GitHub
parent eb4631fb81
commit 40d5eff9fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 16 deletions

View File

@ -42,6 +42,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (evm) [\#529](https://github.com/tharsis/ethermint/issues/529) support return value on trace tx response. * (evm) [\#529](https://github.com/tharsis/ethermint/issues/529) support return value on trace tx response.
## Improvements
- (rpc) [#968](https://github.com/tharsis/ethermint/pull/968) Add some buffer to returned gas price to provide better default UX for client.
## [v0.10.0] - 2022-02-26 ## [v0.10.0] - 2022-02-26
### API Breaking ### API Breaking

View File

@ -50,7 +50,7 @@ type Backend interface {
RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether. RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether.
RPCMinGasPrice() int64 RPCMinGasPrice() int64
SuggestGasTipCap() (*big.Int, error) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error)
// Blockchain API // Blockchain API
BlockNumber() (hexutil.Uint64, error) BlockNumber() (hexutil.Uint64, error)
@ -954,9 +954,34 @@ func (e *EVMBackend) ChainConfig() *params.ChainConfig {
} }
// SuggestGasTipCap returns the suggested tip cap // SuggestGasTipCap returns the suggested tip cap
// always return zero since we don't support tx prioritization yet. // Although we don't support tx prioritization yet, but we return a positive value to help client to
func (e *EVMBackend) SuggestGasTipCap() (*big.Int, error) { // mitigate the base fee changes.
return big.NewInt(0), nil func (e *EVMBackend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) {
if baseFee == nil {
// london hardfork not enabled or feemarket not enabeld
return big.NewInt(0), nil
}
params, err := e.queryClient.FeeMarket.Params(e.ctx, &feemarkettypes.QueryParamsRequest{})
if err != nil {
return nil, err
}
// calculate the maximum base fee delta in current block, assuming all block gas limit is consumed
// ```
// GasTarget = GasLimit / ElasticityMultiplier
// Delta = BaseFee * (GasUsed - GasTarget) / GasTarget / Denominator
// ```
// The delta is at maximum when `GasUsed` is equal to `GasLimit`, which is:
// ```
// MaxDelta = BaseFee * (GasLimit - GasLimit / ElasticityMultiplier) / (GasLimit / ElasticityMultiplier) / Denominator
// = BaseFee * (ElasticityMultiplier - 1) / Denominator
// ```
maxDelta := baseFee.Int64() * (int64(params.Params.ElasticityMultiplier) - 1) / int64(params.Params.BaseFeeChangeDenominator)
if maxDelta < 0 {
// impossible if the parameter validation passed.
maxDelta = 0
}
return big.NewInt(maxDelta), nil
} }
// BaseFee returns the base fee tracked by the Fee Market module. If the base fee is not enabled, // BaseFee returns the base fee tracked by the Fee Market module. If the base fee is not enabled,

View File

@ -31,19 +31,16 @@ func (e *EVMBackend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Tran
return args, errors.New("latest header is nil") return args, errors.New("latest header is nil")
} }
cfg := e.ChainConfig()
// If user specifies both maxPriorityfee and maxFee, then we do not // If user specifies both maxPriorityfee and maxFee, then we do not
// need to consult the chain for defaults. It's definitely a London tx. // need to consult the chain for defaults. It's definitely a London tx.
if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil { if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
// In this clause, user left some fields unspecified. // In this clause, user left some fields unspecified.
if cfg.IsLondon(head.Number) && args.GasPrice == nil { if head.BaseFee != nil && args.GasPrice == nil {
if args.MaxPriorityFeePerGas == nil { if args.MaxPriorityFeePerGas == nil {
tip, err := e.SuggestGasTipCap() tip, err := e.SuggestGasTipCap(head.BaseFee)
if err != nil { if err != nil {
return args, err return args, err
} }
args.MaxPriorityFeePerGas = (*hexutil.Big)(tip) args.MaxPriorityFeePerGas = (*hexutil.Big)(tip)
} }
@ -65,12 +62,11 @@ func (e *EVMBackend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Tran
} }
if args.GasPrice == nil { if args.GasPrice == nil {
price, err := e.SuggestGasTipCap() price, err := e.SuggestGasTipCap(head.BaseFee)
if err != nil { if err != nil {
return args, err return args, err
} }
if head.BaseFee != nil {
if cfg.IsLondon(head.Number) {
// The legacy tx gas price suggestion should not add 2x base fee // The legacy tx gas price suggestion should not add 2x base fee
// because all fees are consumed, so it would result in a spiral // because all fees are consumed, so it would result in a spiral
// upwards. // upwards.

View File

@ -202,11 +202,10 @@ func (e *PublicAPI) GasPrice() (*hexutil.Big, error) {
err error err error
) )
if head := e.backend.CurrentHeader(); head.BaseFee != nil { if head := e.backend.CurrentHeader(); head.BaseFee != nil {
result, err = e.backend.SuggestGasTipCap() result, err = e.backend.SuggestGasTipCap(head.BaseFee)
if err != nil { if err != nil {
return nil, err return nil, err
} }
result = result.Add(result, head.BaseFee) result = result.Add(result, head.BaseFee)
} else { } else {
result = big.NewInt(e.backend.RPCMinGasPrice()) result = big.NewInt(e.backend.RPCMinGasPrice())
@ -218,11 +217,11 @@ func (e *PublicAPI) GasPrice() (*hexutil.Big, error) {
// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions.
func (e *PublicAPI) MaxPriorityFeePerGas() (*hexutil.Big, error) { func (e *PublicAPI) MaxPriorityFeePerGas() (*hexutil.Big, error) {
e.logger.Debug("eth_maxPriorityFeePerGas") e.logger.Debug("eth_maxPriorityFeePerGas")
tipcap, err := e.backend.SuggestGasTipCap() head := e.backend.CurrentHeader()
tipcap, err := e.backend.SuggestGasTipCap(head.BaseFee)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return (*hexutil.Big)(tipcap), nil return (*hexutil.Big)(tipcap), nil
} }