From 72568d9f11ee3544ccd166c7efa18ca19cf4207a Mon Sep 17 00:00:00 2001 From: Adarsh Kumar Date: Tue, 3 Dec 2024 10:12:21 +0530 Subject: [PATCH 1/2] Fix Join amm pool method (#1004) * fix amm join pool * add comment in test * add migration --------- Co-authored-by: Amit Yadav --- x/amm/keeper/keeper_join_pool_no_swap.go | 16 +++++------ x/amm/keeper/pool.go | 28 +++++++++++++++++++ x/amm/keeper/query_join_pool_estimation.go | 8 +++--- .../keeper/query_join_pool_estimation_test.go | 3 +- x/amm/migrations/v9_migration.go | 9 ++++++ x/amm/module.go | 8 ++---- x/amm/types/pool_join_pool.go | 28 +++++++++---------- 7 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 x/amm/migrations/v9_migration.go diff --git a/x/amm/keeper/keeper_join_pool_no_swap.go b/x/amm/keeper/keeper_join_pool_no_swap.go index 145b70b82..37cbd0878 100644 --- a/x/amm/keeper/keeper_join_pool_no_swap.go +++ b/x/amm/keeper/keeper_join_pool_no_swap.go @@ -67,7 +67,7 @@ func (k Keeper) JoinPoolNoSwap( } params := k.GetParams(ctx) snapshot := k.GetAccountedPoolSnapshotOrSet(ctx, pool) - sharesOut, _, weightBalanceBonus, err := pool.JoinPool(ctx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokensIn, params) + tokensJoined, sharesOut, _, weightBalanceBonus, err := pool.JoinPool(ctx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokensIn, params) if err != nil { return nil, sdkmath.ZeroInt(), err } @@ -78,23 +78,23 @@ func (k Keeper) JoinPoolNoSwap( shareOutAmount, sharesOut)) } - err = k.ApplyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokensIn, weightBalanceBonus) + err = k.ApplyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokensJoined, weightBalanceBonus) if err != nil { return nil, sdkmath.Int{}, err } // Increase liquidity amount - err = k.RecordTotalLiquidityIncrease(ctx, tokensIn) + err = k.RecordTotalLiquidityIncrease(ctx, tokensJoined) if err != nil { return nil, sdkmath.Int{}, err } - return tokensIn, sharesOut, err + return tokensJoined, sharesOut, err } params := k.GetParams(ctx) // on oracle pool, full tokenInMaxs are used regardless shareOutAmount snapshot := k.GetAccountedPoolSnapshotOrSet(ctx, pool) - sharesOut, _, weightBalanceBonus, err := pool.JoinPool(ctx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokenInMaxs, params) + tokensJoined, sharesOut, _, weightBalanceBonus, err := pool.JoinPool(ctx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokenInMaxs, params) if err != nil { return nil, sdkmath.ZeroInt(), err } @@ -105,16 +105,16 @@ func (k Keeper) JoinPoolNoSwap( shareOutAmount, sharesOut)) } - err = k.ApplyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokenInMaxs, weightBalanceBonus) + err = k.ApplyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokensJoined, weightBalanceBonus) if err != nil { return nil, sdkmath.Int{}, err } // Increase liquidity amount - err = k.RecordTotalLiquidityIncrease(ctx, tokenInMaxs) + err = k.RecordTotalLiquidityIncrease(ctx, tokensJoined) if err != nil { return nil, sdkmath.Int{}, err } - return tokenInMaxs, sharesOut, err + return tokensJoined, sharesOut, err } diff --git a/x/amm/keeper/pool.go b/x/amm/keeper/pool.go index 6f9f96aa1..7f22a4e44 100644 --- a/x/amm/keeper/pool.go +++ b/x/amm/keeper/pool.go @@ -227,3 +227,31 @@ func (k Keeper) RemoveFromPoolBalance(ctx sdk.Context, pool *types.Pool, removeS k.SetPool(ctx, *pool) return k.RecordTotalLiquidityDecrease(ctx, coins) } + +// For migration only, fixes for amm mismatch has been added, to verify if the fix is working we +// will match the balances and do operations after +func (k Keeper) MatchAmmBalances(ctx sdk.Context) error { + // Match pool balances and assets structure balances + pools := k.GetAllPool(ctx) + for _, pool := range pools { + if !pool.PoolParams.UseOracle { + balances := k.bankKeeper.GetAllBalances(ctx, sdk.MustAccAddressFromBech32(pool.GetAddress())) + for _, asset := range pool.PoolAssets { + for _, balance := range balances { + if asset.Token.Denom == balance.Denom { + if asset.Token.Amount.GT(balance.Amount) { + k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(asset.Token.Denom, asset.Token.Amount.Sub(balance.Amount)))) + k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, sdk.MustAccAddressFromBech32(pool.GetAddress()), sdk.NewCoins(sdk.NewCoin(asset.Token.Denom, asset.Token.Amount.Sub(balance.Amount)))) + } + + if asset.Token.Amount.LT(balance.Amount) { + k.bankKeeper.SendCoinsFromAccountToModule(ctx, sdk.MustAccAddressFromBech32(pool.GetAddress()), types.ModuleName, sdk.NewCoins(sdk.NewCoin(asset.Token.Denom, balance.Amount.Sub(asset.Token.Amount)))) + k.bankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(asset.Token.Denom, balance.Amount.Sub(asset.Token.Amount)))) + } + } + } + } + } + } + return nil +} diff --git a/x/amm/keeper/query_join_pool_estimation.go b/x/amm/keeper/query_join_pool_estimation.go index 6627d7642..196ee5e8e 100644 --- a/x/amm/keeper/query_join_pool_estimation.go +++ b/x/amm/keeper/query_join_pool_estimation.go @@ -53,22 +53,22 @@ func (k Keeper) JoinPoolEst( params := k.GetParams(ctx) snapshot := k.GetAccountedPoolSnapshotOrSet(ctx, pool) cacheCtx, _ := ctx.CacheContext() - sharesOut, slippage, weightBalanceBonus, err = pool.JoinPool(cacheCtx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokensIn, params) + tokensJoined, sharesOut, slippage, weightBalanceBonus, err := pool.JoinPool(cacheCtx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokensIn, params) if err != nil { return nil, math.ZeroInt(), math.LegacyZeroDec(), math.LegacyZeroDec(), err } - return tokensIn, sharesOut, slippage, weightBalanceBonus, err + return tokensJoined, sharesOut, slippage, weightBalanceBonus, err } params := k.GetParams(ctx) // on oracle pool, full tokenInMaxs are used regardless shareOutAmount snapshot := k.GetAccountedPoolSnapshotOrSet(ctx, pool) cacheCtx, _ := ctx.CacheContext() - sharesOut, slippage, weightBalanceBonus, err = pool.JoinPool(cacheCtx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokenInMaxs, params) + tokensJoined, sharesOut, slippage, weightBalanceBonus, err := pool.JoinPool(cacheCtx, &snapshot, k.oracleKeeper, k.accountedPoolKeeper, tokenInMaxs, params) if err != nil { return nil, math.ZeroInt(), math.LegacyZeroDec(), math.LegacyZeroDec(), err } - return tokenInMaxs, sharesOut, slippage, weightBalanceBonus, err + return tokensJoined, sharesOut, slippage, weightBalanceBonus, err } diff --git a/x/amm/keeper/query_join_pool_estimation_test.go b/x/amm/keeper/query_join_pool_estimation_test.go index 13de955db..23268d92b 100644 --- a/x/amm/keeper/query_join_pool_estimation_test.go +++ b/x/amm/keeper/query_join_pool_estimation_test.go @@ -32,6 +32,7 @@ func TestJoinPoolEstimation(t *testing.T) { AmountsIn: sdk.NewCoins(sdk.NewInt64Coin("denom1", 100), sdk.NewInt64Coin("denom2", 200)), }) require.NoError(t, err) - require.Equal(t, sdk.Coins(resp.AmountsIn).String(), "100denom1,200denom2") + // Pool ratio is 1:1, so join pool will accept only 100denom1,100denom2 + require.Equal(t, sdk.Coins(resp.AmountsIn).String(), "100denom1,100denom2") require.Equal(t, resp.ShareAmountOut.String(), "100000000000000000amm/pool/1") } diff --git a/x/amm/migrations/v9_migration.go b/x/amm/migrations/v9_migration.go new file mode 100644 index 000000000..0511f9250 --- /dev/null +++ b/x/amm/migrations/v9_migration.go @@ -0,0 +1,9 @@ +package migrations + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (m Migrator) V9Migration(ctx sdk.Context) error { + return m.keeper.MatchAmmBalances(ctx) +} diff --git a/x/amm/module.go b/x/amm/module.go index b0e06c131..e184f60b7 100644 --- a/x/amm/module.go +++ b/x/amm/module.go @@ -132,11 +132,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, 6, m.V7Migration) - if err != nil { - panic(err) - } - err = cfg.RegisterMigration(types.ModuleName, 7, m.V8Migration) + err := cfg.RegisterMigration(types.ModuleName, 8, m.V9Migration) if err != nil { panic(err) } @@ -163,7 +159,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 8 } +func (AppModule) ConsensusVersion() uint64 { return 9 } // BeginBlock contains the logic that is automatically triggered at the beginning of each block func (am AppModule) BeginBlock(_ context.Context) error { diff --git a/x/amm/types/pool_join_pool.go b/x/amm/types/pool_join_pool.go index e726426b8..2faf50400 100644 --- a/x/amm/types/pool_join_pool.go +++ b/x/amm/types/pool_join_pool.go @@ -121,20 +121,20 @@ func (p *Pool) JoinPool( oracleKeeper OracleKeeper, accountedPoolKeeper AccountedPoolKeeper, tokensIn sdk.Coins, params Params, -) (numShares sdkmath.Int, slippage sdkmath.LegacyDec, weightBalanceBonus sdkmath.LegacyDec, err error) { +) (tokensJoined sdk.Coins, numShares sdkmath.Int, slippage sdkmath.LegacyDec, weightBalanceBonus sdkmath.LegacyDec, err error) { // if it's not single sided liquidity, add at pool ratio if len(tokensIn) != 1 { numShares, tokensJoined, err := p.CalcJoinPoolNoSwapShares(tokensIn) if err != nil { - return sdkmath.Int{}, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.Int{}, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } // update pool with the calculated share and liquidity needed to join pool err = p.IncreaseLiquidity(numShares, tokensJoined) if err != nil { - return sdkmath.Int{}, sdkmath.LegacyDec{}, sdkmath.LegacyDec{}, err + return sdk.NewCoins(), sdkmath.Int{}, sdkmath.LegacyDec{}, sdkmath.LegacyDec{}, err } - return numShares, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), nil + return tokensJoined, numShares, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), nil } if !p.PoolParams.UseOracle { @@ -152,37 +152,37 @@ func (p *Pool) JoinPool( numShares, tokensJoined, err := p.CalcSingleAssetJoinPoolShares(tokensIn) if err != nil { - return sdkmath.Int{}, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.Int{}, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } // update pool with the calculated share and liquidity needed to join pool err = p.IncreaseLiquidity(numShares, tokensJoined) if err != nil { - return sdkmath.Int{}, sdkmath.LegacyDec{}, sdkmath.LegacyDec{}, err + return sdk.NewCoins(), sdkmath.Int{}, sdkmath.LegacyDec{}, sdkmath.LegacyDec{}, err } - return numShares, totalSlippage, sdkmath.LegacyZeroDec(), nil + return tokensJoined, numShares, totalSlippage, sdkmath.LegacyZeroDec(), nil } joinValueWithoutSlippage, err := p.CalcJoinValueWithoutSlippage(ctx, oracleKeeper, accountedPoolKeeper, tokensIn) if err != nil { - return sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } accountedAssets := p.GetAccountedBalance(ctx, accountedPoolKeeper, p.PoolAssets) initialWeightDistance := p.WeightDistanceFromTarget(ctx, oracleKeeper, accountedAssets) tvl, err := p.TVL(ctx, oracleKeeper, accountedPoolKeeper) if err != nil { - return sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } // Ensure tvl is not zero to avoid division by zero if tvl.IsZero() { - return sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), ErrAmountTooLow + return sdk.NewCoins(), sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), ErrAmountTooLow } - newAssetPools, err := p.NewPoolAssetsAfterSwap(ctx, tokensIn, sdk.Coins{}, accountedAssets) + newAssetPools, err := p.NewPoolAssetsAfterSwap(ctx, tokensIn, sdk.NewCoins(), accountedAssets) if err != nil { - return sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } weightDistance := p.WeightDistanceFromTarget(ctx, oracleKeeper, newAssetPools) distanceDiff := weightDistance.Sub(initialWeightDistance) @@ -216,9 +216,9 @@ func (p *Pool) JoinPool( numShares = numSharesDec.RoundInt() err = p.IncreaseLiquidity(numShares, tokensIn) if err != nil { - return sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err + return sdk.NewCoins(), sdkmath.ZeroInt(), sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), err } // No slippage in oracle pool due to 1 hr lock - return numShares, sdkmath.LegacyZeroDec(), weightBalanceBonus, nil + return tokensIn, numShares, sdkmath.LegacyZeroDec(), weightBalanceBonus, nil } From 7b89d6a982390d7d1a7788ea3e5b7100b954c0bf Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Tue, 3 Dec 2024 10:59:56 +0530 Subject: [PATCH 2/2] Masterchef improvements and fixes (#1014) * handle masterchef erros * improvements * handle * add event * remove redundant code * fix * imp * rename --- x/amm/types/calc_out_amt_given_in.go | 5 +- x/amm/types/errors.go | 5 +- x/amm/types/swap_out_amt_given_in_test.go | 2 +- ...quid_tokens.go => commit_liquid_tokens.go} | 0 ...s_test.go => commit_liquid_tokens_test.go} | 0 x/masterchef/keeper/abci.go | 46 ++++++++++--- x/masterchef/keeper/external_incentive.go | 34 --------- x/masterchef/keeper/hooks_masterchef.go | 24 +++---- x/masterchef/keeper/hooks_user_actions.go | 3 +- x/masterchef/keeper/params.go | 12 ---- x/masterchef/keeper/pool.go | 24 +------ x/masterchef/keeper/pool_reward_info.go | 21 ------ x/masterchef/keeper/pool_rewards_accum.go | 21 ------ x/masterchef/migrations/v5_migration.go | 40 ----------- x/masterchef/types/events.go | 1 + x/masterchef/types/keys.go | 69 ------------------- 16 files changed, 57 insertions(+), 250 deletions(-) rename x/commitment/keeper/{msg_server_commit_liquid_tokens.go => commit_liquid_tokens.go} (100%) rename x/commitment/keeper/{msg_server_commit_liquid_tokens_test.go => commit_liquid_tokens_test.go} (100%) diff --git a/x/amm/types/calc_out_amt_given_in.go b/x/amm/types/calc_out_amt_given_in.go index 399f80394..9fa1d2cc3 100644 --- a/x/amm/types/calc_out_amt_given_in.go +++ b/x/amm/types/calc_out_amt_given_in.go @@ -66,8 +66,9 @@ func (p Pool) CalcOutAmtGivenIn( if err != nil { return sdk.Coin{}, sdkmath.LegacyZeroDec(), err } + if tokenAmountOut.IsZero() { - return sdk.Coin{}, sdkmath.LegacyZeroDec(), ErrAmountTooLow + return sdk.Coin{}, sdkmath.LegacyZeroDec(), ErrTokenOutAmountZero } rate, err := p.GetTokenARate(ctx, oracle, snapshot, tokenIn.Denom, tokenOutDenom, accountedPool) @@ -87,7 +88,7 @@ func (p Pool) CalcOutAmtGivenIn( // We ignore the decimal component, as we round down the token amount out. tokenAmountOutInt := tokenAmountOut.TruncateInt() if !tokenAmountOutInt.IsPositive() { - return sdk.Coin{}, sdkmath.LegacyZeroDec(), errorsmod.Wrapf(ErrInvalidMathApprox, "token amount must be positive") + return sdk.Coin{}, sdkmath.LegacyZeroDec(), ErrTokenOutAmountZero } return sdk.NewCoin(tokenOutDenom, tokenAmountOutInt), slippage, nil diff --git a/x/amm/types/errors.go b/x/amm/types/errors.go index 3e242f210..812b2440d 100644 --- a/x/amm/types/errors.go +++ b/x/amm/types/errors.go @@ -3,8 +3,9 @@ package types // DONTCOVER import ( - "cosmossdk.io/errors" "fmt" + + "cosmossdk.io/errors" ) // x/amm module sentinel errors @@ -36,6 +37,8 @@ var ( ErrInvalidShareAmountOut = errors.Register(ModuleName, 112, "invalid share amount out") ErrPoolAssetsMustBeTwo = errors.Register(ModuleName, 113, "pool assets must be exactly two") ErrOnlyBaseAssetsPoolAllowed = errors.Register(ModuleName, 114, "Only base assets paired pool allowed") + + ErrTokenOutAmountZero = errors.Register(ModuleName, 115, "token out amount is zero") ) const ( diff --git a/x/amm/types/swap_out_amt_given_in_test.go b/x/amm/types/swap_out_amt_given_in_test.go index dd35861f8..85aff2f34 100644 --- a/x/amm/types/swap_out_amt_given_in_test.go +++ b/x/amm/types/swap_out_amt_given_in_test.go @@ -640,7 +640,7 @@ func (suite *TestSuite) TestSwapOutAmtGivenIn() { tokenOut, _, _, weightBonus, err := pool.SwapOutAmtGivenIn(suite.ctx, suite.app.OracleKeeper, &pool, sdk.Coins{tc.tokenIn}, tc.outTokenDenom, tc.swapFee, suite.app.AccountedPoolKeeper, sdkmath.LegacyOneDec(), params) if tc.expErr { suite.Require().Error(err) - suite.Require().EqualError(err, "amount too low") + suite.Require().EqualError(err, "token out amount is zero") } else { suite.Require().NoError(err) suite.Require().Equal(tokenOut.String(), tc.expTokenOut.String()) diff --git a/x/commitment/keeper/msg_server_commit_liquid_tokens.go b/x/commitment/keeper/commit_liquid_tokens.go similarity index 100% rename from x/commitment/keeper/msg_server_commit_liquid_tokens.go rename to x/commitment/keeper/commit_liquid_tokens.go diff --git a/x/commitment/keeper/msg_server_commit_liquid_tokens_test.go b/x/commitment/keeper/commit_liquid_tokens_test.go similarity index 100% rename from x/commitment/keeper/msg_server_commit_liquid_tokens_test.go rename to x/commitment/keeper/commit_liquid_tokens_test.go diff --git a/x/masterchef/keeper/abci.go b/x/masterchef/keeper/abci.go index 232b52637..18d0c92fb 100644 --- a/x/masterchef/keeper/abci.go +++ b/x/masterchef/keeper/abci.go @@ -307,7 +307,7 @@ func (k Keeper) UpdateLPRewards(ctx sdk.Context) error { // Move gas fees collected to dex revenue wallet // Convert it into USDC -func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, address sdk.AccAddress) sdk.Coins { +func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, address sdk.AccAddress) (sdk.Coins, error) { // 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) @@ -326,6 +326,9 @@ func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, addre // Find a pool that can convert tokenIn to usdc pool, found := k.amm.GetBestPoolWithDenoms(ctx, []string{tokenIn.Denom, baseCurrency}, false) if !found { + // If there is a denom for which pool doesn't exist, log it, otherwise + // if pool exist, throw error later + ctx.Logger().Info("Pool not found for denom: " + tokenIn.Denom) continue } @@ -334,7 +337,19 @@ func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, addre snapshot := k.amm.GetAccountedPoolSnapshotOrSet(ctx, pool) tokenOutCoin, _, _, _, err := k.amm.SwapOutAmtGivenIn(ctx, pool.PoolId, k.oracleKeeper, &snapshot, sdk.Coins{tokenIn}, baseCurrency, math.LegacyZeroDec(), math.LegacyOneDec()) if err != nil { - continue + // Continue as we can swap it when this amount is higher + if err == ammtypes.ErrTokenOutAmountZero { + ctx.Logger().Info("Token out amount is zero(skipping conversion) for denom: " + tokenIn.Denom) + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.TypeEvtSkipSwap, + sdk.NewAttribute("Token denom", tokenIn.Denom), + sdk.NewAttribute("Token amount", "0"), + ), + }) + continue + } + return sdk.Coins{}, err } tokenOutAmount := tokenOutCoin.Amount @@ -344,12 +359,10 @@ func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, addre // 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, address, address, tokenIn, tokenOutCoin, math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) + _, err = k.amm.UpdatePoolForSwap(ctx, pool, address, address, tokenIn, tokenOutCoin, math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) if err != nil { - continue + return sdk.Coins{}, err } - write() // Swapped USDC coin swappedCoins := sdk.NewCoins(sdk.NewCoin(baseCurrency, tokenOutAmount)) @@ -358,14 +371,17 @@ func (k Keeper) ConvertGasFeesToUsdc(ctx sdk.Context, baseCurrency string, addre totalSwappedCoins = totalSwappedCoins.Add(swappedCoins...) } - return totalSwappedCoins + return totalSwappedCoins, nil } func (k Keeper) CollectGasFees(ctx sdk.Context, baseCurrency string) (sdk.DecCoins, error) { 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, feeCollector.GetAddress()) + fees, err := k.ConvertGasFeesToUsdc(ctx, baseCurrency, feeCollector.GetAddress()) + if err != nil { + return sdk.DecCoins{}, err + } gasFeeCollectedDec := sdk.NewDecCoinsFromCoins(fees...) gasFeesForLpsDec := gasFeeCollectedDec.MulDecTruncate(params.RewardPortionForLps) @@ -408,7 +424,10 @@ func (k Keeper) CollectPerpRevenue(ctx sdk.Context, baseCurrency string) (sdk.De 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) + fees, err := k.ConvertGasFeesToUsdc(ctx, baseCurrency, fundAddr) + if err != nil { + return sdk.DecCoins{}, err + } // Calculate each portion of Gas fees collected - stakers, LPs perpFeeCollectedDec := sdk.NewDecCoinsFromCoins(fees...) @@ -420,6 +439,7 @@ func (k Keeper) CollectPerpRevenue(ctx sdk.Context, baseCurrency string) (sdk.De lpsGasFeeCoins, _ := perpFeesForLpsDec.TruncateDecimal() protocolGasFeeCoins, _ := perpFeesForProtocolDec.TruncateDecimal() + stakerCoins, _ := perpFeesForStakersDec.TruncateDecimal() // Send coins from fund address to masterchef if lpsGasFeeCoins.IsAllPositive() { @@ -429,6 +449,14 @@ func (k Keeper) CollectPerpRevenue(ctx sdk.Context, baseCurrency string) (sdk.De } } + // Send coins to fee collector name + if perpFeesForStakersDec.IsAllPositive() { + err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, authtypes.FeeCollectorName, stakerCoins) + if err != nil { + return sdk.DecCoins{}, err + } + } + // Send coins to protocol revenue address if protocolGasFeeCoins.IsAllPositive() { protocolRevenueAddress, err := sdk.AccAddressFromBech32(params.ProtocolRevenueAddress) diff --git a/x/masterchef/keeper/external_incentive.go b/x/masterchef/keeper/external_incentive.go index 92e5fd518..ef4a05d1f 100644 --- a/x/masterchef/keeper/external_incentive.go +++ b/x/masterchef/keeper/external_incentive.go @@ -1,7 +1,6 @@ package keeper import ( - "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" @@ -20,19 +19,6 @@ func (k Keeper) SetExternalIncentiveIndex(ctx sdk.Context, index uint64) { store.Set(types.ExternalIncentiveIndexKeyPrefix, sdk.Uint64ToBigEndian(index)) } -// remove after migration -func (k Keeper) GetLegacyExternalIncentiveIndex(ctx sdk.Context) (index uint64) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyExternalIncentiveIndexKeyPrefix)) - index = sdk.BigEndianToUint64(store.Get(types.LegacyExternalIncentiveIndex())) - return index -} - -// remove after migration -func (k Keeper) RemoveLegacyExternalIncentiveIndex(ctx sdk.Context) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyExternalIncentiveIndexKeyPrefix)) - store.Delete(types.LegacyExternalIncentiveIndex()) -} - func (k Keeper) SetExternalIncentive(ctx sdk.Context, externalIncentive types.ExternalIncentive) { store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) key := types.GetExternalIncentiveKey(externalIncentive.Id) @@ -72,23 +58,3 @@ func (k Keeper) GetAllExternalIncentives(ctx sdk.Context) (list []types.External return } - -func (k Keeper) DeleteLegacyExternalIncentive(ctx sdk.Context, id uint64) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyExternalIncentiveKeyPrefix)) - store.Delete(types.LegacyExternalIncentiveKey(id)) -} - -func (k Keeper) GetAllLegacyExternalIncentives(ctx sdk.Context) (list []types.ExternalIncentive) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyExternalIncentiveKeyPrefix)) - iterator := storetypes.KVStorePrefixIterator(store, []byte{}) - - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var val types.ExternalIncentive - k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) - } - - return -} diff --git a/x/masterchef/keeper/hooks_masterchef.go b/x/masterchef/keeper/hooks_masterchef.go index bcf5b86ca..52c2abc01 100644 --- a/x/masterchef/keeper/hooks_masterchef.go +++ b/x/masterchef/keeper/hooks_masterchef.go @@ -52,13 +52,9 @@ func (k Keeper) UpdateAccPerShare(ctx sdk.Context, poolId uint64, rewardDenom st func (k Keeper) UpdateUserRewardPending(ctx sdk.Context, poolId uint64, rewardDenom string, user sdk.AccAddress, isDeposit bool, amount math.Int) { poolRewardInfo, found := k.GetPoolRewardInfo(ctx, poolId, rewardDenom) - if !found { - poolRewardInfo = types.PoolRewardInfo{ - PoolId: poolId, - RewardDenom: rewardDenom, - PoolAccRewardPerShare: math.LegacyNewDec(0), - LastUpdatedBlock: uint64(ctx.BlockHeight()), - } + poolAccRewardPerShare := math.LegacyNewDec(0) + if found { + poolAccRewardPerShare = poolRewardInfo.PoolAccRewardPerShare } userRewardInfo, found := k.GetUserRewardInfo(ctx, user, poolId, rewardDenom) @@ -81,7 +77,7 @@ func (k Keeper) UpdateUserRewardPending(ctx sdk.Context, poolId uint64, rewardDe } userRewardInfo.RewardPending = userRewardInfo.RewardPending.Add( - poolRewardInfo.PoolAccRewardPerShare. + poolAccRewardPerShare. MulInt(userBalance). Sub(userRewardInfo.RewardDebt). QuoInt(ammtypes.OneShare), @@ -92,13 +88,9 @@ func (k Keeper) UpdateUserRewardPending(ctx sdk.Context, poolId uint64, rewardDe func (k Keeper) UpdateUserRewardDebt(ctx sdk.Context, poolId uint64, rewardDenom string, user sdk.AccAddress) { poolRewardInfo, found := k.GetPoolRewardInfo(ctx, poolId, rewardDenom) - if !found { - poolRewardInfo = types.PoolRewardInfo{ - PoolId: poolId, - RewardDenom: rewardDenom, - PoolAccRewardPerShare: math.LegacyNewDec(0), - LastUpdatedBlock: uint64(ctx.BlockHeight()), - } + poolAccRewardPerShare := math.LegacyNewDec(0) + if found { + poolAccRewardPerShare = poolRewardInfo.PoolAccRewardPerShare } userRewardInfo, found := k.GetUserRewardInfo(ctx, user, poolId, rewardDenom) @@ -112,7 +104,7 @@ func (k Keeper) UpdateUserRewardDebt(ctx sdk.Context, poolId uint64, rewardDenom } } - userRewardInfo.RewardDebt = poolRewardInfo.PoolAccRewardPerShare.Mul( + userRewardInfo.RewardDebt = poolAccRewardPerShare.Mul( math.LegacyNewDecFromInt(k.GetPoolBalance(ctx, poolId, user)), ) diff --git a/x/masterchef/keeper/hooks_user_actions.go b/x/masterchef/keeper/hooks_user_actions.go index 62cf53d40..f68fda7d2 100644 --- a/x/masterchef/keeper/hooks_user_actions.go +++ b/x/masterchef/keeper/hooks_user_actions.go @@ -3,7 +3,6 @@ package keeper import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/elys-network/elys/x/parameter/types" ptypes "github.com/elys-network/elys/x/parameter/types" ) @@ -65,7 +64,7 @@ func (k Keeper) GetRewardDenoms(ctx sdk.Context, poolId uint64) []string { } if poolInfo.EnableEdenRewards { - keys = append(keys, types.Eden) + keys = append(keys, ptypes.Eden) } for _, denom := range poolInfo.ExternalRewardDenoms { diff --git a/x/masterchef/keeper/params.go b/x/masterchef/keeper/params.go index 2548a3d82..968734a12 100644 --- a/x/masterchef/keeper/params.go +++ b/x/masterchef/keeper/params.go @@ -29,15 +29,3 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { func (k Keeper) CheckBlockedAddress(params types.Params) bool { return k.bankKeeper.BlockedAddr(sdk.MustAccAddressFromBech32(params.ProtocolRevenueAddress)) } - -func (k Keeper) GetLegacyParams(ctx sdk.Context) (params types.LegacyParams) { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - - b := store.Get(types.ParamsKey) - if b == nil { - return - } - - k.cdc.MustUnmarshal(b, ¶ms) - return -} diff --git a/x/masterchef/keeper/pool.go b/x/masterchef/keeper/pool.go index 148e9e786..6679e30af 100644 --- a/x/masterchef/keeper/pool.go +++ b/x/masterchef/keeper/pool.go @@ -1,8 +1,9 @@ package keeper import ( - storetypes "cosmossdk.io/store/types" "fmt" + + storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" @@ -50,27 +51,6 @@ func (k Keeper) GetAllPoolInfos(ctx sdk.Context) (list []types.PoolInfo) { return } -func (k Keeper) RemoveLegacyPoolInfo(ctx sdk.Context, poolId uint64) { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - key := types.GetPoolInfoKey(poolId) - store.Delete(key) -} - -func (k Keeper) GetAllLegacyPoolInfos(ctx sdk.Context) (list []types.LegacyPoolInfo) { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - iterator := storetypes.KVStorePrefixIterator(store, types.PoolInfoKeyPrefix) - - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var val types.LegacyPoolInfo - k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) - } - - return -} - func (k Keeper) UpdatePoolMultipliers(ctx sdk.Context, poolMultipliers []types.PoolMultiplier) bool { if len(poolMultipliers) < 1 { return false diff --git a/x/masterchef/keeper/pool_reward_info.go b/x/masterchef/keeper/pool_reward_info.go index 5bb7cd713..e8ee1a1cf 100644 --- a/x/masterchef/keeper/pool_reward_info.go +++ b/x/masterchef/keeper/pool_reward_info.go @@ -1,7 +1,6 @@ package keeper import ( - "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" @@ -48,23 +47,3 @@ func (k Keeper) GetAllPoolRewardInfos(ctx sdk.Context) (list []types.PoolRewardI return } - -func (k Keeper) DeleteLegacyPoolRewardInfo(ctx sdk.Context, poolId uint64, rewardDenom string) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyPoolRewardInfoKeyPrefix)) - store.Delete(types.LegacyPoolRewardInfoKey(poolId, rewardDenom)) -} - -func (k Keeper) GetAllLegacyPoolRewardInfos(ctx sdk.Context) (list []types.PoolRewardInfo) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyPoolRewardInfoKeyPrefix)) - iterator := storetypes.KVStorePrefixIterator(store, []byte{}) - - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var val types.PoolRewardInfo - k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) - } - - return -} diff --git a/x/masterchef/keeper/pool_rewards_accum.go b/x/masterchef/keeper/pool_rewards_accum.go index deb102b4c..4f5aa10ae 100644 --- a/x/masterchef/keeper/pool_rewards_accum.go +++ b/x/masterchef/keeper/pool_rewards_accum.go @@ -2,7 +2,6 @@ package keeper import ( "cosmossdk.io/math" - "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" @@ -47,26 +46,6 @@ func (k Keeper) GetAllPoolRewardsAccum(ctx sdk.Context) (list []types.PoolReward return } -func (k Keeper) DeleteLegacyPoolRewardsAccum(ctx sdk.Context, accum types.PoolRewardsAccum) { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store.Delete(types.GetLegacyPoolRewardsAccumKey(accum.PoolId, accum.Timestamp)) -} - -func (k Keeper) GetAllLegacyPoolRewardsAccum(ctx sdk.Context) (list []types.PoolRewardsAccum) { - store := prefix.NewStore(runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)), types.KeyPrefix(types.LegacyPoolRewardsAccumKeyPrefix)) - iterator := storetypes.KVStorePrefixIterator(store, []byte{}) - - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var val types.PoolRewardsAccum - k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) - } - - return -} - func (k Keeper) IterateAllPoolRewardsAccum(ctx sdk.Context, handler func(accum types.PoolRewardsAccum) (stop bool)) { store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) iter := storetypes.KVStorePrefixIterator(store, types.PoolRewardsAccumKeyPrefix) diff --git a/x/masterchef/migrations/v5_migration.go b/x/masterchef/migrations/v5_migration.go index 77343c5e0..3822097bd 100644 --- a/x/masterchef/migrations/v5_migration.go +++ b/x/masterchef/migrations/v5_migration.go @@ -2,49 +2,9 @@ package migrations import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/elys-network/elys/x/masterchef/types" ) func (m Migrator) V5Migration(ctx sdk.Context) error { - legacyParams := m.keeper.GetLegacyParams(ctx) - params := types.Params{} - if legacyParams.LpIncentives != nil { - params.LpIncentives = &types.IncentiveInfo{ - EdenAmountPerYear: legacyParams.LpIncentives.EdenAmountPerYear, - BlocksDistributed: legacyParams.LpIncentives.BlocksDistributed.Int64(), - } - } - params.MaxEdenRewardAprLps = legacyParams.MaxEdenRewardAprLps - params.RewardPortionForLps = legacyParams.RewardPortionForLps - params.RewardPortionForStakers = legacyParams.RewardPortionForStakers - params.SupportedRewardDenoms = legacyParams.SupportedRewardDenoms - params.ProtocolRevenueAddress = legacyParams.ProtocolRevenueAddress - m.keeper.SetParams(ctx, params) - - // Migrate pool infos - pools := m.keeper.GetAllLegacyPoolInfos(ctx) - - ctx.Logger().Info("Migration: Adding enable eden rewards field") - - for _, pool := range pools { - - ctx.Logger().Debug("pool", pool) - - newPool := types.PoolInfo{ - PoolId: pool.PoolId, - RewardWallet: pool.RewardWallet, - Multiplier: pool.Multiplier, - EdenApr: pool.EdenApr, - DexApr: pool.DexApr, - GasApr: pool.GasApr, - ExternalIncentiveApr: pool.ExternalIncentiveApr, - ExternalRewardDenoms: pool.ExternalRewardDenoms, - EnableEdenRewards: true, - } - - m.keeper.RemoveLegacyPoolInfo(ctx, pool.PoolId) - m.keeper.SetPoolInfo(ctx, newPool) - } return nil } diff --git a/x/masterchef/types/events.go b/x/masterchef/types/events.go index 557c8c74c..605637c93 100644 --- a/x/masterchef/types/events.go +++ b/x/masterchef/types/events.go @@ -5,6 +5,7 @@ const ( TypeEvtAddExternalIncentive = "add_external_incentive" TypeEvtClaimRewards = "claim_rewards" TypeEvtSetPoolMultiplier = "set_pool_multiplier" + TypeEvtSkipSwap = "skip_conversion_of_fee" AttributeRewardDenom = "reward_denom" AttributeMinAmount = "min_amount" diff --git a/x/masterchef/types/keys.go b/x/masterchef/types/keys.go index 023f117a2..51684649d 100644 --- a/x/masterchef/types/keys.go +++ b/x/masterchef/types/keys.go @@ -14,12 +14,6 @@ const ( // StoreKey defines the primary module store key StoreKey = ModuleName - - LegacyUserRewardInfoKeyPrefix = "UserRewardInfo" - LegacyExternalIncentiveIndexKeyPrefix = "IndexExternalIncentive" - LegacyExternalIncentiveKeyPrefix = "ExternalIncentive" - LegacyPoolRewardInfoKeyPrefix = "PoolRewardInfo" - LegacyPoolRewardsAccumKeyPrefix = "PoolRewardsAccum" ) var ( @@ -37,17 +31,6 @@ func KeyPrefix(p string) []byte { return []byte(p) } -func LegacyPoolInfoKey(poolId uint64) []byte { - var key []byte - - poolIdBytes := make([]byte, 8) - binary.BigEndian.PutUint64(poolIdBytes, poolId) - key = append(key, poolIdBytes...) - key = append(key, []byte("/")...) - - return key -} - func GetPoolInfoKey(poolId uint64) []byte { key := PoolInfoKeyPrefix poolIdBytes := make([]byte, 8) @@ -57,17 +40,6 @@ func GetPoolInfoKey(poolId uint64) []byte { return key } -func LegacyExternalIncentiveKey(incentiveId uint64) []byte { - var key []byte - - incentiveIdBytes := make([]byte, 8) - binary.BigEndian.PutUint64(incentiveIdBytes, incentiveId) - key = append(key, incentiveIdBytes...) - key = append(key, []byte("/")...) - - return key -} - func GetExternalIncentiveKey(incentiveId uint64) []byte { key := ExternalIncentiveKeyPrefix @@ -77,25 +49,6 @@ func GetExternalIncentiveKey(incentiveId uint64) []byte { return key } -func LegacyExternalIncentiveIndex() []byte { - var key []byte - - key = append(key, LegacyExternalIncentiveIndexKeyPrefix...) - return key -} - -func LegacyPoolRewardInfoKey(poolId uint64, rewardDenom string) []byte { - var key []byte - - poolIdBytes := sdk.Uint64ToBigEndian(poolId) - key = append(key, poolIdBytes...) - key = append(key, []byte("/")...) - key = append(key, rewardDenom...) - key = append(key, []byte("/")...) - - return key -} - func GetPoolRewardInfoKey(poolId uint64, rewardDenom string) []byte { key := PoolRewardInfoKeyPrefix @@ -108,20 +61,6 @@ func GetPoolRewardInfoKey(poolId uint64, rewardDenom string) []byte { return key } -func GetLegacyUserRewardInfoKey(user string, poolId uint64, rewardDenom string) []byte { - key := KeyPrefix(LegacyUserRewardInfoKeyPrefix) - - key = append(key, user...) - key = append(key, []byte("/")...) - poolIdBytes := sdk.Uint64ToBigEndian(poolId) - key = append(key, poolIdBytes...) - key = append(key, []byte("/")...) - key = append(key, rewardDenom...) - key = append(key, []byte("/")...) - - return key -} - func GetUserRewardInfoKey(user sdk.AccAddress, poolId uint64, rewardDenom string) []byte { key := UserRewardInfoKeyPrefix @@ -135,14 +74,6 @@ func GetUserRewardInfoKey(user sdk.AccAddress, poolId uint64, rewardDenom string return key } -func GetLegacyPoolRewardsAccumPrefix(poolId uint64) []byte { - return append([]byte(LegacyPoolRewardsAccumKeyPrefix), sdk.Uint64ToBigEndian(uint64(poolId))...) -} - -func GetLegacyPoolRewardsAccumKey(poolId uint64, timestamp uint64) []byte { - return append(GetLegacyPoolRewardsAccumPrefix(poolId), sdk.Uint64ToBigEndian(timestamp)...) -} - func GetPoolRewardsAccumPrefix(poolId uint64) []byte { key := PoolRewardsAccumKeyPrefix key = append(key, []byte("/")...)