Skip to content

Commit f4c5518

Browse files
authored
Perpetual fees updates (#1355)
* transfer fee when opening position * repay fees * tier address * subtract fee from return amount
1 parent 29e94a5 commit f4c5518

File tree

7 files changed

+91
-31
lines changed

7 files changed

+91
-31
lines changed

x/perpetual/keeper/amm.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,10 @@ func (k Keeper) EstimateSwapGivenIn(ctx sdk.Context, tokenInAmount sdk.Coin, tok
3838
}
3939
params := k.GetParams(ctx)
4040

41-
addr, err := sdk.AccAddressFromBech32(owner)
42-
if err != nil {
43-
addr = sdk.AccAddress{}
44-
}
45-
_, tier := k.tierKeeper.GetMembershipTier(ctx, addr)
46-
perpetualFees := ammtypes.ApplyDiscount(params.GetBigDecPerpetualSwapFee(), tier.GetBigDecDiscount())
47-
takersFee := k.parameterKeeper.GetParams(ctx).GetBigDecTakerFees()
4841
// Estimate swap
4942
snapshot := k.amm.GetPoolWithAccountedBalance(ctx, ammPool.PoolId)
5043
tokensIn := sdk.Coins{tokenInAmount}
51-
tokenOut, slippage, slippageAmount, weightBalanceBonus, _, _, err := k.amm.SwapOutAmtGivenIn(ctx, ammPool.PoolId, k.oracleKeeper, snapshot, tokensIn, tokenOutDenom, perpetualFees, params.GetBigDecWeightBreakingFeeFactor(), takersFee)
44+
tokenOut, slippage, slippageAmount, weightBalanceBonus, _, _, err := k.amm.SwapOutAmtGivenIn(ctx, ammPool.PoolId, k.oracleKeeper, snapshot, tokensIn, tokenOutDenom, osmomath.ZeroBigDec(), params.GetBigDecWeightBreakingFeeFactor(), osmomath.ZeroBigDec())
5245
if err != nil {
5346
return math.ZeroInt(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), math.LegacyDec{}, math.LegacyDec{}, errorsmod.Wrapf(err, "unable to swap (EstimateSwapGivenIn) for in %s and out denom %s", tokenInAmount.String(), tokenOutDenom)
5447
}
@@ -57,6 +50,15 @@ func (k Keeper) EstimateSwapGivenIn(ctx sdk.Context, tokenInAmount sdk.Coin, tok
5750
return math.ZeroInt(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), math.LegacyDec{}, math.LegacyDec{}, errorsmod.Wrapf(types.ErrAmountTooLow, "tokenOut is zero for swap (EstimateSwapGivenIn) for in %s and out denom %s", tokenInAmount.String(), tokenOutDenom)
5851
}
5952

53+
// send for query purpose only
54+
addr, err := sdk.AccAddressFromBech32(owner)
55+
if err != nil {
56+
addr = sdk.AccAddress{}
57+
}
58+
_, tier := k.tierKeeper.GetMembershipTier(ctx, addr)
59+
perpetualFees := ammtypes.ApplyDiscount(params.GetBigDecPerpetualSwapFee(), tier.GetBigDecDiscount())
60+
takersFee := k.parameterKeeper.GetParams(ctx).GetBigDecTakerFees()
61+
6062
return tokenOut.Amount, slippage, slippageAmount, getWeightBreakingFee(weightBalanceBonus), perpetualFees.Dec(), takersFee.Dec(), nil
6163
}
6264

