Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Perpetual/Masterchef]: Add perpetual fee collection function in Masterchef #827

Merged
merged 5 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,18 @@
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

app.PerpetualKeeper = *perpetualmodulekeeper.NewKeeper(
appCodec,
keys[perpetualmoduletypes.StoreKey],
keys[perpetualmoduletypes.MemStoreKey],
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
&app.AmmKeeper,
app.BankKeeper,
app.OracleKeeper,
app.AssetprofileKeeper,
&app.ParameterKeeper,
)

Check warning on line 840 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L830-L840

Added lines #L830 - L840 were not covered by tests

app.MasterchefKeeper = *masterchefmodulekeeper.NewKeeper(
appCodec,
keys[masterchefmoduletypes.StoreKey],
Expand All @@ -842,6 +854,7 @@
app.TokenomicsKeeper,
app.AccountKeeper,
app.BankKeeper,
app.PerpetualKeeper,

Check warning on line 857 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L857

Added line #L857 was not covered by tests
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
masterchefModule := masterchefmodule.NewAppModule(appCodec, app.MasterchefKeeper, app.AccountKeeper, app.BankKeeper)
Expand Down Expand Up @@ -988,18 +1001,6 @@
}
govKeeper.SetLegacyRouter(govRouter)

app.PerpetualKeeper = *perpetualmodulekeeper.NewKeeper(
appCodec,
keys[perpetualmoduletypes.StoreKey],
keys[perpetualmoduletypes.MemStoreKey],
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
&app.AmmKeeper,
app.BankKeeper,
app.OracleKeeper,
app.AssetprofileKeeper,
&app.ParameterKeeper,
)

app.ClockKeeper = *clockmodulekeeper.NewKeeper(
keys[clockmoduletypes.StoreKey],
appCodec,
Expand Down
1 change: 1 addition & 0 deletions testutil/keeper/masterchef.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func MasterchefKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
nil,
nil,
nil,
nil,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

Expand Down
58 changes: 51 additions & 7 deletions x/masterchef/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@

// Collect Gas fees + swap fees
gasFeesForLpsDec := k.CollectGasFees(ctx, baseCurrency)
gasFeesForLpsDec = gasFeesForLpsDec.Add(k.CollectPerpRevenue(ctx, baseCurrency)...)
_, _, rewardsPerPool := k.CollectDEXRevenue(ctx)

// USDC amount in sdk.Dec type
Expand Down Expand Up @@ -292,12 +293,11 @@

// Move gas fees collected to dex revenue wallet
// Convert it into USDC
func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string) sdk.Coins {
func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, address sdk.AccAddress) sdk.Coins {
// fetch and clear the collected fees for distribution, since this is
// called in BeginBlock, collected fees will be from the previous block
// (and distributed to the previous proposer)
feeCollector := k.authKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName)
feesCollected := k.bankKeeper.GetAllBalances(ctx, feeCollector.GetAddress())
feesCollected := k.bankKeeper.GetAllBalances(ctx, address)

