diff --git a/pkg/fee/models.go b/pkg/fee/models.go deleted file mode 100644 index f3092e113..000000000 --- a/pkg/fee/models.go +++ /dev/null @@ -1,85 +0,0 @@ -package fee - -import ( - "errors" - "fmt" - "math/big" - - "github.com/smartcontractkit/chainlink-common/pkg/chains/label" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" -) - -var ( - ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit") - ErrBump = errors.New("fee bump failed") - ErrConnectivity = errors.New("transaction propagation issue: transactions are not being mined") -) - -func IsBumpErr(err error) bool { - return err != nil && (errors.Is(err, ErrBumpFeeExceedsLimit) || errors.Is(err, ErrBump) || errors.Is(err, ErrConnectivity)) -} - -// CalculateFee computes the fee price for a transaction. -// The fee price is the minimum of: -// - max fee price specified, default fee price and max fee price for the node. -func CalculateFee( - maxFeePrice, defaultPrice, maxFeePriceConfigured *big.Int, -) *big.Int { - maxFeePriceAllowed := bigmath.Min(maxFeePrice, maxFeePriceConfigured) - return bigmath.Min(defaultPrice, maxFeePriceAllowed) -} - -// CalculateBumpedFee computes the next fee price to attempt as the largest of: -// - A configured percentage bump (bumpPercent) on top of the baseline price. -// - A configured fixed amount of Unit (bumpMin) on top of the baseline price. -// The baseline price is the maximum of the previous fee price attempt and the node's current fee price. -func CalculateBumpedFee( - lggr logger.SugaredLogger, - currentfeePrice, originalfeePrice, maxFeePriceInput, maxBumpPrice, bumpMin *big.Int, - bumpPercent uint16, - toChainUnit feeUnitToChainUnit, -) (*big.Int, error) { - maxFeePrice := bigmath.Min(maxFeePriceInput, maxBumpPrice) - bumpedFeePrice := maxBumpedFee(originalfeePrice, bumpPercent, bumpMin) - - // Update bumpedFeePrice if currentfeePrice is higher than bumpedFeePrice and within maxFeePrice - bumpedFeePrice = maxFee(lggr, currentfeePrice, bumpedFeePrice, maxFeePrice, "fee price", toChainUnit) - - if bumpedFeePrice.Cmp(maxFeePrice) > 0 { - return maxFeePrice, fmt.Errorf("bumped fee price of %s would exceed configured max fee price of %s (original price was %s). %s: %w", - toChainUnit(bumpedFeePrice), toChainUnit(maxFeePrice), toChainUnit(originalfeePrice), label.NodeConnectivityProblemWarning, ErrBumpFeeExceedsLimit) - } else if bumpedFeePrice.Cmp(originalfeePrice) == 0 { - // NOTE: This really shouldn't happen since we enforce minimums for - // FeeEstimator.BumpPercent and FeeEstimator.BumpMin in the config validation, - // but it's here anyway for a "belts and braces" approach - return bumpedFeePrice, fmt.Errorf("bumped fee price of %s is equal to original fee price of %s."+ - " ACTION REQUIRED: This is a configuration error, you must increase either "+ - "FeeEstimator.BumpPercent or FeeEstimator.BumpMin: %w", toChainUnit(bumpedFeePrice), toChainUnit(bumpedFeePrice), ErrBump) - } - return bumpedFeePrice, nil -} - -// Returns highest bumped fee price of originalFeePrice bumped by fixed units or percentage. -func maxBumpedFee(originalFeePrice *big.Int, feeBumpPercent uint16, feeBumpUnits *big.Int) *big.Int { - return bigmath.Max( - bigmath.AddPercentage(originalFeePrice, feeBumpPercent), - new(big.Int).Add(originalFeePrice, feeBumpUnits), - ) -} - -// Returns the max of currentFeePrice, bumpedFeePrice, and maxFeePrice -func maxFee(lggr logger.SugaredLogger, currentFeePrice, bumpedFeePrice, maxFeePrice *big.Int, feeType string, toChainUnit feeUnitToChainUnit) *big.Int { - if currentFeePrice == nil { - return bumpedFeePrice - } - if currentFeePrice.Cmp(maxFeePrice) > 0 { - // Shouldn't happen because the estimator should not be allowed to - // estimate a higher fee than the maximum allowed - lggr.AssumptionViolationf("Ignoring current %s of %s that would exceed max %s of %s", feeType, toChainUnit(currentFeePrice), feeType, toChainUnit(maxFeePrice)) - } else if bumpedFeePrice.Cmp(currentFeePrice) < 0 { - // If the current fee price is higher than the old price bumped, use that instead - return currentFeePrice - } - return bumpedFeePrice -} diff --git a/pkg/fee/models_test.go b/pkg/fee/models_test.go deleted file mode 100644 index 2ba415c92..000000000 --- a/pkg/fee/models_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package fee - -import ( - "fmt" - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" -) - -// This test is based on EVM Fixed Fee Estimator. -func TestCalculateFee(t *testing.T) { - t.Run("CalculateFee returns DefaultPrice when UserSpecifiedMaxFeePrice and MaxFeePriceConfigured are greater", func(t *testing.T) { - cfg := newMockFeeEstimatorConfig(nil) - assert.Equal(t, big.NewInt(42), CalculateFee(cfg.UserSpecifiedMaxFeePrice, cfg.DefaultPrice, cfg.MaxFeePriceConfigured)) - }) - - t.Run("CalculateFee returns UserSpecifiedMaxFeePrice when it's lower than DefaultPrice and MaxFeePriceConfigured", func(t *testing.T) { - cfg := newMockFeeEstimatorConfig(&mockFeeEstimatorConfig{ - UserSpecifiedMaxFeePrice: big.NewInt(30), - DefaultPrice: big.NewInt(42), - MultiplierLimit: 1.1, - MaxFeePriceConfigured: big.NewInt(35), - }) - assert.Equal(t, big.NewInt(30), CalculateFee(cfg.UserSpecifiedMaxFeePrice, cfg.DefaultPrice, cfg.MaxFeePriceConfigured)) - }) - - t.Run("CalculateFee returns global maximum price", func(t *testing.T) { - cfg := newMockFeeEstimatorConfig(&mockFeeEstimatorConfig{ - UserSpecifiedMaxFeePrice: big.NewInt(30), - DefaultPrice: big.NewInt(42), - MultiplierLimit: 1.1, - MaxFeePriceConfigured: big.NewInt(20), - }) - assert.Equal(t, big.NewInt(20), CalculateFee(cfg.UserSpecifiedMaxFeePrice, cfg.DefaultPrice, cfg.MaxFeePriceConfigured)) - }) -} - -func TestCalculateBumpedFee(t *testing.T) { - lggr := logger.Sugared(logger.Test(t)) - // Create a mock config - cfg := newMockFeeEstimatorConfig(&mockFeeEstimatorConfig{ - UserSpecifiedMaxFeePrice: big.NewInt(1000000), - DefaultPrice: big.NewInt(42), - MaxFeePriceConfigured: big.NewInt(1000000), - MultiplierLimit: 1.1, - }) - currentFeePrice := cfg.DefaultPrice - originalFeePrice := big.NewInt(42) - maxBumpPrice := big.NewInt(1000000) - bumpMin := big.NewInt(150) - bumpPercent := uint16(10) - - // Expected results - expectedFeePrice := big.NewInt(192) - - actualFeePrice, err := CalculateBumpedFee( - lggr, - currentFeePrice, - originalFeePrice, - cfg.MaxFeePriceConfigured, - maxBumpPrice, - bumpMin, - bumpPercent, - toChainUnit, - ) - require.NoError(t, err) - - assert.Equal(t, expectedFeePrice, actualFeePrice) -} - -func TestApplyMultiplier(t *testing.T) { - testCases := []struct { - cfg *mockFeeEstimatorConfig - input int64 - want int - }{ - { - cfg: newMockFeeEstimatorConfig(&mockFeeEstimatorConfig{ - UserSpecifiedMaxFeePrice: big.NewInt(2000000), - DefaultPrice: big.NewInt(84), - MaxFeePriceConfigured: big.NewInt(2000000), - MultiplierLimit: 1.2, - }), - input: 100000, - want: 120000, - }, - { - cfg: newMockFeeEstimatorConfig(nil), // default config - input: 100000, - want: 110000, - }, - } - - for _, tc := range testCases { - got, err := ApplyMultiplier(uint32(tc.input), tc.cfg.MultiplierLimit) - require.NoError(t, err) - assert.Equal(t, tc.want, int(got)) - } -} - -// type dummyFee big.Int - -type mockFeeEstimatorConfig struct { - UserSpecifiedMaxFeePrice *big.Int - DefaultPrice *big.Int - MaxFeePriceConfigured *big.Int - MultiplierLimit float32 -} - -// Currently the values are based on EVM Fixed Fee Estimator. -func newMockFeeEstimatorConfig(cfg *mockFeeEstimatorConfig) *mockFeeEstimatorConfig { - if cfg == nil { - return &mockFeeEstimatorConfig{ - UserSpecifiedMaxFeePrice: big.NewInt(1000000), - DefaultPrice: big.NewInt(42), - MaxFeePriceConfigured: big.NewInt(1000000), - MultiplierLimit: 1.1, - } - } - - return cfg -} - -func toChainUnit(fee *big.Int) string { - return fmt.Sprintf("%d chain unit", fee) -} diff --git a/pkg/fee/types/fee.go b/pkg/fee/types/fee.go deleted file mode 100644 index 2c03db597..000000000 --- a/pkg/fee/types/fee.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - "fmt" -) - -// Opt is an option for a gas estimator -type Opt int - -const ( - // OptForceRefetch forces the estimator to bust a cache if necessary - OptForceRefetch Opt = iota -) - -type Fee fmt.Stringer diff --git a/pkg/fee/utils.go b/pkg/fee/utils.go deleted file mode 100644 index b83e28bd7..000000000 --- a/pkg/fee/utils.go +++ /dev/null @@ -1,21 +0,0 @@ -package fee - -import ( - "fmt" - "math" - "math/big" - - "github.com/shopspring/decimal" -) - -func ApplyMultiplier(feeLimit uint32, multiplier float32) (uint32, error) { - result := decimal.NewFromBigInt(big.NewInt(0).SetUint64(uint64(feeLimit)), 0).Mul(decimal.NewFromFloat32(multiplier)).IntPart() - - if result > math.MaxUint32 { - return 0, fmt.Errorf("integer overflow when applying multiplier of %f to fee limit of %d", multiplier, feeLimit) - } - return uint32(result), nil -} - -// Returns the fee in its chain specific unit. -type feeUnitToChainUnit func(fee *big.Int) string