From a813e050b937e9c3b3963e8951987834821e64cb Mon Sep 17 00:00:00 2001 From: dwasse Date: Tue, 22 Oct 2024 12:13:46 -0500 Subject: [PATCH] feat(rfq-relayer): make QuoteWidthBps a token-level param [SLT-354] (#3305) * Feat: make QuoteWidthBps token-level param * [goreleaser] * Fix: build * [goreleaser] * Fix: tests * Cleanup: lint * [goreleaser] * [goreleaser] --- services/rfq/relayer/quoter/quoter.go | 2 +- services/rfq/relayer/quoter/quoter_test.go | 9 ++++---- services/rfq/relayer/relconfig/config.go | 6 ++--- services/rfq/relayer/relconfig/config_test.go | 18 --------------- services/rfq/relayer/relconfig/getters.go | 22 ++++++++++--------- 5 files changed, 20 insertions(+), 37 deletions(-) diff --git a/services/rfq/relayer/quoter/quoter.go b/services/rfq/relayer/quoter/quoter.go index fb5ef025e2..36669422d3 100644 --- a/services/rfq/relayer/quoter/quoter.go +++ b/services/rfq/relayer/quoter/quoter.go @@ -818,7 +818,7 @@ func (m *Manager) getDestAmount(parentCtx context.Context, originAmount *big.Int if err != nil { return nil, fmt.Errorf("error getting quote offset bps: %w", err) } - quoteWidthBps, err := m.config.GetQuoteWidthBps(input.DestChainID) + quoteWidthBps, err := m.config.GetQuoteWidthBps(input.DestChainID, tokenName) if err != nil { return nil, fmt.Errorf("error getting quote width bps: %w", err) } diff --git a/services/rfq/relayer/quoter/quoter_test.go b/services/rfq/relayer/quoter/quoter_test.go index 48a5b1f19b..d9a4822f8b 100644 --- a/services/rfq/relayer/quoter/quoter_test.go +++ b/services/rfq/relayer/quoter/quoter_test.go @@ -354,12 +354,12 @@ func (s *QuoterSuite) TestGetDestAmount() { DestBalance: balance, } setQuoteParams := func(originQuoteOffsetBps, destQuoteOffsetBps, quoteWidthBps float64) { - s.config.BaseChainConfig.QuoteWidthBps = quoteWidthBps tokenCfg := s.config.Chains[origin].Tokens["USDC"] tokenCfg.QuoteOffsetBps = originQuoteOffsetBps s.config.Chains[origin].Tokens["USDC"] = tokenCfg tokenCfg = s.config.Chains[dest].Tokens["USDC"] tokenCfg.QuoteOffsetBps = destQuoteOffsetBps + tokenCfg.QuoteWidthBps = quoteWidthBps s.config.Chains[dest].Tokens["USDC"] = tokenCfg s.manager.SetConfig(s.config) } @@ -398,12 +398,11 @@ func (s *QuoterSuite) TestGetDestAmount() { expectedAmount = big.NewInt(960_000_000) s.Equal(expectedAmount, destAmount) - // Set QuoteWidthBps to -100, should default to balance. + // Set QuoteWidthBps to -100, should error. setQuoteParams(0, 0, -100) destAmount, err = s.manager.GetDestAmount(s.GetTestContext(), balance, "USDC", input) - s.NoError(err) - expectedAmount = balance - s.Equal(expectedAmount, destAmount) + s.Error(err) + s.Nil(destAmount) // Set origin offset to 100, should return 101% of balance. setQuoteParams(100, 0, 0) diff --git a/services/rfq/relayer/relconfig/config.go b/services/rfq/relayer/relconfig/config.go index 220627e13a..5804c3da5d 100644 --- a/services/rfq/relayer/relconfig/config.go +++ b/services/rfq/relayer/relconfig/config.go @@ -99,9 +99,6 @@ type ChainConfig struct { MinGasToken string `yaml:"min_gas_token"` // QuotePct is the percent of balance to quote. QuotePct *float64 `yaml:"quote_pct"` - // QuoteWidthBps is the number of basis points to deduct from the dest amount. - // Note that this parameter is applied on a chain level and must be positive. - QuoteWidthBps float64 `yaml:"quote_width_bps"` // QuoteFixedFeeMultiplier is the multiplier for the fixed fee, applied when generating quotes. QuoteFixedFeeMultiplier *float64 `yaml:"quote_fixed_fee_multiplier"` // RelayFixedFeeMultiplier is the multiplier for the fixed fee, applied when relaying. @@ -142,6 +139,9 @@ type TokenConfig struct { // Note that this value can be positive or negative; if positive it effectively increases the quoted price // of the given token, and vice versa. QuoteOffsetBps float64 `yaml:"quote_offset_bps"` + // QuoteWidthBps is the number of basis points to deduct from the dest amount. + // Note that this parameter must be positive. + QuoteWidthBps float64 `yaml:"quote_width_bps"` // MaxBalance is the maximum balance that should be accumulated for this token on this chain (human-readable units) MaxBalance *string `yaml:"max_balance"` } diff --git a/services/rfq/relayer/relconfig/config_test.go b/services/rfq/relayer/relconfig/config_test.go index 355f92264a..13c1060863 100644 --- a/services/rfq/relayer/relconfig/config_test.go +++ b/services/rfq/relayer/relconfig/config_test.go @@ -31,7 +31,6 @@ func TestChainGetters(t *testing.T) { L1FeeDestGasEstimate: 40000, MinGasToken: "1000", QuotePct: relconfig.NewFloatPtr(0), - QuoteWidthBps: 10, QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1), RebalanceConfigs: relconfig.RebalanceConfigs{ Synapse: &relconfig.SynapseCCTPRebalanceConfig{ @@ -60,7 +59,6 @@ func TestChainGetters(t *testing.T) { L1FeeDestGasEstimate: 40001, MinGasToken: "1001", QuotePct: relconfig.NewFloatPtr(51), - QuoteWidthBps: 11, QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.2), RebalanceConfigs: relconfig.RebalanceConfigs{ Synapse: &relconfig.SynapseCCTPRebalanceConfig{ @@ -91,7 +89,6 @@ func TestChainGetters(t *testing.T) { L1FeeDestGasEstimate: 40000, MinGasToken: "1000", QuotePct: relconfig.NewFloatPtr(50), - QuoteWidthBps: 10, QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1), Tokens: map[string]relconfig.TokenConfig{ "USDC": { @@ -257,20 +254,6 @@ func TestChainGetters(t *testing.T) { assert.Equal(t, chainVal, 0.) }) - t.Run("GetQuoteWidthBps", func(t *testing.T) { - defaultVal, err := cfg.GetQuoteWidthBps(badChainID) - assert.NoError(t, err) - assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.QuoteWidthBps) - - baseVal, err := cfgWithBase.GetQuoteWidthBps(badChainID) - assert.NoError(t, err) - assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.QuoteWidthBps) - - chainVal, err := cfgWithBase.GetQuoteWidthBps(chainID) - assert.NoError(t, err) - assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].QuoteWidthBps) - }) - t.Run("GetQuoteFixedFeeMultiplier", func(t *testing.T) { defaultVal, err := cfg.GetQuoteFixedFeeMultiplier(badChainID) assert.NoError(t, err) @@ -311,7 +294,6 @@ func TestGetQuoteOffset(t *testing.T) { L1FeeDestGasEstimate: 40000, MinGasToken: "1000", QuotePct: relconfig.NewFloatPtr(50), - QuoteWidthBps: 10, QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1), Tokens: map[string]relconfig.TokenConfig{ "USDC": { diff --git a/services/rfq/relayer/relconfig/getters.go b/services/rfq/relayer/relconfig/getters.go index a3fbb25cc7..cbc4f56edb 100644 --- a/services/rfq/relayer/relconfig/getters.go +++ b/services/rfq/relayer/relconfig/getters.go @@ -20,7 +20,6 @@ var DefaultChainConfig = ChainConfig{ DestGasEstimate: 100000, MinGasToken: "100000000000000000", // 1 ETH QuotePct: NewFloatPtr(100), - QuoteWidthBps: 0, QuoteFixedFeeMultiplier: NewFloatPtr(1), RelayFixedFeeMultiplier: NewFloatPtr(1), } @@ -440,20 +439,23 @@ func (c Config) GetMaxBalance(chainID int, addr common.Address) *big.Int { } // GetQuoteWidthBps returns the QuoteWidthBps for the given chainID. -func (c Config) GetQuoteWidthBps(chainID int) (value float64, err error) { - rawValue, err := c.getChainConfigValue(chainID, "QuoteWidthBps") - if err != nil { - return value, err +func (c Config) GetQuoteWidthBps(chainID int, tokenName string) (value float64, err error) { + chainCfg, ok := c.Chains[chainID] + if !ok { + return 0, fmt.Errorf("no chain config for chain %d", chainID) } - value, ok := rawValue.(float64) + tokenCfg, ok := chainCfg.Tokens[tokenName] if !ok { - return value, fmt.Errorf("failed to cast QuoteWidthBps to float") + return 0, fmt.Errorf("no token config for chain %d and token %s", chainID, tokenName) } - if value <= 0 { - value = DefaultChainConfig.QuoteWidthBps + + width := tokenCfg.QuoteWidthBps + if width < 0 { + return 0, fmt.Errorf("quote width bps must be positive: %f", width) } - return value, nil + + return width, nil } // GetQuoteFixedFeeMultiplier returns the QuoteFixedFeeMultiplier for the given chainID.