Skip to content

Commit

Permalink
enable disable TakeProfitCustodyLiabilities (#885)
Browse files Browse the repository at this point in the history
* enable disable TakeProfitCustodyLiabilities

* correcting TakeProfitBorrowFactor for short

* fixing unit test case
  • Loading branch information
avkr003 authored Oct 26, 2024
1 parent 215f6de commit 6c3996c
Show file tree
Hide file tree
Showing 17 changed files with 205 additions and 86 deletions.
1 change: 1 addition & 0 deletions proto/elys/perpetual/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@ message Params {
(gogoproto.nullable) = false
];
// No need for minimumShortTakeProfitPriceRatio as it will be 0, checked in validate message
bool enable_take_profit_custody_liabilities = 22;
}
4 changes: 2 additions & 2 deletions x/accountedpool/keeper/accounted_pool_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ func TestAccountedPoolUpdate(t *testing.T) {
},
}
// Update accounted pool
err := apk.PerpetualUpdates(ctx, ammPool, perpetualPool)
err := apk.PerpetualUpdates(ctx, ammPool, perpetualPool, false)
require.NoError(t, err)

apool, found := apk.GetAccountedPool(ctx, (uint64)(0))
require.Equal(t, found, true)
require.Equal(t, apool.PoolId, (uint64)(0))

usdcBalance := apk.GetAccountedBalance(ctx, (uint64)(0), ptypes.BaseCurrency)
require.Equal(t, usdcBalance, sdk.NewInt(1000+400-50+400-70+10-20))
require.Equal(t, usdcBalance, sdk.NewInt(1000+400-50+400-70))
atomBalance := apk.GetAccountedBalance(ctx, (uint64)(0), ptypes.ATOM)
require.Equal(t, atomBalance, sdk.NewInt(5000-50-50))
}
23 changes: 15 additions & 8 deletions x/accountedpool/keeper/hooks_perpetual.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
perpetualtypes "github.com/elys-network/elys/x/perpetual/types"
)

func (k Keeper) PerpetualUpdates(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) error {
func (k Keeper) PerpetualUpdates(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, EnableTakeProfitCustodyLiabilities bool) error {
// Get accounted pool
accountedPool, found := k.GetAccountedPool(ctx, ammPool.PoolId)
if !found {
Expand All @@ -22,7 +22,10 @@ func (k Keeper) PerpetualUpdates(ctx sdk.Context, ammPool ammtypes.Pool, perpetu
return err
}
totalLiabilities, totalCustody, totalTakeProfitCustody, totalTakeProfitLiabilities := perpetualPool.GetPerpetualPoolBalances(asset.Token.Denom)
accountedPoolAmt := ammBalance.Add(totalLiabilities).Sub(totalCustody).Add(totalTakeProfitCustody).Sub(totalTakeProfitLiabilities)
accountedPoolAmt := ammBalance.Add(totalLiabilities).Sub(totalCustody)
if EnableTakeProfitCustodyLiabilities {
accountedPoolAmt = accountedPoolAmt.Add(totalTakeProfitCustody).Sub(totalTakeProfitLiabilities)
}
accountedPool.PoolAssets[i].Token = sdk.NewCoin(asset.Token.Denom, accountedPoolAmt)

for j, nonAmmToken := range accountedPool.NonAmmPoolTokens {
Expand Down Expand Up @@ -50,14 +53,18 @@ func (k Keeper) PerpetualHooks() PerpetualHooks {
return PerpetualHooks{k}
}

func (h PerpetualHooks) AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool)
func (h PerpetualHooks) AfterParamsChange(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, EnableTakeProfitCustodyLiabilities bool) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool, EnableTakeProfitCustodyLiabilities)
}

func (h PerpetualHooks) AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool, EnableTakeProfitCustodyLiabilities)
}

func (h PerpetualHooks) AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool)
func (h PerpetualHooks) AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool, EnableTakeProfitCustodyLiabilities)
}

