From 947fc1c7348dfce664e32d85071a16fcb7f50576 Mon Sep 17 00:00:00 2001 From: Maximilian Langenfeld <15726643+ezdac@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:06:35 +0200 Subject: [PATCH] Make eth_estimateGas CIP64 and CIP66 compatible --- internal/ethapi/api.go | 38 ++++++++++++++++++++++++----- internal/ethapi/transaction_args.go | 2 +- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f14efb8a16..8aefa5d138 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1344,14 +1344,35 @@ func DoEstimateGas(ctx context.Context, b CeloBackend, args TransactionArgs, blo // Recap the highest gas limit with account's available balance. if feeCap.BitLen() != 0 { - balance := state.GetBalance(*args.From) // from can't be nil + // Is given in native token when the feeCurrency is nil. + balance, err := b.GetFeeBalance(ctx, header.Hash(), *args.From, args.FeeCurrency) // from can't be nil + if err != nil { + return 0, err + } available := new(big.Int).Set(balance) - if args.Value != nil { - if args.Value.ToInt().Cmp(available) >= 0 { - return 0, core.ErrInsufficientFundsForTransfer + if args.FeeCurrency != nil { + if !args.IsFeeCurrencyDenominated() { + // CIP-66, prices are given in native token. + // We need to check the allowance in the converted feeCurrency + feeCap, err = b.ConvertToCurrency(ctx, header.Hash(), feeCap, args.FeeCurrency) + if err != nil { + return 0, err + } + } + } else { + if args.Value != nil { + if args.Value.ToInt().Cmp(available) >= 0 { + return 0, core.ErrInsufficientFundsForTransfer + } + available.Sub(available, args.Value.ToInt()) } - available.Sub(available, args.Value.ToInt()) } + + // cap the available by the maxFeeInFeeCurrency + if args.MaxFeeInFeeCurrency != nil { + available = math.BigMin(available, args.MaxFeeInFeeCurrency.ToInt()) + } + allowance := new(big.Int).Div(available, feeCap) // If the allowance is larger than maximum uint64, skip checking @@ -1360,8 +1381,13 @@ func DoEstimateGas(ctx context.Context, b CeloBackend, args TransactionArgs, blo if transfer == nil { transfer = new(hexutil.Big) } + maxFeeInFeeCurrency := args.MaxFeeInFeeCurrency + if maxFeeInFeeCurrency == nil { + maxFeeInFeeCurrency = new(hexutil.Big) + } log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, - "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance) + "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance, + "feeCurrency", args.FeeCurrency, "maxFeeInFeeCurrency", maxFeeInFeeCurrency.ToInt()) hi = allowance.Uint64() } } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 7b2a0dc582..3e4e0b6bb2 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -349,7 +349,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, ex var err error baseFee, err = exchange.ConvertGoldToCurrency(exchangeRates, args.FeeCurrency, baseFee) if err != nil { - return nil, err + return nil, fmt.Errorf("can't convert base-fee to fee-currency: %w", err) } } gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)