Skip to content

Commit

Permalink
Add FixedFeeMultiplier to rfq fee pricer (#1782)
Browse files Browse the repository at this point in the history
* Feat: apply fixed fee multiplier

* Feat: add TestGetTotalFeeWithMultiplier
  • Loading branch information
dwasse authored Jan 8, 2024
1 parent 8470b73 commit 92a42e5
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
6 changes: 4 additions & 2 deletions services/rfq/relayer/pricer/fee_pricer.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ func (f *feePricer) getFee(ctx context.Context, gasChain, denomChain uint32, gas
feeUSDC := new(big.Float).Mul(feeUSD, new(big.Float).SetFloat64(denomTokenPrice))
// Note that this rounds towards zero- we may need to apply rounding here if
// we want to be conservative and lean towards overestimating fees.
feeUSDCDecimals, _ := new(big.Float).Mul(feeUSDC, new(big.Float).SetInt(denomDecimalsFactor)).Int(nil)
return feeUSDCDecimals, nil
feeUSDCDecimals := new(big.Float).Mul(feeUSDC, new(big.Float).SetInt(denomDecimalsFactor))
// Apply the fixed fee multiplier.
feeUSDCDecimalsScaled, _ := new(big.Float).Mul(feeUSDCDecimals, new(big.Float).SetFloat64(f.config.GetFixedFeeMultiplier())).Int(nil)
return feeUSDCDecimalsScaled, nil
}

// getGasPrice returns the gas price for a given chainID in native units.
Expand Down
64 changes: 64 additions & 0 deletions services/rfq/relayer/pricer/fee_pricer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,67 @@ func (s *PricerSuite) TestGetGasPrice() {
return expectedGasPrice.String() == gasPrice.String()
})
}

func (s *PricerSuite) TestGetTotalFeeWithMultiplier() {
// Override the fixed fee multiplier to greater than 1.
s.config.FeePricer.FixedFeeMultiplier = 2

// Build a new FeePricer with a mocked client for fetching gas price.
clientFetcher := new(fetcherMocks.ClientFetcher)
clientOrigin := new(clientMocks.EVM)
clientDestination := new(clientMocks.EVM)
headerOrigin := &types.Header{BaseFee: big.NewInt(100_000_000_000)} // 100 gwei
headerDestination := &types.Header{BaseFee: big.NewInt(500_000_000_000)} // 500 gwei
clientOrigin.On(testsuite.GetFunctionName(clientOrigin.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerOrigin, nil)
clientDestination.On(testsuite.GetFunctionName(clientDestination.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerDestination, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.origin))).Once().Return(clientOrigin, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.destination))).Once().Return(clientDestination, nil)
feePricer := pricer.NewFeePricer(s.config, clientFetcher)
go func() { feePricer.Start(s.GetTestContext()) }()

// Calculate the total fee.
fee, err := feePricer.GetTotalFee(s.GetTestContext(), s.origin, s.destination, "USDC")
s.NoError(err)

// The expected fee should be the sum of the Origin and Destination fees, i.e. 200_500_000.
expectedFee := big.NewInt(200_500_000) // 200.50 usd
s.Equal(expectedFee, fee)

// Override the fixed fee multiplier to less than 1; should default to 1.
s.config.FeePricer.FixedFeeMultiplier = -1

// Build a new FeePricer with a mocked client for fetching gas price.
clientOrigin.On(testsuite.GetFunctionName(clientOrigin.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerOrigin, nil)
clientDestination.On(testsuite.GetFunctionName(clientDestination.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerDestination, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.origin))).Once().Return(clientOrigin, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.destination))).Once().Return(clientDestination, nil)
feePricer = pricer.NewFeePricer(s.config, clientFetcher)
go func() { feePricer.Start(s.GetTestContext()) }()

// Calculate the total fee.
fee, err = feePricer.GetTotalFee(s.GetTestContext(), s.origin, s.destination, "USDC")
s.NoError(err)

// The expected fee should be the sum of the Origin and Destination fees, i.e. 100_250_000.
expectedFee = big.NewInt(100_250_000) // 100.25 usd
s.Equal(expectedFee, fee)

// Reset the fixed fee multiplier to zero; should default to 1
s.config.FeePricer.FixedFeeMultiplier = 0

// Build a new FeePricer with a mocked client for fetching gas price.
clientOrigin.On(testsuite.GetFunctionName(clientOrigin.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerOrigin, nil)
clientDestination.On(testsuite.GetFunctionName(clientDestination.HeaderByNumber), mock.Anything, mock.Anything).Once().Return(headerDestination, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.origin))).Once().Return(clientOrigin, nil)
clientFetcher.On(testsuite.GetFunctionName(clientFetcher.GetClient), mock.Anything, big.NewInt(int64(s.destination))).Once().Return(clientDestination, nil)
feePricer = pricer.NewFeePricer(s.config, clientFetcher)
go func() { feePricer.Start(s.GetTestContext()) }()

// Calculate the total fee.
fee, err = feePricer.GetTotalFee(s.GetTestContext(), s.origin, s.destination, "USDC")
s.NoError(err)

// The expected fee should be the sum of the Origin and Destination fees, i.e. 100_250_000.
expectedFee = big.NewInt(100_250_000) // 100.25 usd
s.Equal(expectedFee, fee)
}
12 changes: 12 additions & 0 deletions services/rfq/relayer/relconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ type FeePricerConfig struct {
OriginGasEstimate int `yaml:"origin_gas_estimate"`
// DestinationGasEstimate is the gas required to execute relay transaction on destination chain.
DestinationGasEstimate int `yaml:"destination_gas_estimate"`
// FixedFeeMultiplier is the multiplier for the fixed fee.
FixedFeeMultiplier float64 `yaml:"fixed_fee_multiplier"`
// GasPriceCacheTTLSeconds is the TTL for the gas price cache.
GasPriceCacheTTLSeconds int `yaml:"gas_price_cache_ttl"`
// TokenPriceCacheTTLSeconds is the TTL for the token price cache.
Expand Down Expand Up @@ -193,4 +195,14 @@ func (c Config) GetTokenName(chain uint32, addr string) (string, error) {
return "", fmt.Errorf("no tokenName found for chain %d and address %s", chain, addr)
}

const defaultFixedFeeMultiplier = 1

// GetFixedFeeMultiplier returns the fixed fee multiplier.
func (c Config) GetFixedFeeMultiplier() float64 {
if c.FeePricer.FixedFeeMultiplier <= 0 {
return defaultFixedFeeMultiplier
}
return c.FeePricer.FixedFeeMultiplier
}

var _ IConfig = &Config{}
2 changes: 2 additions & 0 deletions services/rfq/relayer/relconfig/iconfig_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 92a42e5

Please sign in to comment.