func (h PerpetualHooks) AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool)
func (h PerpetualHooks) AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
return h.k.PerpetualUpdates(ctx, ammPool, perpetualPool, EnableTakeProfitCustodyLiabilities)
}
13 changes: 11 additions & 2 deletions x/perpetual/keeper/calc_mtp_take_profit_borrow_rate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper

import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/x/perpetual/types"
)
Expand All @@ -20,12 +21,20 @@ func (k Keeper) CalcMTPTakeProfitBorrowFactor(mtp types.MTP) (sdk.Dec, error) {
return sdk.ZeroDec(), types.ErrZeroCustodyAmount
}

// infinite for long, 0 for short
if types.IsTakeProfitPriceInfinite(mtp) || mtp.TakeProfitPrice.IsZero() {
return sdk.OneDec(), nil
}

// takeProfitBorrowFactor = 1 - (liabilities / (custody * take profit price))
takeProfitBorrowFactor := sdk.OneDec().Sub(mtp.Liabilities.ToLegacyDec().Quo(mtp.Custody.ToLegacyDec().Mul(mtp.TakeProfitPrice)))
takeProfitBorrowFactor := math.LegacyOneDec()
if mtp.Position == types.Position_LONG {
// takeProfitBorrowFactor = 1 - (liabilities / (custody * take profit price))
takeProfitBorrowFactor = sdk.OneDec().Sub(mtp.Liabilities.ToLegacyDec().Quo(mtp.Custody.ToLegacyDec().Mul(mtp.TakeProfitPrice)))
} else {
// takeProfitBorrowFactor = 1 - ((liabilities * take profit price) / custody)
takeProfitBorrowFactor = sdk.OneDec().Sub((mtp.Liabilities.ToLegacyDec().Mul(mtp.TakeProfitPrice)).Quo(mtp.Custody.ToLegacyDec()))

}

return takeProfitBorrowFactor, nil
}
3 changes: 2 additions & 1 deletion x/perpetual/keeper/close_position.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ func (k Keeper) ClosePosition(ctx sdk.Context, msg *types.MsgClose, baseCurrency

// EpochHooks after perpetual position closed
if k.hooks != nil {
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, pool, creator)
params := k.GetParams(ctx)
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, pool, creator, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return nil, math.Int{}, err
}
Expand Down
3 changes: 2 additions & 1 deletion x/perpetual/keeper/force_close_long.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func (k Keeper) ForceCloseLong(ctx sdk.Context, mtp *types.MTP, pool *types.Pool
// EpochHooks after perpetual position closed
address := sdk.MustAccAddressFromBech32(mtp.Address)
if k.hooks != nil {
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, *pool, address)
params := k.GetParams(ctx)
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, *pool, address, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return math.Int{}, err
}
Expand Down
3 changes: 2 additions & 1 deletion x/perpetual/keeper/force_close_short.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func (k Keeper) ForceCloseShort(ctx sdk.Context, mtp *types.MTP, pool *types.Poo
address := sdk.MustAccAddressFromBech32(mtp.Address)
// EpochHooks after perpetual position closed
if k.hooks != nil {
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, *pool, address)
params := k.GetParams(ctx)
err = k.hooks.AfterPerpetualPositionClosed(ctx, ammPool, *pool, address, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return math.Int{}, err
}
Expand Down
15 changes: 15 additions & 0 deletions x/perpetual/keeper/msg_server_update_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"context"
"fmt"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -22,5 +23,19 @@ func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParam
return nil, err
}

if k.hooks != nil {
pools := k.GetAllPools(ctx)
for _, pool := range pools {
ammPool, err := k.GetAmmPool(ctx, pool.AmmPoolId)
if err != nil {
return nil, fmt.Errorf("amm pool %d not found", pool.AmmPoolId)
}

err = k.hooks.AfterParamsChange(ctx, ammPool, pool, msg.Params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return nil, err
}
}
}
return &types.MsgUpdateParamsResponse{}, nil
}
3 changes: 2 additions & 1 deletion x/perpetual/keeper/msg_server_update_take_profit_price.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ func (k msgServer) UpdateTakeProfitPrice(goCtx context.Context, msg *types.MsgUp
}

