Skip to content

Commit

Permalink
Add flags for setting fee limits for swaps (L2 routing) (#79)
Browse files Browse the repository at this point in the history
* Flags limitQuoteFees and limitFeesL2, to set fee limits for swaps. The limitQuoteFees flag sets the fee ratio for swaps quotes, while the limitFeesL2 flag sets the fee ratio for swaps max routing fee.

* Docs update

* Add logging for max L2 routing fees in RequestReverseSubmarineSwap function
  • Loading branch information
Jossec101 authored May 8, 2024
1 parent 26d4155 commit 52fc54a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 21 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Flags:
--backoffCoefficient float Coefficient to apply to the backoff (default 0.95)
--backoffLimit float Limit coefficient of the backoff (default 0.1)
-h, --help help for liquidator
--limitFees float Limit fees for swaps e.g. 0.01 = 1% (default 0.007)
--limitFeesL2 float Limit fee ratio for swaps max routing fee e.g. 0.01 = 1% (default 0.002)
--limitQuoteFees float Limit fee ratio for swaps quotes (e.g. onchain+service fee estimation) e.g. 0.01 = 1% (default 0.005)
--lndconnecturis string CSV of lndconnect strings to connect to lnd(s)
--logFormat string Log format from: {text, json} (default "text")
--logLevel string Log level from values: {trace, debug, info, warn, error, fatal, panic} (default "info")
Expand Down Expand Up @@ -55,7 +56,8 @@ Available recipes:
All the flags can be set as environment variables, with the following format, except stated, they are all mandatory:

- LNDCONNECTURIS : CSV of lndconnect strings to connect to lnd(s)\
- LIMITFEES (optional) : Limit to total Swap Fees (default 0.007 -> 0.7% Swap size)
- LIMITQUOTEFEES (optional) : Limit to total Max Quote Fees (L1+service fee) (default 0.007 -> 0.7% of the Swap size)
- LIMITFEESL2 (optional) : Limit to total Max Routing Fees (L2) (default 0.002 -> 0.2% of the Swap size)
- LOOPDCONNECTURIS : CSV of loopdconnect strings to connect to loopd(s)
- POLLINGINTERVAL (optional) : Interval to poll data(default 15s)
- LOGLEVEL (optional) : Log level (default info) from: {trace, debug, info, warn, error, fatal, panic}
Expand Down
11 changes: 7 additions & 4 deletions flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ func init() {
rootCmd.Flags().Float64("backoffLimit", 0.1, "Limit coefficient of the backoff")
viper.BindPFlag("backoffLimit", rootCmd.Flags().Lookup("backoffLimit"))

// Limit fees for swaps
rootCmd.Flags().Float64("limitFees", 0.007, "Limit fees for swaps e.g. 0.01 = 1%")
viper.BindPFlag("limitFees", rootCmd.Flags().Lookup("limitFees"))
// Limit fees for swaps quotes
rootCmd.Flags().Float64("limitQuoteFees", 0.005, "Limit fee ratio for swaps quotes (e.g. onchain+service fee estimation) e.g. 0.01 = 1%")
viper.BindPFlag("limitQuoteFees", rootCmd.Flags().Lookup("limitQuoteFees"))

// Limit fees for swaps L2
rootCmd.Flags().Float64("limitFeesL2", 0.002, "Limit fee ratio for swaps max routing fee e.g. 0.01 = 1%")
viper.BindPFlag("limitFeesL2", rootCmd.Flags().Lookup("limitFeesL2"))

//Sweep conf
rootCmd.Flags().String("sweepConfTarget", "400", "Target number of confirmations for swaps, this uses bitcoin core broken estimator, procced with caution")
Expand All @@ -131,7 +135,6 @@ func init() {
retries = viper.GetInt("retriesBeforeBackoff")
backoffCoefficient = viper.GetFloat64("backoffCoefficient")
backoffLimit = viper.GetFloat64("backoffLimit")
limitFees = viper.GetFloat64("limitFees")

//Set log level and format

Expand Down
1 change: 0 additions & 1 deletion liquidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ var (
retries int
backoffCoefficient float64
backoffLimit float64
limitFees float64
)

// Entrypoint of liquidator main logic
Expand Down
27 changes: 15 additions & 12 deletions provider/loop_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (l *LoopProvider) RequestSubmarineSwap(ctx context.Context, request Submari
return SubmarineSwapResponse{}, err
}

limitFeesStr := viper.GetString("LIMITFEES")
limitFeesStr := viper.GetString("limitQuoteFees")
limitFees, err := strconv.ParseFloat(limitFeesStr, 64)
if err != nil {
return SubmarineSwapResponse{}, err
Expand Down Expand Up @@ -228,8 +228,8 @@ func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request

//Do a quote for loop out
quote, err := client.LoopOutQuote(ctx, &looprpc.QuoteRequest{
Amt: request.SatsAmount,
//ConfTarget: 1, //TODO Make this configurable
Amt: request.SatsAmount,
ConfTarget: viper.GetInt32("sweepConfTarget"),
ExternalHtlc: true,
Private: false,
})
Expand All @@ -239,21 +239,24 @@ func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request
return ReverseSubmarineSwapResponse{}, err
}

limitFeesStr := viper.GetString("LIMITFEES")
limitFees, err := strconv.ParseFloat(limitFeesStr, 64)
if err != nil {
return ReverseSubmarineSwapResponse{}, err
}
limitQuoteFees := viper.GetFloat64("limitQuoteFees")

//This fees are onchain + service fees, NOT L2 fees as they are not in the quote
sumFees := quote.SwapFeeSat + quote.HtlcSweepFeeSat + quote.PrepayAmtSat
maximumFeesAllowed := int64(float64(request.SatsAmount) * limitFees)
maximumFeesAllowed := int64(float64(request.SatsAmount) * limitQuoteFees)

if sumFees > maximumFeesAllowed {
err := fmt.Errorf("swap fees are greater than max limit fees, quote fees: %d, maximum fees allowed: %d", sumFees, maximumFeesAllowed)
err := fmt.Errorf("swap quote fees (L1+Service estimation fees) are greater than max limit fees, quote fees: %d, maximum fees allowed: %d", sumFees, maximumFeesAllowed)
log.Error(err)
return ReverseSubmarineSwapResponse{}, err
}

//Max swap routing fee (L2 fees) is a percentage of the swap amount
l2MaxRoutingFeeRatio := viper.GetFloat64("limitFeesL2")
maxSwapRoutingFee := int64(float64(request.SatsAmount) * l2MaxRoutingFeeRatio)

log.Infof("max L2 routing fees for the swap: %d", maxSwapRoutingFee)

//Get limits
//Amt using btcutil
amt := btcutil.Amount(request.SatsAmount)
Expand All @@ -270,13 +273,13 @@ func (l *LoopProvider) RequestReverseSubmarineSwap(ctx context.Context, request
MaxPrepayAmt: int64(limits.maxPrepayAmt),
MaxSwapFee: int64(limits.maxSwapFee),
MaxPrepayRoutingFee: int64(limits.maxPrepayRoutingFee),
MaxSwapRoutingFee: int64(limits.maxSwapRoutingFee),
MaxSwapRoutingFee: maxSwapRoutingFee,
OutgoingChanSet: request.ChannelSet,
SweepConfTarget: viper.GetInt32("sweepConfTarget"),
HtlcConfirmations: 3,
//The publication deadline is maximum the offset of the swap deadline conf plus the current time
SwapPublicationDeadline: uint64(time.Now().Add(viper.GetDuration("swapPublicationOffset") * time.Minute).Unix()),
Label: fmt.Sprintf("Reverse submarine swap %d sats on date %s", request.SatsAmount, time.Now().Format(time.RFC3339)),
Label: fmt.Sprintf("Reverse submarine swap %d sats on date %s for channels: %v", request.SatsAmount, time.Now().Format(time.RFC3339), request.ChannelSet),
Initiator: "Liquidator",
})

Expand Down
14 changes: 12 additions & 2 deletions provider/loop_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,23 @@ import (
gomock "go.uber.org/mock/gomock"
)

func TestMain(m *testing.M) {

setLimitFees()

m.Run()
}

func setLimitFees() {
viper.Set("limitQuoteFees", "0.005")
viper.Set("limitFeesL2", "0.002")
}

func TestLoopProvider_RequestSubmarineSwap(t *testing.T) {

ctrl := gomock.NewController(t)
defer ctrl.Finish()

viper.Set("LIMITFEES", "0.007")

//Mock lightning swapClient GetLoopInQuote and LoopIn methods to return fake data
swapClient := NewMockSwapClientClient(ctrl)

Expand Down

0 comments on commit 52fc54a

Please sign in to comment.