From 8e90738db865885325053c60cc709925378501ad Mon Sep 17 00:00:00 2001 From: Mohammed Affan Date: Wed, 2 Oct 2024 16:24:50 -0400 Subject: [PATCH] Update GetAllRevshare to handle liquidations (#2413) --- protocol/x/affiliates/abci.go | 5 +- .../x/clob/keeper/process_single_match.go | 2 +- protocol/x/revshare/keeper/revshare.go | 10 +- protocol/x/revshare/keeper/revshare_test.go | 118 ++++++++++++++++++ protocol/x/revshare/types/errors.go | 4 +- 5 files changed, 130 insertions(+), 9 deletions(-) diff --git a/protocol/x/affiliates/abci.go b/protocol/x/affiliates/abci.go index ccffe2ff8e..90063b492f 100644 --- a/protocol/x/affiliates/abci.go +++ b/protocol/x/affiliates/abci.go @@ -1,8 +1,6 @@ package affiliates import ( - "runtime/debug" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dydxprotocol/v4-chain/protocol/lib/log" "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/keeper" @@ -13,7 +11,6 @@ func EndBlocker( keeper *keeper.Keeper, ) { if err := keeper.AggregateAffiliateReferredVolumeForFills(ctx); err != nil { - log.ErrorLog(ctx, "error aggregating affiliate volume for fills", "error", - err, "stack", string(debug.Stack())) + log.ErrorLogWithError(ctx, "error aggregating affiliate volume for fills", err) } } diff --git a/protocol/x/clob/keeper/process_single_match.go b/protocol/x/clob/keeper/process_single_match.go index 903e351928..c2e504ea72 100644 --- a/protocol/x/clob/keeper/process_single_match.go +++ b/protocol/x/clob/keeper/process_single_match.go @@ -467,7 +467,7 @@ func (k Keeper) persistMatchedOrders( revSharesForFill, err := k.revshareKeeper.GetAllRevShares(ctx, fillForProcess, affiliatesWhitelistMap) if err != nil { revSharesForFill = revsharetypes.RevSharesForFill{} - log.ErrorLog(ctx, "error getting rev shares for fill", "error", err) + log.ErrorLogWithError(ctx, "error getting rev shares for fill", err) } if revSharesForFill.AffiliateRevShare != nil { affiliateRevSharesQuoteQuantums = revSharesForFill.AffiliateRevShare.QuoteQuantums diff --git a/protocol/x/revshare/keeper/revshare.go b/protocol/x/revshare/keeper/revshare.go index a842083791..b249e30fca 100644 --- a/protocol/x/revshare/keeper/revshare.go +++ b/protocol/x/revshare/keeper/revshare.go @@ -175,13 +175,18 @@ func (k Keeper) GetAllRevShares( makerFees := fill.MakerFeeQuoteQuantums netFees := big.NewInt(0).Add(takerFees, makerFees) + // when net fee is zero, no rev share is generated from the fill + if netFees.Sign() == 0 { + return types.RevSharesForFill{}, nil + } + affiliateRevShares, affiliateFeesShared, err := k.getAffiliateRevShares(ctx, fill, affiliatesWhitelistMap) if err != nil { return types.RevSharesForFill{}, err } netFeesSubAffiliateFeesShared := new(big.Int).Sub(netFees, affiliateFeesShared) if netFeesSubAffiliateFeesShared.Sign() <= 0 { - return types.RevSharesForFill{}, types.ErrAffiliateFeesSharedExceedsNetFees + return types.RevSharesForFill{}, types.ErrAffiliateFeesSharedGreaterThanOrEqualToNetFees } unconditionalRevShares, err := k.getUnconditionalRevShares(ctx, netFeesSubAffiliateFeesShared) @@ -233,7 +238,8 @@ func (k Keeper) getAffiliateRevShares( ) ([]types.RevShare, *big.Int, error) { takerAddr := fill.TakerAddr takerFee := fill.TakerFeeQuoteQuantums - if fill.MonthlyRollingTakerVolumeQuantums >= types.MaxReferee30dVolumeForAffiliateShareQuantums { + if fill.MonthlyRollingTakerVolumeQuantums >= types.MaxReferee30dVolumeForAffiliateShareQuantums || + takerFee.Sign() == 0 { return nil, big.NewInt(0), nil } diff --git a/protocol/x/revshare/keeper/revshare_test.go b/protocol/x/revshare/keeper/revshare_test.go index 23f2c2422f..d49c46ea75 100644 --- a/protocol/x/revshare/keeper/revshare_test.go +++ b/protocol/x/revshare/keeper/revshare_test.go @@ -726,6 +726,124 @@ func TestKeeper_GetAllRevShares_Valid(t *testing.T) { affiliatesKeeper *affiliateskeeper.Keeper) { }, }, + { + name: "Revshares with 0 fees from maker and taker", + expectedRevSharesForFill: types.RevSharesForFill{}, + fill: clobtypes.FillForProcess{ + TakerAddr: constants.AliceAccAddress.String(), + TakerFeeQuoteQuantums: big.NewInt(0), + MakerAddr: constants.BobAccAddress.String(), + MakerFeeQuoteQuantums: big.NewInt(0), + FillQuoteQuantums: big.NewInt(100_000_000_000), + ProductId: perpetualId, + MonthlyRollingTakerVolumeQuantums: 1_000_000_000_000, + MarketId: marketId, + }, + setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, + affiliatesKeeper *affiliateskeeper.Keeper) { + err := keeper.SetMarketMapperRevenueShareParams(ctx, types.MarketMapperRevenueShareParams{ + Address: constants.AliceAccAddress.String(), + RevenueSharePpm: 100_000, // 10% + ValidDays: 1, + }) + require.NoError(t, err) + + keeper.SetUnconditionalRevShareConfigParams(ctx, types.UnconditionalRevShareConfig{ + Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ + { + Address: constants.BobAccAddress.String(), + SharePpm: 200_000, // 20% + }, + { + Address: constants.AliceAccAddress.String(), + SharePpm: 300_000, // 30% + }, + }, + }) + + err = affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) + require.NoError(t, err) + err = affiliatesKeeper.RegisterAffiliate(ctx, constants.AliceAccAddress.String(), + constants.BobAccAddress.String()) + require.NoError(t, err) + }, + }, + { + name: "Valid revenue share with 0 taker fee and positive maker fees", + expectedRevSharesForFill: types.RevSharesForFill{ + AllRevShares: []types.RevShare{ + { + Recipient: constants.BobAccAddress.String(), + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, + QuoteQuantums: big.NewInt(400_000), + RevSharePpm: 200_000, + }, + { + Recipient: constants.AliceAccAddress.String(), + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: types.REV_SHARE_TYPE_UNCONDITIONAL, + QuoteQuantums: big.NewInt(600_000), + RevSharePpm: 300_000, + }, + { + Recipient: constants.AliceAccAddress.String(), + RevShareFeeSource: types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE, + RevShareType: types.REV_SHARE_TYPE_MARKET_MAPPER, + QuoteQuantums: big.NewInt(200_000), + RevSharePpm: 100_000, + }, + }, + AffiliateRevShare: nil, + FeeSourceToQuoteQuantums: map[types.RevShareFeeSource]*big.Int{ + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: big.NewInt(0), + // unconditional + market mapper rev shares fees + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: big.NewInt(1_200_000), + }, + FeeSourceToRevSharePpm: map[types.RevShareFeeSource]uint32{ + types.REV_SHARE_FEE_SOURCE_TAKER_FEE: 0, + types.REV_SHARE_FEE_SOURCE_NET_PROTOCOL_REVENUE: 600_000, + }, + }, + fill: clobtypes.FillForProcess{ + TakerAddr: constants.AliceAccAddress.String(), + TakerFeeQuoteQuantums: big.NewInt(0), + MakerAddr: constants.BobAccAddress.String(), + MakerFeeQuoteQuantums: big.NewInt(2_000_000), + FillQuoteQuantums: big.NewInt(100_000_000_000), + ProductId: perpetualId, + MonthlyRollingTakerVolumeQuantums: 1_000_000_000_000, + MarketId: marketId, + }, + setup: func(tApp *testapp.TestApp, ctx sdk.Context, keeper *keeper.Keeper, + affiliatesKeeper *affiliateskeeper.Keeper) { + err := keeper.SetMarketMapperRevenueShareParams(ctx, types.MarketMapperRevenueShareParams{ + Address: constants.AliceAccAddress.String(), + RevenueSharePpm: 100_000, // 10% + ValidDays: 1, + }) + require.NoError(t, err) + + keeper.SetUnconditionalRevShareConfigParams(ctx, types.UnconditionalRevShareConfig{ + Configs: []types.UnconditionalRevShareConfig_RecipientConfig{ + { + Address: constants.BobAccAddress.String(), + SharePpm: 200_000, // 20% + }, + { + Address: constants.AliceAccAddress.String(), + SharePpm: 300_000, // 30% + }, + }, + }) + + err = affiliatesKeeper.UpdateAffiliateTiers(ctx, affiliatetypes.DefaultAffiliateTiers) + require.NoError(t, err) + err = affiliatesKeeper.RegisterAffiliate(ctx, constants.AliceAccAddress.String(), + constants.BobAccAddress.String()) + require.NoError(t, err) + }, + }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { diff --git a/protocol/x/revshare/types/errors.go b/protocol/x/revshare/types/errors.go index 702ae92d15..e270cce323 100644 --- a/protocol/x/revshare/types/errors.go +++ b/protocol/x/revshare/types/errors.go @@ -36,9 +36,9 @@ var ( 6, "total fees shared exceeds net fees", ) - ErrAffiliateFeesSharedExceedsNetFees = errorsmod.Register( + ErrAffiliateFeesSharedGreaterThanOrEqualToNetFees = errorsmod.Register( ModuleName, 7, - "affiliate fees shared exceeds net fees", + "affiliate fees shared greater than or equal to net fees", ) )