@@ -68,17 +70,9 @@ func (k Keeper) EstimateSwapGivenOut(ctx sdk.Context, tokenOutAmount sdk.Coin, t
6870
params := k.GetParams(ctx)
6971
tokensOut := sdk.Coins{tokenOutAmount}
7072

71-
addr, err := sdk.AccAddressFromBech32(owner)
72-
if err != nil {
73-
addr = sdk.AccAddress{}
74-
}
75-
_, tier := k.tierKeeper.GetMembershipTier(ctx, addr)
76-
perpetualFees := ammtypes.ApplyDiscount(params.GetBigDecPerpetualSwapFee(), tier.GetBigDecDiscount())
77-
takersFee := k.parameterKeeper.GetParams(ctx).GetBigDecTakerFees()
78-
7973
// Estimate swap
8074
snapshot := k.amm.GetPoolWithAccountedBalance(ctx, ammPool.PoolId)
81-
tokenIn, slippage, slippageAmount, weightBalanceBonus, oracleIn, _, err := k.amm.SwapInAmtGivenOut(ctx, ammPool.PoolId, k.oracleKeeper, snapshot, tokensOut, tokenInDenom, perpetualFees, params.GetBigDecWeightBreakingFeeFactor(), takersFee)
75+
tokenIn, slippage, slippageAmount, weightBalanceBonus, oracleIn, _, err := k.amm.SwapInAmtGivenOut(ctx, ammPool.PoolId, k.oracleKeeper, snapshot, tokensOut, tokenInDenom, osmomath.ZeroBigDec(), params.GetBigDecWeightBreakingFeeFactor(), osmomath.ZeroBigDec())
8276
if err != nil {
8377
return math.ZeroInt(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), math.LegacyDec{}, math.LegacyDec{}, errorsmod.Wrapf(err, "unable to swap (EstimateSwapGivenOut) for out %s and in denom %s", tokenOutAmount.String(), tokenInDenom)
8478
}
@@ -87,6 +81,15 @@ func (k Keeper) EstimateSwapGivenOut(ctx sdk.Context, tokenOutAmount sdk.Coin, t
8781
return math.ZeroInt(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), osmomath.ZeroBigDec(), math.LegacyDec{}, math.LegacyDec{}, errorsmod.Wrapf(types.ErrAmountTooLow, "tokenIn is zero for swap (EstimateSwapGivenOut) for out %s and in denom %s", tokenOutAmount.String(), tokenInDenom)
8882
}
8983

84+
// send for query purpose only
85+
addr, err := sdk.AccAddressFromBech32(owner)
86+
if err != nil {
87+
addr = sdk.AccAddress{}
88+
}
89+
_, tier := k.tierKeeper.GetMembershipTier(ctx, addr)
90+
perpetualFees := ammtypes.ApplyDiscount(params.GetBigDecPerpetualSwapFee(), tier.GetBigDecDiscount())
91+
takersFee := k.parameterKeeper.GetParams(ctx).GetBigDecTakerFees()
92+
9093
return tokenIn.Amount, slippage, slippageAmount, getWeightBreakingFee(weightBalanceBonus), oracleIn, perpetualFees.Dec(), takersFee.Dec(), nil
9194
}
9295

x/perpetual/keeper/close_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (suite *PerpetualKeeperTestSuite) TestClose() {
9494
}
9595
},
9696
"",
97-
math.NewInt(204),
97+
math.NewInt(203),
9898
},
9999
{
100100
"Close with price greater than open price and less than take profit price",
@@ -217,7 +217,7 @@ func (suite *PerpetualKeeperTestSuite) TestClose() {
217217
}
218218
},
219219
"",
220-
math.NewInt(502),
220+
math.NewInt(501),
221221
},
222222
{
223223
"Success: close long position,at same price as open price",
@@ -248,7 +248,7 @@ func (suite *PerpetualKeeperTestSuite) TestClose() {
248248
}
249249
},
250250
"",
251-
math.NewInt(204),
251+
math.NewInt(203),
252252
},
253253
{
254254
"Success: close short position at same price as open price",
@@ -277,7 +277,7 @@ func (suite *PerpetualKeeperTestSuite) TestClose() {
277277
}
278278
},
279279
"",
280-
math.NewInt(4498),
280+
math.NewInt(4503),
281281
},
282282
// TODO: Edge case when custody becomes low, this is throwing error, instead it should be closed
283283
// FIX this: error updating mtp health: unable to swap (EstimateSwapGivenOut) for out 1uatom and in denom uusdc: amount too low

x/perpetual/keeper/keeper.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ func (k Keeper) Borrow(ctx sdk.Context, collateralAmount math.Int, custodyAmount
136136
return err
137137
}
138138

