Skip to content

Commit

Permalink
Resolve stablestake reward claim issue on masterchef
Browse files Browse the repository at this point in the history
  • Loading branch information
jelysn committed Apr 19, 2024
1 parent 5605f96 commit 8b86092
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 85 deletions.
9 changes: 6 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,6 @@ func NewElysApp(
&app.CommitmentKeeper,
app.AssetprofileKeeper,
)
stablestake := stablestake.NewAppModule(appCodec, app.StablestakeKeeper, app.AccountKeeper, app.BankKeeper)

app.CommitmentKeeper = *commitmentKeeper.SetHooks(
commitmentmodulekeeper.NewMultiCommitmentHooks(
app.IncentiveKeeper.CommitmentHooks(),
Expand Down Expand Up @@ -846,6 +844,11 @@ func NewElysApp(
)
masterchefModule := masterchefmodule.NewAppModule(appCodec, app.MasterchefKeeper, app.AccountKeeper, app.BankKeeper)

app.StablestakeKeeper = *app.StablestakeKeeper.SetHooks(stablestakekeeper.NewMultiStableStakeHooks(
app.MasterchefKeeper.StableStakeHooks(),
))
stablestakeModule := stablestake.NewAppModule(appCodec, app.StablestakeKeeper, app.AccountKeeper, app.BankKeeper)

app.IncentiveKeeper = *incentivemodulekeeper.NewKeeper(
appCodec,
keys[incentivemoduletypes.StoreKey],
Expand Down Expand Up @@ -1141,7 +1144,7 @@ func NewElysApp(
accountedPoolModule,
transferhookModule,
clockModule,
stablestake,
stablestakeModule,
leveragelpModule,
masterchefModule,
estakingModule,
Expand Down
5 changes: 4 additions & 1 deletion app/setup_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
m "github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
estakingtypes "github.com/elys-network/elys/x/estaking/types"
mastercheftypes "github.com/elys-network/elys/x/masterchef/types"
)

func SetupHandlers(app *ElysApp) {
Expand Down Expand Up @@ -56,7 +59,7 @@ func loadUpgradeStore(app *ElysApp) {

if shouldLoadUpgradeStore(app, upgradeInfo) {
storeUpgrades := storetypes.StoreUpgrades{
// Added: []string{},
Added: []string{distrtypes.StoreKey, mastercheftypes.StoreKey, estakingtypes.StoreKey},
}
// Use upgrade store loader for the initial loading of all stores when app starts,
// it checks if version == upgradeHeight and applies store upgrades before loading the stores,
Expand Down
10 changes: 10 additions & 0 deletions x/amm/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package types

import (
fmt "fmt"
"strconv"
"strings"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -11,6 +13,14 @@ func GetPoolShareDenom(poolId uint64) string {
return fmt.Sprintf("amm/pool/%d", poolId)
}

func GetPoolIdFromShareDenom(shareDenom string) (uint64, error) {
poolId, err := strconv.Atoi(strings.TrimPrefix(shareDenom, "amm/pool/"))
if err != nil {
return 0, err
}
return uint64(poolId), nil
}

// poolAssetsCoins returns all the coins corresponding to a slice of pool assets.
func poolAssetsCoins(assets []PoolAsset) sdk.Coins {
coins := sdk.Coins{}
Expand Down
23 changes: 18 additions & 5 deletions x/incentive/migrations/v11_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
ammtypes "github.com/elys-network/elys/x/amm/types"
commitmenttypes "github.com/elys-network/elys/x/commitment/types"
estakingtypes "github.com/elys-network/elys/x/estaking/types"
mastercheftypes "github.com/elys-network/elys/x/masterchef/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
stablestaketypes "github.com/elys-network/elys/x/stablestake/types"
)

func (m Migrator) V11Migration(ctx sdk.Context) error {
Expand All @@ -30,7 +32,7 @@ func (m Migrator) V11Migration(ctx sdk.Context) error {

// initiate masterchef params
m.masterchefKeeper.SetParams(ctx, mastercheftypes.NewParams(
nil, // TODO:
nil,
sdk.NewDecWithPrec(60, 2),
sdk.NewDecWithPrec(25, 2),
mastercheftypes.DexRewardsTracker{
Expand All @@ -44,7 +46,7 @@ func (m Migrator) V11Migration(ctx sdk.Context) error {
// initiate estaking module data
m.estakingKeeper.InitGenesis(ctx, estakingtypes.GenesisState{
Params: estakingtypes.Params{
StakeIncentives: nil, // TODO:
StakeIncentives: nil,
EdenCommitVal: "",
EdenbCommitVal: "",
MaxEdenRewardAprStakers: sdk.NewDecWithPrec(3, 1), // 30%
Expand Down Expand Up @@ -103,21 +105,32 @@ func (m Migrator) V11Migration(ctx sdk.Context) error {
VestingTokens: legacy.VestingTokens,
}
m.commitmentKeeper.SetCommitments(ctx, commitments)
commParams := m.commitmentKeeper.GetParams(ctx)
for _, committed := range commitments.CommittedTokens {
if committed.Denom == ptypes.Eden {
if committed.Denom == ptypes.Eden && commParams.TotalCommitted.AmountOf(ptypes.Eden).IsPositive() {
err = m.estakingKeeper.Hooks().AfterDelegationModified(ctx, addr, edenValAddr)
if err != nil {
panic(err)
}
}
if committed.Denom == ptypes.EdenB {
if committed.Denom == ptypes.EdenB && commParams.TotalCommitted.AmountOf(ptypes.EdenB).IsPositive() {
err = m.estakingKeeper.Hooks().AfterDelegationModified(ctx, addr, edenBValAddr)
if err != nil {
panic(err)
}
}
}

// Execute hook for normal amm pool deposit
poolId, err := ammtypes.GetPoolIdFromShareDenom(committed.Denom)
if err == nil {
m.masterchefKeeper.AfterDeposit(ctx, poolId, addr.String(), committed.Amount)
}

// Execute hook for stablestake deposit
if committed.Denom == stablestaketypes.GetShareDenom() {
m.masterchefKeeper.AfterDeposit(ctx, stablestaketypes.PoolId, addr.String(), committed.Amount)
}
}
}

return nil
Expand Down
114 changes: 45 additions & 69 deletions x/masterchef/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
ammtypes "github.com/elys-network/elys/x/amm/types"
Expand All @@ -21,6 +22,26 @@ func (k Keeper) EndBlocker(ctx sdk.Context) {
k.ProcessExternalRewardsDistribution(ctx)
}

func (k Keeper) GetPoolTVL(ctx sdk.Context, poolId uint64) math.LegacyDec {
if poolId == stabletypes.PoolId {
entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency)
if !found {
return math.LegacyZeroDec()
}
baseCurrency := entry.Denom
return k.stableKeeper.TVL(ctx, k.oracleKeeper, baseCurrency)
}
ammPool, found := k.amm.GetPool(ctx, poolId)
if found {
tvl, err := ammPool.TVL(ctx, k.oracleKeeper)
if err != nil {
return math.LegacyZeroDec()
}
return tvl
}
return math.LegacyZeroDec()
}

func (k Keeper) ProcessExternalRewardsDistribution(ctx sdk.Context) {
canDistribute := k.CanDistributeLPRewards(ctx)
if !canDistribute {
Expand Down Expand Up @@ -55,25 +76,21 @@ func (k Keeper) ProcessExternalRewardsDistribution(ctx sdk.Context) {
k.SetPool(ctx, pool)
}

ammPool, found := k.amm.GetPool(ctx, pool.PoolId)
if found {
tvl, err := ammPool.TVL(ctx, k.oracleKeeper)
if err == nil {
yearlyIncentiveRewardsTotal := externalIncentive.AmountPerBlock.
Mul(lpIncentive.TotalBlocksPerYear).
Quo(pool.NumBlocks)

entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency)
if found {
baseCurrency := entry.Denom
pool.ExternalIncentiveApr = sdk.NewDecFromInt(yearlyIncentiveRewardsTotal).
Mul(k.amm.GetTokenPrice(ctx, externalIncentive.RewardDenom, baseCurrency)).
Quo(tvl)
k.SetPool(ctx, pool)
}
tvl := k.GetPoolTVL(ctx, pool.PoolId)
if tvl.IsPositive() {
yearlyIncentiveRewardsTotal := externalIncentive.AmountPerBlock.
Mul(lpIncentive.TotalBlocksPerYear).
Quo(pool.NumBlocks)

entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency)
if found {
baseCurrency := entry.Denom
pool.ExternalIncentiveApr = sdk.NewDecFromInt(yearlyIncentiveRewardsTotal).
Mul(k.amm.GetTokenPrice(ctx, externalIncentive.RewardDenom, baseCurrency)).
Quo(tvl)
k.SetPool(ctx, pool)
}
}

}

if curBlockHeight.Uint64() == externalIncentive.ToBlock {
Expand Down Expand Up @@ -229,31 +246,13 @@ func (k Keeper) UpdateLPRewards(ctx sdk.Context) error {
return errorsmod.Wrap(types.ErrNoInflationaryParams, "invalid eden price")
}

stableStakePoolId := uint64(stabletypes.PoolId)
// Distribute Eden / USDC Rewards
for _, pool := range k.GetAllPools(ctx) {
var proxyTVL, tvl sdk.Dec
var err error
if pool.PoolId == stableStakePoolId {
tvl = k.stableKeeper.TVL(ctx, k.oracleKeeper, baseCurrency)
proxyTVL = tvl.Mul(pool.Multiplier)
} else {
ammPool, found := k.amm.GetPool(ctx, pool.PoolId)
if !found {
continue
}

// ------------ New Eden calculation -------------------
// -----------------------------------------------------
// newEdenAllocated = 80 / ( 80 + 90 + 200 + 0) * 100
// Pool share = 80
// edenAmountLp = 100
tvl, err = ammPool.TVL(ctx, k.oracleKeeper)
if err != nil {
continue
}
// Calculate Proxy TVL share considering multiplier
proxyTVL = tvl.Mul(pool.Multiplier)
tvl := k.GetPoolTVL(ctx, pool.PoolId)
proxyTVL := tvl.Mul(pool.Multiplier)
if proxyTVL.IsZero() {
continue
}

poolShare := sdk.ZeroDec()
Expand Down Expand Up @@ -487,37 +486,14 @@ func (k Keeper) CollectDEXRevenue(ctx sdk.Context) (sdk.Coins, sdk.DecCoins) {
func (k Keeper) CalculateProxyTVL(ctx sdk.Context, baseCurrency string) sdk.Dec {
multipliedShareSum := sdk.ZeroDec()
stableStakePoolId := uint64(stabletypes.PoolId)
_, found := k.GetPool(ctx, stableStakePoolId)
// Ensure stablestakePoolParams exist
if !found {
k.InitStableStakePoolParams(ctx, stableStakePoolId)
}
for _, pool := range k.GetAllPools(ctx) {
if pool.PoolId == stableStakePoolId {
// Get pool info from incentive param
poolInfo, found := k.GetPool(ctx, stableStakePoolId)
if !found {
k.InitStableStakePoolParams(ctx, stableStakePoolId)
poolInfo, _ = k.GetPool(ctx, stableStakePoolId)
}
tvl := k.stableKeeper.TVL(ctx, k.oracleKeeper, baseCurrency)
proxyTVL := tvl.Mul(poolInfo.Multiplier)
multipliedShareSum = multipliedShareSum.Add(proxyTVL)
continue
}

ammPool, found := k.amm.GetPool(ctx, pool.PoolId)
if !found {
continue
}

tvl, err := ammPool.TVL(ctx, k.oracleKeeper)
if err != nil {
continue
}

// Get pool info from incentive param
poolInfo, found := k.GetPool(ctx, ammPool.GetPoolId())
if !found {
continue
}

proxyTVL := tvl.Mul(poolInfo.Multiplier)
tvl := k.GetPoolTVL(ctx, pool.PoolId)
proxyTVL := tvl.Mul(pool.Multiplier)

// Calculate total pool share by TVL and multiplier
multipliedShareSum = multipliedShareSum.Add(proxyTVL)
Expand Down
2 changes: 1 addition & 1 deletion x/masterchef/keeper/apr_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func (k Keeper) CalculatePoolAprs(ctx sdk.Context, ids []uint64) []types.PoolApr {
if len(ids) == 0 {
pools := k.amm.GetAllPool(ctx)
pools := k.GetAllPools(ctx)
for _, pool := range pools {
ids = append(ids, pool.PoolId)
}
Expand Down
20 changes: 17 additions & 3 deletions x/masterchef/keeper/hooks_masterchef.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
ammtypes "github.com/elys-network/elys/x/amm/types"
"github.com/elys-network/elys/x/masterchef/types"
stablestaketypes "github.com/elys-network/elys/x/stablestake/types"
)

func (k Keeper) GetPoolTotalSupply(ctx sdk.Context, poolId uint64) sdk.Int {
if poolId == stablestaketypes.PoolId {
params := k.cmk.GetParams(ctx)
return params.TotalCommitted.AmountOf(stablestaketypes.GetShareDenom())
}

pool, found := k.amm.GetPool(ctx, poolId)
if !found {
return sdk.ZeroInt()
Expand All @@ -18,8 +24,12 @@ func (k Keeper) GetPoolTotalSupply(ctx sdk.Context, poolId uint64) sdk.Int {

func (k Keeper) GetPoolBalance(ctx sdk.Context, poolId uint64, user string) sdk.Int {
commitments := k.cmk.GetCommitments(ctx, user)
shareDenom := stablestaketypes.GetShareDenom()
if poolId != stablestaketypes.PoolId {
shareDenom = ammtypes.GetPoolShareDenom(poolId)
}

return commitments.GetCommittedAmountForDenom(ammtypes.GetPoolShareDenom(poolId))
return commitments.GetCommittedAmountForDenom(shareDenom)
}

func (k Keeper) UpdateAccPerShare(ctx sdk.Context, poolId uint64, rewardDenom string, amount sdk.Int) {
Expand All @@ -34,11 +44,15 @@ func (k Keeper) UpdateAccPerShare(ctx sdk.Context, poolId uint64, rewardDenom st
}
}

supply := k.GetPoolTotalSupply(ctx, poolId)
if supply.IsZero() {
return
}
poolRewardInfo.PoolAccRewardPerShare = poolRewardInfo.PoolAccRewardPerShare.Add(
math.LegacyNewDecFromInt(amount.Mul(ammtypes.OneShare)).Quo(math.LegacyNewDecFromInt(k.GetPoolTotalSupply(ctx, poolId))),
math.LegacyNewDecFromInt(amount.Mul(ammtypes.OneShare)).
Quo(math.LegacyNewDecFromInt(supply)),
)
poolRewardInfo.LastUpdatedBlock = uint64(ctx.BlockHeight())

k.SetPoolRewardInfo(ctx, poolRewardInfo)
}

Expand Down
29 changes: 29 additions & 0 deletions x/masterchef/keeper/hooks_stablestake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package keeper

import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
stablestaketypes "github.com/elys-network/elys/x/stablestake/types"
)

// Hooks wrapper struct for incentive keeper
type StableStakeHooks struct {
k Keeper
}

var _ stablestaketypes.StableStakeHooks = StableStakeHooks{}

// Return the wrapper struct
func (k Keeper) StableStakeHooks() StableStakeHooks {
return StableStakeHooks{k}
}

func (h StableStakeHooks) AfterBond(ctx sdk.Context, sender string, shareAmount math.Int) error {
h.k.AfterDeposit(ctx, stablestaketypes.PoolId, sender, shareAmount)
return nil
}

func (h StableStakeHooks) AfterUnbond(ctx sdk.Context, sender string, shareAmount math.Int) error {
h.k.AfterWithdraw(ctx, stablestaketypes.PoolId, sender, shareAmount)
return nil
}
2 changes: 1 addition & 1 deletion x/masterchef/keeper/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (k Keeper) UserRewardInfo(goCtx context.Context, req *types.QueryUserReward

userRewardInfo, found := k.GetUserRewardInfo(ctx, req.User, req.PoolId, req.RewardDenom)
if !found {
return nil, status.Error(codes.InvalidArgument, "invalid pool id")
return nil, status.Error(codes.InvalidArgument, "invalid pool id or denom")
}

return &types.QueryUserRewardInfoResponse{UserRewardInfo: userRewardInfo}, nil
Expand Down
1 change: 1 addition & 0 deletions x/masterchef/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type CommitmentKeeper interface {
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
BurnEdenBoost(ctx sdk.Context, creator string, denom string, amount math.Int) (ctypes.Commitments, error)
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
GetParams(sdk.Context) ctypes.Params
}

// Staking keeper
Expand Down
Loading

0 comments on commit 8b86092

Please sign in to comment.