// Total Swapped coin
totalSwappedCoins := sdk.Coins{}
Expand Down Expand Up @@ -331,7 +331,7 @@
// Settles balances between the tx sender and the pool to match the swap that was executed earlier.
// Also emits a swap event and updates related liquidity metrics.
cacheCtx, write := ctx.CacheContext()
_, err = k.amm.UpdatePoolForSwap(cacheCtx, pool, feeCollector.GetAddress(), feeCollector.GetAddress(), tokenIn, tokenOutCoin, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
_, err = k.amm.UpdatePoolForSwap(cacheCtx, pool, address, address, tokenIn, tokenOutCoin, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
if err != nil {
continue
}
Expand All @@ -349,9 +349,9 @@

func (k Keeper) CollectGasFees(ctx sdk.Context, baseCurrency string) sdk.DecCoins {
params := k.GetParams(ctx)

feeCollector := k.authKeeper.GetModuleAccount(ctx, authtypes.FeeCollectorName)
// Calculate each portion of Gas fees collected - stakers, LPs
fees := k.ConvertGasFeesToUsdc(ctx, baseCurrency)
fees := k.ConvertGasFeesToUsdc(ctx, baseCurrency, feeCollector.GetAddress())
gasFeeCollectedDec := sdk.NewDecCoinsFromCoins(fees...)

gasFeesForLpsDec := gasFeeCollectedDec.MulDecTruncate(params.RewardPortionForLps)
Expand Down Expand Up @@ -387,12 +387,56 @@
return gasFeesForLpsDec
}

// Collect all Perpetual module revenues to Perpetual revenue wallet,
// transfer collected fees from perpetual moduleto the distribution module account
// Coins are not in usdc, so convert them to usdc
func (k Keeper) CollectPerpRevenue(ctx sdk.Context, baseCurrency string) sdk.DecCoins {
fundAddr := k.perpetualKeeper.GetIncrementalBorrowInterestPaymentFundAddress(ctx)
params := k.GetParams(ctx)
// Transfer revenue to a single wallet of Perpetual revenue wallet.
fees := k.ConvertGasFeesToUsdc(ctx, baseCurrency, fundAddr)
// Calculate each portion of Gas fees collected - stakers, LPs
perpFeeCollectedDec := sdk.NewDecCoinsFromCoins(fees...)

perpFeesForLpsDec := perpFeeCollectedDec.MulDecTruncate(params.RewardPortionForLps)
perpFeesForStakersDec := perpFeeCollectedDec.MulDecTruncate(params.RewardPortionForStakers)
perpFeesForProtocolDec := perpFeeCollectedDec.Sub(perpFeesForLpsDec).Sub(perpFeesForStakersDec)

k.AddFeeInfo(ctx, perpFeesForLpsDec.AmountOf(baseCurrency), perpFeesForStakersDec.AmountOf(baseCurrency), perpFeesForProtocolDec.AmountOf(baseCurrency), true)

lpsGasFeeCoins, _ := perpFeesForLpsDec.TruncateDecimal()
protocolGasFeeCoins, _ := perpFeesForProtocolDec.TruncateDecimal()

// Send coins from fund address to masterchef
if lpsGasFeeCoins.IsAllPositive() {
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, fundAddr, types.ModuleName, lpsGasFeeCoins)
if err != nil {
panic(err)

Check warning on line 414 in x/masterchef/keeper/abci.go

View check run for this annotation

Codecov / codecov/patch

x/masterchef/keeper/abci.go#L414

Added line #L414 was not covered by tests
}
}

// Send coins to protocol revenue address
if protocolGasFeeCoins.IsAllPositive() {
protocolRevenueAddress, err := sdk.AccAddressFromBech32(params.ProtocolRevenueAddress)
if err != nil {
// Handle the error by skipping the fee distribution
ctx.Logger().Error("Invalid protocol revenue address", "error", err)
return perpFeesForLpsDec

Check warning on line 424 in x/masterchef/keeper/abci.go

View check run for this annotation

Codecov / codecov/patch

x/masterchef/keeper/abci.go#L423-L424

Added lines #L423 - L424 were not covered by tests
}
err = k.bankKeeper.SendCoins(ctx, fundAddr, protocolRevenueAddress, protocolGasFeeCoins)
if err != nil {
panic(err)

Check warning on line 428 in x/masterchef/keeper/abci.go

View check run for this annotation

Codecov / codecov/patch

x/masterchef/keeper/abci.go#L428

Added line #L428 was not covered by tests
}
}
return perpFeesForLpsDec
}

// Collect all DEX revenues to DEX revenue wallet,
// while tracking the 60% of it for LPs reward distribution
// transfer collected fees from different wallets(liquidity pool, perpetual module etc) to the distribution module account
// Assume this is already in USDC.
func (k Keeper) CollectDEXRevenue(ctx sdk.Context) (sdk.Coins, sdk.DecCoins, map[uint64]sdk.Dec) {
// Total colllected revenue amount
// Total collected revenue amount
amountTotalCollected := sdk.Coins{}
amountLPsCollected := sdk.DecCoins{}
rewardsPerPool := make(map[uint64]sdk.Dec)
Expand Down
28 changes: 28 additions & 0 deletions x/masterchef/keeper/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
ammtypes "github.com/elys-network/elys/x/amm/types"
ctypes "github.com/elys-network/elys/x/commitment/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
perptypes "github.com/elys-network/elys/x/perpetual/types"

tokenomicskeeper "github.com/elys-network/elys/x/tokenomics/keeper"
tokenomicstypes "github.com/elys-network/elys/x/tokenomics/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -317,3 +319,29 @@ func TestCollectDEXRevenue(t *testing.T) {
// It should be 1950=3000*0.65 usdc
require.Equal(t, rewardForLpsAmt, sdk.DecCoins{sdk.NewDecCoin(ptypes.BaseCurrency, sdk.NewInt(1800))})
}

func TestCollectPerpRevenue(t *testing.T) {
app := simapp.InitElysTestApp(true)
ctx := app.BaseApp.NewContext(true, tmproto.Header{})

mk, perp := app.MasterchefKeeper, app.PerpetualKeeper

// Generate 1 random account
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000))

