From 11e1ac417af62980c1f5898c7c43073317d46c6c Mon Sep 17 00:00:00 2001 From: Daniel Wasserman Date: Wed, 13 Mar 2024 00:01:38 -0400 Subject: [PATCH] Feat: add MinRebalanceAmount with tests --- services/rfq/relayer/inventory/manager.go | 6 ++++ .../rfq/relayer/inventory/manager_test.go | 20 ++++++++++-- services/rfq/relayer/relconfig/config.go | 2 ++ services/rfq/relayer/relconfig/getters.go | 32 +++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/services/rfq/relayer/inventory/manager.go b/services/rfq/relayer/inventory/manager.go index 658d1a7220..e566e82515 100644 --- a/services/rfq/relayer/inventory/manager.go +++ b/services/rfq/relayer/inventory/manager.go @@ -472,6 +472,12 @@ func getRebalance(span trace.Span, cfg relconfig.Config, tokens map[int]map[comm return nil, nil } + // clip the rebalance amount by the configured min + minAmount := cfg.GetMinRebalanceAmount(maxTokenData.ChainID, maxTokenData.Addr) + if amount.Cmp(minAmount) < 0 { + amount = minAmount + } + // clip the rebalance amount by the configured max maxAmount := cfg.GetMaxRebalanceAmount(maxTokenData.ChainID, maxTokenData.Addr) if amount.Cmp(maxAmount) > 0 { diff --git a/services/rfq/relayer/inventory/manager_test.go b/services/rfq/relayer/inventory/manager_test.go index 11d33709f6..0ff3cbee62 100644 --- a/services/rfq/relayer/inventory/manager_test.go +++ b/services/rfq/relayer/inventory/manager_test.go @@ -88,7 +88,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { usdcDataDest.Addr: &usdcDataDest, }, } - getConfig := func(maxRebalanceAmount string) relconfig.Config { + getConfig := func(minRebalanceAmount, maxRebalanceAmount string) relconfig.Config { return relconfig.Config{ Chains: map[int]relconfig.ChainConfig{ origin: { @@ -98,6 +98,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 20, InitialBalancePct: 50, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -109,6 +110,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 20, InitialBalancePct: 50, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -120,6 +122,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 0, InitialBalancePct: 0, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -129,7 +132,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { } // 10 USDC on both chains; no rebalance needed - cfg := getConfig("") + cfg := getConfig("", "") usdcDataOrigin.Balance = big.NewInt(1e7) usdcDataDest.Balance = big.NewInt(1e7) rebalance, err := inventory.GetRebalance(cfg, tokens, origin, usdcDataOrigin.Addr) @@ -148,8 +151,19 @@ func (i *InventoryTestSuite) TestGetRebalance() { } i.Equal(expected, rebalance) + // Set min rebalance amount + cfgWithMax := getConfig("10", "1000000000") + rebalance, err = inventory.GetRebalance(cfgWithMax, tokens, origin, usdcDataOrigin.Addr) + i.NoError(err) + expected = &inventory.RebalanceData{ + OriginMetadata: &usdcDataOrigin, + DestMetadata: &usdcDataDest, + Amount: big.NewInt(1e7), + } + i.Equal(expected, rebalance) + // Set max rebalance amount - cfgWithMax := getConfig("1.1") + cfgWithMax = getConfig("0", "1.1") rebalance, err = inventory.GetRebalance(cfgWithMax, tokens, origin, usdcDataOrigin.Addr) i.NoError(err) expected = &inventory.RebalanceData{ diff --git a/services/rfq/relayer/relconfig/config.go b/services/rfq/relayer/relconfig/config.go index 12d3cb7ef6..a52e7b74f2 100644 --- a/services/rfq/relayer/relconfig/config.go +++ b/services/rfq/relayer/relconfig/config.go @@ -102,6 +102,8 @@ type TokenConfig struct { MaintenanceBalancePct float64 `yaml:"maintenance_balance_pct"` // InitialBalancePct is the percentage of the total balance to retain when triggering a rebalance. InitialBalancePct float64 `yaml:"initial_balance_pct"` + // MinRebalanceAmount is the minimum amount to rebalance in human-readable units. + MinRebalanceAmount string `yaml:"min_rebalance_amount"` // MaxRebalanceAmount is the maximum amount to rebalance in human-readable units. MaxRebalanceAmount string `yaml:"max_rebalance_amount"` } diff --git a/services/rfq/relayer/relconfig/getters.go b/services/rfq/relayer/relconfig/getters.go index 2e0b5362de..6d7e87364e 100644 --- a/services/rfq/relayer/relconfig/getters.go +++ b/services/rfq/relayer/relconfig/getters.go @@ -547,6 +547,38 @@ func (c Config) GetMinQuoteAmount(chainID int, addr common.Address) *big.Int { return quoteAmountScaled } +var defaultMinRebalanceAmount = big.NewInt(1000) + +// GetMinRebalanceAmount returns the min rebalance amount for the given chain and address. +// Note that this getter returns the value in native token decimals. +func (c Config) GetMinRebalanceAmount(chainID int, addr common.Address) *big.Int { + chainCfg, ok := c.Chains[chainID] + if !ok { + return defaultMinRebalanceAmount + } + + var tokenCfg *TokenConfig + for _, cfg := range chainCfg.Tokens { + if common.HexToAddress(cfg.Address).Hex() == addr.Hex() { + cfgCopy := cfg + tokenCfg = &cfgCopy + break + } + } + if tokenCfg == nil { + return defaultMinRebalanceAmount + } + rebalanceAmountFlt, ok := new(big.Float).SetString(tokenCfg.MinRebalanceAmount) + if !ok || rebalanceAmountFlt == nil { + return defaultMinRebalanceAmount + } + + // Scale by the token decimals. + denomDecimalsFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenCfg.Decimals)), nil) + minRebalanceAmountScaled, _ := new(big.Float).Mul(rebalanceAmountFlt, new(big.Float).SetInt(denomDecimalsFactor)).Int(nil) + return minRebalanceAmountScaled +} + var defaultMaxRebalanceAmount = abi.MaxInt256 // GetMaxRebalanceAmount returns the max rebalance amount for the given chain and address.