mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
140 lines
3.4 KiB
Go
140 lines
3.4 KiB
Go
// (c) 2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package ethapi
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/luxfi/evm/upgrade/etna"
|
|
"github.com/luxfi/geth/common/hexutil"
|
|
)
|
|
|
|
const (
|
|
minGasTip = 1 // 1 wei
|
|
feeDenominator = 100
|
|
)
|
|
|
|
var (
|
|
bigMinGasTip = big.NewInt(minGasTip)
|
|
bigFeeDenominator = big.NewInt(feeDenominator)
|
|
)
|
|
|
|
type PriceOptionConfig struct {
|
|
SlowFeePercentage uint64
|
|
FastFeePercentage uint64
|
|
MaxBaseFee uint64
|
|
MaxTip uint64
|
|
}
|
|
|
|
type Price struct {
|
|
GasTip *hexutil.Big `json:"maxPriorityFeePerGas"`
|
|
GasFee *hexutil.Big `json:"maxFeePerGas"`
|
|
}
|
|
|
|
type PriceOptions struct {
|
|
Slow *Price `json:"slow"`
|
|
Normal *Price `json:"normal"`
|
|
Fast *Price `json:"fast"`
|
|
}
|
|
|
|
// TODO: This can be moved to LUX/custom API
|
|
|
|
// SuggestPriceOptions returns suggestions for what to display to a user for
|
|
// current transaction fees.
|
|
func (s *EthereumAPI) SuggestPriceOptions(ctx context.Context) (*PriceOptions, error) {
|
|
baseFee, err := s.b.EstimateBaseFee(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to estimate base fee: %w", err)
|
|
}
|
|
gasTip, err := s.b.SuggestGasTipCap(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to suggest gas tip cap: %w", err)
|
|
}
|
|
|
|
// If the chain isn't running with dynamic fees, return nil.
|
|
if baseFee == nil || gasTip == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
// TODO: Simplified min base fee logic post-Fortuna activation
|
|
minBaseFee := new(big.Int).SetUint64(etna.MinBaseFee)
|
|
|
|
cfg := s.b.PriceOptionsConfig()
|
|
bigSlowFeePercent := new(big.Int).SetUint64(cfg.SlowFeePercentage)
|
|
bigFastFeePercent := new(big.Int).SetUint64(cfg.FastFeePercentage)
|
|
|
|
baseFees := calculateFeeSpeeds(
|
|
minBaseFee,
|
|
baseFee,
|
|
big.NewInt(int64(cfg.MaxBaseFee)),
|
|
bigSlowFeePercent,
|
|
bigFastFeePercent,
|
|
)
|
|
gasTips := calculateFeeSpeeds(
|
|
bigMinGasTip,
|
|
gasTip,
|
|
big.NewInt(int64(cfg.MaxTip)),
|
|
bigSlowFeePercent,
|
|
bigFastFeePercent,
|
|
)
|
|
slowGasFee := new(big.Int).Add(baseFees.slow, gasTips.slow)
|
|
normalGasFee := new(big.Int).Add(baseFees.normal, gasTips.normal)
|
|
fastGasFee := new(big.Int).Add(baseFees.fast, gasTips.fast)
|
|
return &PriceOptions{
|
|
Slow: &Price{
|
|
GasTip: (*hexutil.Big)(gasTips.slow),
|
|
GasFee: (*hexutil.Big)(slowGasFee),
|
|
},
|
|
Normal: &Price{
|
|
GasTip: (*hexutil.Big)(gasTips.normal),
|
|
GasFee: (*hexutil.Big)(normalGasFee),
|
|
},
|
|
Fast: &Price{
|
|
GasTip: (*hexutil.Big)(gasTips.fast),
|
|
GasFee: (*hexutil.Big)(fastGasFee),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
type feeSpeeds struct {
|
|
slow *big.Int
|
|
normal *big.Int
|
|
fast *big.Int
|
|
}
|
|
|
|
// calculateFeeSpeeds returns the slow, normal, and fast price options for a
|
|
// given min, estimate, and max,
|
|
//
|
|
// slow = max(slowFeePerc/100 * min(estimate, maxFee), minFee)
|
|
// normal = min(estimate, maxFee)
|
|
// fast = fastFeePerc/100 * estimate
|
|
func calculateFeeSpeeds(
|
|
minFee *big.Int,
|
|
estimate *big.Int,
|
|
maxFee *big.Int,
|
|
slowFeePerc *big.Int,
|
|
fastFeePerc *big.Int,
|
|
) feeSpeeds {
|
|
// Cap the fee to keep slow and normal options reasonable during fee spikes.
|
|
cappedFee := BigMin(estimate, maxFee)
|
|
|
|
slowFee := new(big.Int).Set(cappedFee)
|
|
slowFee.Mul(slowFee, slowFeePerc)
|
|
slowFee.Div(slowFee, bigFeeDenominator)
|
|
slowFee = BigMax(slowFee, minFee)
|
|
|
|
normalFee := cappedFee
|
|
|
|
fastFee := new(big.Int).Set(estimate)
|
|
fastFee.Mul(fastFee, fastFeePerc)
|
|
fastFee.Div(fastFee, bigFeeDenominator)
|
|
return feeSpeeds{
|
|
slow: slowFee,
|
|
normal: normalFee,
|
|
fast: fastFee,
|
|
}
|
|
}
|