From 8b05383dabc574582d866952378331a23eb7da1a Mon Sep 17 00:00:00 2001 From: parodime Date: Thu, 9 Jan 2025 16:01:28 -0500 Subject: [PATCH] reduced origin min gas balance when quoting a route w/ origin gas token --- services/rfq/relayer/inventory/manager.go | 21 ++++++++++++++++-- .../rfq/relayer/inventory/mocks/manager.go | 22 +++++++++++++++++++ services/rfq/relayer/quoter/quoter.go | 12 +++++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/services/rfq/relayer/inventory/manager.go b/services/rfq/relayer/inventory/manager.go index 04fbea754d..08290b0ee6 100644 --- a/services/rfq/relayer/inventory/manager.go +++ b/services/rfq/relayer/inventory/manager.go @@ -48,6 +48,8 @@ type Manager interface { ApproveAllTokens(ctx context.Context) error // HasSufficientGas checks if there is sufficient gas for a given route. HasSufficientGas(ctx context.Context, chainID int, gasValue *big.Int) (bool, error) + // HasSufficientGasWithMult checks if there is sufficient gas for a given route with an optional threshold multiplier applied. + HasSufficientGasWithMult(ctx context.Context, chainID int, gasValue *big.Int, thresholdMultiplier *float64) (bool, error) // Rebalance attempts any rebalances that could be executed across all supported tokens and chains. Rebalance(ctx context.Context) error // GetTokenMetadata gets the metadata for a token. @@ -438,6 +440,11 @@ func (i *inventoryManagerImpl) approve(parentCtx context.Context, tokenAddr, con // HasSufficientGas checks if there is sufficient gas for a given route. func (i *inventoryManagerImpl) HasSufficientGas(parentCtx context.Context, chainID int, gasValue *big.Int) (sufficient bool, err error) { + return i.HasSufficientGasWithMult(parentCtx, chainID, gasValue, nil) +} + +// HasSufficientGasWithMult checks if there is sufficient gas for a given route with an optional threshold multiplier applied. +func (i *inventoryManagerImpl) HasSufficientGasWithMult(parentCtx context.Context, chainID int, gasValue *big.Int, thresholdMultiplier *float64) (sufficient bool, err error) { ctx, span := i.handler.Tracer().Start(parentCtx, "HasSufficientGas", trace.WithAttributes( attribute.Int(metrics.ChainID, chainID), )) @@ -447,7 +454,7 @@ func (i *inventoryManagerImpl) HasSufficientGas(parentCtx context.Context, chain gasThreshRaw, err := i.cfg.GetMinGasToken(chainID) if err != nil { - return false, fmt.Errorf("error getting min gas token on origin: %w", err) + return false, fmt.Errorf("error getting min gas token: %w", err) } gasThresh := core.CopyBigInt(gasThreshRaw) if gasValue != nil { @@ -455,9 +462,19 @@ func (i *inventoryManagerImpl) HasSufficientGas(parentCtx context.Context, chain span.SetAttributes(attribute.String("gas_value", gasValue.String())) } + // If param supplied, apply threshold multiplier before comparing + if thresholdMultiplier != nil { + if *thresholdMultiplier < 0 || *thresholdMultiplier > 2 { + return false, fmt.Errorf("thresholdMultiplier out of range: %f", *thresholdMultiplier) + } + gasThreshFloat := new(big.Float).SetInt(gasThresh) + gasThreshFloat.Mul(gasThreshFloat, big.NewFloat(*thresholdMultiplier)) + gasThresh, _ = gasThreshFloat.Int(nil) + } + gasBalance, err := i.GetCommittableBalance(ctx, chainID, util.EthAddress, SkipDBCache()) if err != nil { - return false, fmt.Errorf("error getting committable gas on origin: %w", err) + return false, fmt.Errorf("error getting committable gas: %w", err) } sufficient = gasBalance.Cmp(gasThresh) >= 0 diff --git a/services/rfq/relayer/inventory/mocks/manager.go b/services/rfq/relayer/inventory/mocks/manager.go index d5b75087ad..c1b8fd7c75 100644 --- a/services/rfq/relayer/inventory/mocks/manager.go +++ b/services/rfq/relayer/inventory/mocks/manager.go @@ -136,6 +136,28 @@ func (_m *Manager) HasSufficientGas(ctx context.Context, chainID int, gasValue * return r0, r1 } + +// HasSufficientGasWithMult provides a mock function with given fields: ctx, chainID, gasValue, thresholdMultiplier +func (_m *Manager) HasSufficientGasWithMult(ctx context.Context, chainID int, gasValue *big.Int, thresholdMultiplier *float64) (bool, error) { + ret := _m.Called(ctx, chainID, gasValue, thresholdMultiplier) + + var r0 bool + if rf, ok := ret.Get(0).(func(context.Context, int, *big.Int, *float64) bool); ok { + r0 = rf(ctx, chainID, gasValue, thresholdMultiplier) + } else { + r0 = ret.Get(0).(bool) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int, *big.Int, *float64) error); ok { + r1 = rf(ctx, chainID, gasValue, thresholdMultiplier) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Rebalance provides a mock function with given fields: ctx func (_m *Manager) Rebalance(ctx context.Context) error { ret := _m.Called(ctx) diff --git a/services/rfq/relayer/quoter/quoter.go b/services/rfq/relayer/quoter/quoter.go index f7b03211c9..33c8072602 100644 --- a/services/rfq/relayer/quoter/quoter.go +++ b/services/rfq/relayer/quoter/quoter.go @@ -772,7 +772,17 @@ func (m *Manager) getOriginAmount(parentCtx context.Context, input QuoteInput) ( // First, check if we have enough gas to complete the a bridge for this route // If not, set the quote amount to zero to make sure a stale quote won't be used // TODO: handle in-flight gas; for now we can set a high min_gas_token - sufficentGasOrigin, err := m.inventoryManager.HasSufficientGas(ctx, input.OriginChainID, nil) + + // if the origin token is native gas, require less minimum gas on the origin chain. + // as origin gas gets critically low, this will discourage the relayer from quoting most routes *except* those that will replenish the deficit gas. + var sufficentGasOrigin bool + if input.OriginTokenAddr.Hex() == "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" { + multiplier := 0.65 + sufficentGasOrigin, err = m.inventoryManager.HasSufficientGasWithMult(ctx, input.OriginChainID, nil, &multiplier) + } else { + sufficentGasOrigin, err = m.inventoryManager.HasSufficientGas(ctx, input.OriginChainID, nil) + } + if err != nil { return nil, fmt.Errorf("error checking sufficient gas: %w", err) }