139+
// send fees to masterchef and taker collection address
140+
_, err = k.SendFeesToMasterchefAndTakerCollection(ctx, senderAddress, mtp.Address, liabilitiesInCollateral, mtp.CollateralAsset, ammPool)
141+
if err != nil {
142+
return err
143+
}
144+
139145
err = pool.UpdateCustody(mtp.CustodyAsset, mtp.Custody, true, mtp.Position)
140146
if err != nil {
141147
return nil
@@ -285,6 +291,46 @@ func (k Keeper) CollectInsuranceFund(ctx sdk.Context, amount math.Int, returnAss
285291
return insuranceAmount, nil
286292
}
287293

294+
func (k Keeper) SendFeesToMasterchefAndTakerCollection(ctx sdk.Context, senderAddress sdk.AccAddress, tierAddressStr string, liabilitiesInCollateral math.Int, collateralDenom string, ammPool *ammtypes.Pool) (math.Int, error) {
295+
tierAddress, err := sdk.AccAddressFromBech32(tierAddressStr)
296+
if err != nil {
297+
return math.ZeroInt(), err
298+
}
299+
_, tier := k.tierKeeper.GetMembershipTier(ctx, tierAddress)
300+
params := k.GetParams(ctx)
301+
perpetualFee := ammtypes.ApplyDiscount(params.GetBigDecPerpetualSwapFee(), tier.GetBigDecDiscount())
302+
takersFee := k.parameterKeeper.GetParams(ctx).GetBigDecTakerFees()
303+
sendToMasterchef := perpetualFee.Dec().Mul(math.LegacyNewDecFromInt(liabilitiesInCollateral)).TruncateInt()
304+
sendToTakerCollection := takersFee.Dec().Mul(math.LegacyNewDecFromInt(liabilitiesInCollateral)).TruncateInt()
305+
306+
if sendToMasterchef.IsPositive() {
307+
rebalanceTreasury := sdk.MustAccAddressFromBech32(ammPool.GetRebalanceTreasury())
308+
sendToMasterchefCoin := sdk.NewCoin(collateralDenom, sendToMasterchef)
309+
err := k.bankKeeper.SendCoins(ctx, senderAddress, rebalanceTreasury, sdk.NewCoins(sendToMasterchefCoin))
310+
if err != nil {
311+
return math.ZeroInt(), err
312+
}
313+
314+
err = k.amm.OnCollectFee(ctx, *ammPool, sdk.NewCoins(sendToMasterchefCoin))
315+
if err != nil {
316+
return math.ZeroInt(), err
317+
}
318+
}
319+
320+
if sendToTakerCollection.IsPositive() {
321+
takerAddress, err := sdk.AccAddressFromBech32(k.parameterKeeper.GetParams(ctx).TakerFeeCollectionAddress)
322+
if err != nil {
323+
return math.ZeroInt(), err
324+
}
325+
sendToTakerCollectionCoin := sdk.NewCoin(collateralDenom, sendToTakerCollection)
326+
err = k.bankKeeper.SendCoins(ctx, senderAddress, takerAddress, sdk.NewCoins(sendToTakerCollectionCoin))
327+
if err != nil {
328+
return math.ZeroInt(), err
329+
}
330+
}
331+
return sendToMasterchef.Add(sendToTakerCollection), nil
332+
}
333+
288334
// Set the perpetual hooks.
289335
func (k *Keeper) SetHooks(gh types.PerpetualHooks) *Keeper {
290336
if k.hooks != nil {

x/perpetual/keeper/open_consolidate_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func (suite *PerpetualKeeperTestSuite) TestOpenConsolidateUsingOpen() {
183183
"",
184184
&types.MTP{
185185
Collateral: math.NewInt(800),
186-
Liabilities: math.NewInt(651),
186+
Liabilities: math.NewInt(650),
187187
Custody: math.NewInt(4000),
188188
TakeProfitPrice: math.LegacyMustNewDecFromStr("1.5"),
189189
},
@@ -232,7 +232,7 @@ func (suite *PerpetualKeeperTestSuite) TestOpenConsolidateUsingOpen() {
232232
"",
233233
&types.MTP{
234234
Collateral: math.NewInt(800),
235-
Liabilities: math.NewInt(407),
235+
Liabilities: math.NewInt(406),
236236
Custody: math.NewInt(2800),
237237
TakeProfitPrice: math.LegacyMustNewDecFromStr("0.95"),
238238
},

x/perpetual/keeper/query_open_estimation_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,22 +234,22 @@ func TestOpenEstimation_Long5XAtom10Atom(t *testing.T) {
234234
require.NoError(t, err)
235235
require.Equal(t, &types.QueryOpenEstimationResponse{
236236
Position: types.Position_LONG,
237-
EffectiveLeverage: math.LegacyMustNewDecFromStr("5.080191741067260092"),
237+
EffectiveLeverage: math.LegacyMustNewDecFromStr("5.059547842376060810"),
238238
TradingAsset: ptypes.ATOM,
239239
Collateral: sdk.NewCoin(ptypes.ATOM, math.NewInt(10_000_000)),
240240
PositionSize: sdk.NewCoin(ptypes.ATOM, math.NewInt(50_000_000)),
241-
OpenPrice: math.LegacyMustNewDecFromStr("5.019731475000000000"),
241+
OpenPrice: math.LegacyMustNewDecFromStr("5.014711750000000000"),
242242
TakeProfitPrice: tradingAssetPrice.MulInt64(3),
243-
LiquidationPrice: math.LegacyMustNewDecFromStr("4.116179809500000000"),
244-
EstimatedPnl: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(399210741)),
243+
LiquidationPrice: math.LegacyMustNewDecFromStr("4.112063635000000000"),
244+
EstimatedPnl: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(399411530)),
245245
HourlyInterestRate: math.LegacyZeroDec(),
246246
AvailableLiquidity: sdk.NewCoin(ptypes.ATOM, math.NewInt(10000000000)),
247247
Slippage: math.LegacyMustNewDecFromStr("0.001502505012032000"),
248248
BorrowInterestRate: math.LegacyMustNewDecFromStr("0.000000000000000000"),
249249
FundingRate: math.LegacyMustNewDecFromStr("0.000000000000000000"),
250-
PriceImpact: math.LegacyMustNewDecFromStr("-0.003946295000000000"),
250+
PriceImpact: math.LegacyMustNewDecFromStr("-0.002942350000000000"),
251251
Custody: sdk.NewCoin(ptypes.ATOM, math.NewInt(50_000_000)),
252-
Liabilities: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(200789259)),
252+
Liabilities: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(200588470)),
253253
WeightBreakingFee: math.LegacyMustNewDecFromStr("0.001435619047176014"),
254254
SwapFees: math.LegacyMustNewDecFromStr("0.001000000000000000"),
255255
TakerFees: math.LegacyMustNewDecFromStr("0.000000000000000000"),

x/perpetual/keeper/repay.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,18 @@ import (
1010
// Repay ammPool has to be pointer because RemoveFromPoolBalance updates pool assets
1111
func (k Keeper) Repay(ctx sdk.Context, mtp *types.MTP, pool *types.Pool, ammPool *ammtypes.Pool, returnAmount math.Int, payingLiabilities math.Int, closingRatio math.LegacyDec, baseCurrency string) error {
1212
if returnAmount.IsPositive() {
13-
returnCoins := sdk.NewCoins(sdk.NewCoin(mtp.CustodyAsset, returnAmount))
14-
err := k.SendFromAmmPool(ctx, ammPool, mtp.GetAccountAddress(), returnCoins)
13+
ammPoolAddr, err := sdk.AccAddressFromBech32(ammPool.Address)
14+
if err != nil {
15+
return err
16+
}
17+
// send fees to masterchef and taker collection address
18+
totalFees, err := k.SendFeesToMasterchefAndTakerCollection(ctx, ammPoolAddr, mtp.Address, returnAmount, mtp.CustodyAsset, ammPool)
19+
if err != nil {
20+
return err
21+
}
22+
23+
returnCoins := sdk.NewCoins(sdk.NewCoin(mtp.CustodyAsset, returnAmount.Sub(totalFees)))
24+
err = k.SendFromAmmPool(ctx, ammPool, mtp.GetAccountAddress(), returnCoins)
1525
if err != nil {
1626
return err
1727
}

x/perpetual/types/expected_keepers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type AmmKeeper interface {
3737
RemoveFromPoolBalanceAndUpdateLiquidity(ctx sdk.Context, pool *ammtypes.Pool, removeShares math.Int, coins sdk.Coins) error
3838
CalculateCoinsUSDValue(ctx sdk.Context, coins sdk.Coins) osmomath.BigDec
3939
CalculateUSDValue(ctx sdk.Context, denom string, amount math.Int) osmomath.BigDec
40+
OnCollectFee(ctx sdk.Context, pool ammtypes.Pool, fee sdk.Coins) error
4041
}
4142

4243
type BankKeeper interface {

0 commit comments

Comments
 (0)