if k.hooks != nil {
err = k.hooks.AfterPerpetualPositionModified(ctx, ammPool, pool, creator)
params := k.GetParams(ctx)
err = k.hooks.AfterPerpetualPositionModified(ctx, ammPool, pool, creator, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion x/perpetual/keeper/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (k Keeper) Open(ctx sdk.Context, msg *types.MsgOpen, isBroker bool) (*types
return nil, errorsmod.Wrap(types.ErrPoolDoesNotExist, fmt.Sprintf("poolId: %d", poolId))
}

err = k.hooks.AfterPerpetualPositionOpen(ctx, ammPool, pool, creator)
err = k.hooks.AfterPerpetualPositionOpen(ctx, ammPool, pool, creator, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return nil, err
}
Expand Down
5 changes: 3 additions & 2 deletions x/perpetual/keeper/open_consolidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ func (k Keeper) OpenConsolidate(ctx sdk.Context, existingMtp *types.MTP, newMtp

creator := sdk.MustAccAddressFromBech32(msg.Creator)
if k.hooks != nil {
// The pool value aboce was sent in pointer so its updated
err = k.hooks.AfterPerpetualPositionModified(ctx, ammPool, pool, creator)
params := k.GetParams(ctx)
// The pool value above was sent in pointer so its updated
err = k.hooks.AfterPerpetualPositionModified(ctx, ammPool, pool, creator, params.EnableTakeProfitCustodyLiabilities)
if err != nil {
return nil, err
}
Expand Down
20 changes: 20 additions & 0 deletions x/perpetual/migrations/v11_migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package migrations

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/x/perpetual/types"
)

func (m Migrator) V11Migration(ctx sdk.Context) error {
m.keeper.NukeDB(ctx)
params := types.DefaultParams()
err := m.keeper.SetParams(ctx, &params)
if err != nil {
return err
}

// using previous values
params.IncrementalBorrowInterestPaymentFundAddress = "elys1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnrec2l"
params.ForceCloseFundAddress = "elys1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnrec2l"
return nil
}
4 changes: 2 additions & 2 deletions x/perpetual/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := migrations.NewMigrator(am.keeper)
err := cfg.RegisterMigration(types.ModuleName, 9, m.V10Migration)
err := cfg.RegisterMigration(types.ModuleName, 10, m.V11Migration)
if err != nil {
panic(err)
}
Expand All @@ -144,7 +144,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
}

// ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1
func (AppModule) ConsensusVersion() uint64 { return 10 }
func (AppModule) ConsensusVersion() uint64 { return 11 }

// BeginBlock contains the logic that is automatically triggered at the beginning of each block
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
Expand Down
29 changes: 20 additions & 9 deletions x/perpetual/types/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import (
)

type PerpetualHooks interface {
AfterParamsChange(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, EnableTakeProfitCustodyLiabilities bool) error
// AfterPerpetualPositionOpen is called after OpenLong or OpenShort position.
// This should be used to update pool health
AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error
AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error

// AfterPerpetualPositionModified is called after a position gets modified.
// This should be used to update pool health
AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error
AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error

// AfterPerpetualPositionClosed is called after a position gets closed.
// This should be used to update pool health
AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error
AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error
}

var _ PerpetualHooks = MultiPerpetualHooks{}
Expand All @@ -29,29 +30,39 @@ func NewMultiPerpetualHooks(hooks ...PerpetualHooks) MultiPerpetualHooks {
return hooks
}

func (h MultiPerpetualHooks) AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error {
func (h MultiPerpetualHooks) AfterParamsChange(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, EnableTakeProfitCustodyLiabilities bool) error {
for i := range h {
err := h[i].AfterPerpetualPositionOpen(ctx, ammPool, perpetualPool, sender)
err := h[i].AfterParamsChange(ctx, ammPool, perpetualPool, EnableTakeProfitCustodyLiabilities)
if err != nil {
return err
}
}
return nil
}

func (h MultiPerpetualHooks) AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error {
func (h MultiPerpetualHooks) AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
for i := range h {
err := h[i].AfterPerpetualPositionModified(ctx, ammPool, perpetualPool, sender)
err := h[i].AfterPerpetualPositionOpen(ctx, ammPool, perpetualPool, sender, EnableTakeProfitCustodyLiabilities)
if err != nil {
return err
}
}
return nil
}

func (h MultiPerpetualHooks) AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress) error {
func (h MultiPerpetualHooks) AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
for i := range h {
err := h[i].AfterPerpetualPositionClosed(ctx, ammPool, perpetualPool, sender)
err := h[i].AfterPerpetualPositionModified(ctx, ammPool, perpetualPool, sender, EnableTakeProfitCustodyLiabilities)
if err != nil {
return err
}
}
return nil
}

func (h MultiPerpetualHooks) AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool Pool, sender sdk.AccAddress, EnableTakeProfitCustodyLiabilities bool) error {
for i := range h {
err := h[i].AfterPerpetualPositionClosed(ctx, ammPool, perpetualPool, sender, EnableTakeProfitCustodyLiabilities)
if err != nil {
return err
}
Expand Down
15 changes: 8 additions & 7 deletions x/perpetual/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ func ParamKeyTable() paramtypes.KeyTable {
func NewParams() Params {
return Params{
PerpetualSwapFee: math.LegacyMustNewDecFromStr("0.001"), // 0.1%
FixedFundingRate: math.LegacyMustNewDecFromStr("0.3"), // 30%
BorrowInterestRateDecrease: math.LegacyMustNewDecFromStr("0.000000003300000000"),
BorrowInterestRateIncrease: math.LegacyMustNewDecFromStr("0.000000003300000000"),
BorrowInterestRateMax: math.LegacyMustNewDecFromStr("0.000002700000000000"),
BorrowInterestRateMin: math.LegacyMustNewDecFromStr("0.000000030000000000"),
FixedFundingRate: math.LegacyMustNewDecFromStr("0.5"), // 50%
BorrowInterestRateDecrease: math.LegacyMustNewDecFromStr("0.0003"),
BorrowInterestRateIncrease: math.LegacyMustNewDecFromStr("0.0003"),
BorrowInterestRateMax: math.LegacyMustNewDecFromStr("0.3"),
BorrowInterestRateMin: math.LegacyMustNewDecFromStr("0.1"),
ForceCloseFundAddress: authtypes.NewModuleAddress("zero").String(),
ForceCloseFundPercentage: math.LegacyOneDec(),
HealthGainFactor: math.LegacyMustNewDecFromStr("0.000000220000000000"),
Expand All @@ -63,9 +63,10 @@ func NewParams() Params {
SafetyFactor: math.LegacyMustNewDecFromStr("1.050000000000000000"), // 5%
WhitelistingEnabled: false,
MaxLimitOrder: (int64)(500),
MinimumLongTakeProfitPriceRatio: math.LegacyMustNewDecFromStr("1.1"),
MinimumLongTakeProfitPriceRatio: math.LegacyMustNewDecFromStr("1.02"),
MaximumLongTakeProfitPriceRatio: math.LegacyMustNewDecFromStr("11"),
MaximumShortTakeProfitPriceRatio: math.LegacyMustNewDecFromStr("0.9"),
MaximumShortTakeProfitPriceRatio: math.LegacyMustNewDecFromStr("0.98"),
EnableTakeProfitCustodyLiabilities: false,
}
}

Expand Down
Loading

0 comments on commit 6c3996c

Please sign in to comment.