perpParams := perptypes.DefaultParams()
perpParams.IncrementalBorrowInterestPaymentFundAddress = addr[0].String()
perp.SetParams(ctx, &perpParams)

// Fill in perpetual revenue wallet
usdcRevToken2 := sdk.NewCoins(sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(3000)))
err := app.BankKeeper.MintCoins(ctx, ammtypes.ModuleName, usdcRevToken2)
require.NoError(t, err)
err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, ammtypes.ModuleName, addr[0], usdcRevToken2)
require.NoError(t, err)

fees := mk.CollectPerpRevenue(ctx, ptypes.BaseCurrency)

// It should be 1950=3000*0.65 usdc
require.Equal(t, fees, sdk.DecCoins{sdk.NewDecCoin(ptypes.BaseCurrency, sdk.NewInt(1800))})
}
3 changes: 3 additions & 0 deletions x/masterchef/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type (
tokenomicsKeeper types.TokenomicsKeeper
authKeeper types.AccountKeeper
bankKeeper types.BankKeeper
perpetualKeeper types.PeperpetualKeeper

authority string // gov module addresss
}
Expand All @@ -49,6 +50,7 @@ func NewKeeper(
tokenomicsKeeper types.TokenomicsKeeper,
ak types.AccountKeeper,
bk types.BankKeeper,
perpetualKeeper types.PeperpetualKeeper,
authority string,
) *Keeper {
return &Keeper{
Expand All @@ -66,6 +68,7 @@ func NewKeeper(
tokenomicsKeeper: tokenomicsKeeper,
authKeeper: ak,
bankKeeper: bk,
perpetualKeeper: perpetualKeeper,
authority: authority,
}
}
Expand Down
8 changes: 8 additions & 0 deletions x/masterchef/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
ctypes "github.com/elys-network/elys/x/commitment/types"
oracletypes "github.com/elys-network/elys/x/oracle/types"
parametertypes "github.com/elys-network/elys/x/parameter/types"
perpetualtypes "github.com/elys-network/elys/x/perpetual/types"

stabletypes "github.com/elys-network/elys/x/stablestake/types"
tokenomictypes "github.com/elys-network/elys/x/tokenomics/types"
)
Expand Down Expand Up @@ -62,6 +64,7 @@ type BankKeeper interface {
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error

BlockedAddr(addr sdk.AccAddress) bool
BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error
Expand Down Expand Up @@ -140,3 +143,8 @@ type TokenomicsKeeper interface {
type ParameterKeeper interface {
GetParams(ctx sdk.Context) (params parametertypes.Params)
}

type PeperpetualKeeper interface {
GetParams(ctx sdk.Context) (params perpetualtypes.Params)
GetIncrementalBorrowInterestPaymentFundAddress(ctx sdk.Context) sdk.AccAddress
}
2 changes: 1 addition & 1 deletion x/perpetual/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"fmt"

"github.com/cometbft/cometbft/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
Expand Down Expand Up @@ -503,7 +504,6 @@ func (k Keeper) TakeFundPayment(ctx sdk.Context, returnAmount math.Int, returnAs
return sdk.ZeroInt(), err
}
err = k.bankKeeper.SendCoins(ctx, ammPoolAddr, fundAddr, takeCoins)
//err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, ammPool.Address, fundAddr, takeCoins)
if err != nil {
return sdk.ZeroInt(), err
}
Expand Down
Loading