Skip to content

Commit

Permalink
test(amm): increase test coverage (#941)
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmic-vagabond authored Nov 14, 2024
1 parent 63809ad commit 0a69b09
Show file tree
Hide file tree
Showing 8 changed files with 758 additions and 31 deletions.
313 changes: 313 additions & 0 deletions x/amm/keeper/apply_join_pool_state_change_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
package keeper_test

import (
"time"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
simapp "github.com/elys-network/elys/app"
"github.com/elys-network/elys/x/amm/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
)

func (suite *AmmKeeperTestSuite) TestApplyJoinPoolStateChange() {
testCases := []struct {
name string
prerequisiteFunction func()
postValidateFunction func()
}{
{
"join pool",
func() {
suite.ResetSuite()

suite.SetupCoinPrices()
suite.SetupAssetProfile()
},
func() {
app := suite.app
amm, bk := app.AmmKeeper, app.BankKeeper
ctx := suite.ctx

err := simapp.SetStakingParam(app, ctx)
suite.Require().NoError(err)

addr := suite.AddAccounts(1, nil)[0]

poolAssets := []types.PoolAsset{
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
},
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
},
}

poolParams := &types.PoolParams{
SwapFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
ExitFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
UseOracle: true,
WeightBreakingFeeMultiplier: sdkmath.LegacyZeroDec(),
WeightBreakingFeeExponent: sdkmath.LegacyNewDecWithPrec(25, 1), // 2.5
WeightRecoveryFeePortion: sdkmath.LegacyNewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdkmath.LegacyZeroDec(),
FeeDenom: ptypes.BaseCurrency,
}

msg := types.NewMsgCreatePool(
addr.String(),
poolParams,
poolAssets,
)

// Create a ATOM+USDC pool
poolId, err := amm.CreatePool(ctx, msg)
suite.Require().NoError(err)
suite.Require().Equal(poolId, uint64(1))

pool, found := amm.GetPool(ctx, poolId)
suite.Require().True(found)

lpTokenDenom := types.GetPoolShareDenom(poolId)
lpTokenBalance := bk.GetBalance(ctx, addr, lpTokenDenom)
suite.Require().True(lpTokenBalance.Amount.Equal(sdkmath.ZeroInt()))

joinCoins := sdk.NewCoins(sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)), sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)))

ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Hour))
err = app.AmmKeeper.ApplyJoinPoolStateChange(ctx, pool, addr, pool.TotalShares.Amount, joinCoins, sdkmath.LegacyZeroDec())
suite.Require().NoError(err)
},
},
{
"join pool fails because join coins exceeds user balance",
func() {
suite.ResetSuite()

suite.SetupCoinPrices()
suite.SetupAssetProfile()
},
func() {
app := suite.app
amm, bk := app.AmmKeeper, app.BankKeeper
ctx := suite.ctx

err := simapp.SetStakingParam(app, ctx)
suite.Require().NoError(err)

addr := suite.AddAccounts(1, nil)[0]

poolAssets := []types.PoolAsset{
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
},
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
},
}

poolParams := &types.PoolParams{
SwapFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
ExitFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
UseOracle: true,
WeightBreakingFeeMultiplier: sdkmath.LegacyZeroDec(),
WeightBreakingFeeExponent: sdkmath.LegacyNewDecWithPrec(25, 1), // 2.5
WeightRecoveryFeePortion: sdkmath.LegacyNewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdkmath.LegacyZeroDec(),
FeeDenom: ptypes.BaseCurrency,
}

msg := types.NewMsgCreatePool(
addr.String(),
poolParams,
poolAssets,
)

// Create a ATOM+USDC pool
poolId, err := amm.CreatePool(ctx, msg)
suite.Require().NoError(err)
suite.Require().Equal(poolId, uint64(1))

pool, found := amm.GetPool(ctx, poolId)
suite.Require().True(found)

lpTokenDenom := types.GetPoolShareDenom(poolId)
lpTokenBalance := bk.GetBalance(ctx, addr, lpTokenDenom)
suite.Require().True(lpTokenBalance.Amount.Equal(sdkmath.ZeroInt()))

joinCoins := sdk.NewCoins(
sdk.NewCoin(ptypes.BaseCurrency, suite.GetAccountIssueAmount().Mul(sdkmath.NewInt(10))),
sdk.NewCoin(ptypes.ATOM, suite.GetAccountIssueAmount().Mul(sdkmath.NewInt(10))),
)

ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Hour))
err = app.AmmKeeper.ApplyJoinPoolStateChange(ctx, pool, addr, pool.TotalShares.Amount, joinCoins, sdkmath.LegacyZeroDec())
suite.Require().Error(err)
},
},
{
"join pool fails because numshares is negative",
func() {
suite.ResetSuite()

suite.SetupCoinPrices()
suite.SetupAssetProfile()
},
func() {
app := suite.app
amm, bk := app.AmmKeeper, app.BankKeeper
ctx := suite.ctx

err := simapp.SetStakingParam(app, ctx)
suite.Require().NoError(err)

addr := suite.AddAccounts(1, nil)[0]

poolAssets := []types.PoolAsset{
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
},
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
},
}

poolParams := &types.PoolParams{
SwapFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
ExitFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
UseOracle: true,
WeightBreakingFeeMultiplier: sdkmath.LegacyZeroDec(),
WeightBreakingFeeExponent: sdkmath.LegacyNewDecWithPrec(25, 1), // 2.5
WeightRecoveryFeePortion: sdkmath.LegacyNewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdkmath.LegacyZeroDec(),
FeeDenom: ptypes.BaseCurrency,
}

msg := types.NewMsgCreatePool(
addr.String(),
poolParams,
poolAssets,
)

// Create a ATOM+USDC pool
poolId, err := amm.CreatePool(ctx, msg)
suite.Require().NoError(err)
suite.Require().Equal(poolId, uint64(1))

pool, found := amm.GetPool(ctx, poolId)
suite.Require().True(found)

lpTokenDenom := types.GetPoolShareDenom(poolId)
lpTokenBalance := bk.GetBalance(ctx, addr, lpTokenDenom)
suite.Require().True(lpTokenBalance.Amount.Equal(sdkmath.ZeroInt()))

joinCoins := sdk.NewCoins(
sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
)

ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Hour))

// must panic
suite.Require().Panics(func() {
err = app.AmmKeeper.ApplyJoinPoolStateChange(ctx, pool, addr, sdkmath.NewInt(-1000), joinCoins, sdkmath.LegacyZeroDec())
suite.Require().Error(err)
})
},
},
{
"join pool with positive weight balance bonus",
func() {
suite.ResetSuite()

suite.SetupCoinPrices()
suite.SetupAssetProfile()
},
func() {
app := suite.app
amm, bk := app.AmmKeeper, app.BankKeeper
ctx := suite.ctx

err := simapp.SetStakingParam(app, ctx)
suite.Require().NoError(err)

addr := suite.AddAccounts(1, nil)[0]

poolAssets := []types.PoolAsset{
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
},
{
Weight: sdkmath.NewInt(50),
Token: sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
},
}

poolParams := &types.PoolParams{
SwapFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
ExitFee: sdkmath.LegacyMustNewDecFromStr("0.1"),
UseOracle: true,
WeightBreakingFeeMultiplier: sdkmath.LegacyZeroDec(),
WeightBreakingFeeExponent: sdkmath.LegacyNewDecWithPrec(25, 1), // 2.5
WeightRecoveryFeePortion: sdkmath.LegacyNewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdkmath.LegacyZeroDec(),
FeeDenom: ptypes.BaseCurrency,
}

msg := types.NewMsgCreatePool(
addr.String(),
poolParams,
poolAssets,
)

// Create a ATOM+USDC pool
poolId, err := amm.CreatePool(ctx, msg)
suite.Require().NoError(err)
suite.Require().Equal(poolId, uint64(1))

pool, found := amm.GetPool(ctx, poolId)
suite.Require().True(found)

lpTokenDenom := types.GetPoolShareDenom(poolId)
lpTokenBalance := bk.GetBalance(ctx, addr, lpTokenDenom)
suite.Require().True(lpTokenBalance.Amount.Equal(sdkmath.ZeroInt()))

rebalanceTreasuryAddr := sdk.MustAccAddressFromBech32(pool.GetRebalanceTreasury())
// send 1000ATOM and 1000USDC to treasury
coins := sdk.NewCoins(
sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(1000)),
sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(1000)),
)
// mint coins
err = bk.MintCoins(ctx, types.ModuleName, coins)
suite.Require().NoError(err)
// send coins to treasury
err = bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, rebalanceTreasuryAddr, coins)
suite.Require().NoError(err)

joinCoins := sdk.NewCoins(
sdk.NewCoin(ptypes.BaseCurrency, sdkmath.NewInt(100000)),
sdk.NewCoin(ptypes.ATOM, sdkmath.NewInt(100000)),
)

ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Hour))
err = app.AmmKeeper.ApplyJoinPoolStateChange(ctx, pool, addr, pool.TotalShares.Amount, joinCoins, sdkmath.LegacyNewDecWithPrec(10, 2))
suite.Require().NoError(err)
},
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.prerequisiteFunction()
tc.postValidateFunction()
})
}
}
68 changes: 68 additions & 0 deletions x/amm/keeper/batch_processing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package keeper_test

import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elys-network/elys/x/amm/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
)

func (suite *AmmKeeperTestSuite) TestBatchProcessing() {
testCases := []struct {
name string
prerequisiteFunction func()
postValidateFunction func()
}{
{
"GetAllSwapExactAmountInRequests",
func() {
suite.ResetSuite()

lastSwapIndex := suite.app.AmmKeeper.GetLastSwapRequestIndex(suite.ctx)
suite.app.AmmKeeper.SetSwapExactAmountInRequests(suite.ctx, &types.MsgSwapExactAmountIn{
TokenIn: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(100)),
Routes: []types.SwapAmountInRoute{
{
PoolId: 1,
TokenOutDenom: ptypes.ATOM,
},
},
}, lastSwapIndex+1)
suite.app.AmmKeeper.SetLastSwapRequestIndex(suite.ctx, lastSwapIndex+1)
},
func() {
list := suite.app.AmmKeeper.GetAllSwapExactAmountInRequests(suite.ctx)
suite.Require().Equal(1, len(list))
},
},
{
"GetAllSwapExactAmountOutRequests",
func() {
suite.ResetSuite()

lastSwapIndex := suite.app.AmmKeeper.GetLastSwapRequestIndex(suite.ctx)
suite.app.AmmKeeper.SetSwapExactAmountOutRequests(suite.ctx, &types.MsgSwapExactAmountOut{
TokenOut: sdk.NewCoin(ptypes.ATOM, math.NewInt(100)),
Routes: []types.SwapAmountOutRoute{
{
PoolId: 1,
TokenInDenom: ptypes.BaseCurrency,
},
},
}, lastSwapIndex+1)
suite.app.AmmKeeper.SetLastSwapRequestIndex(suite.ctx, lastSwapIndex+1)
},
func() {
list := suite.app.AmmKeeper.GetAllSwapExactAmountOutRequests(suite.ctx)
suite.Require().Equal(1, len(list))
},
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.prerequisiteFunction()
tc.postValidateFunction()
})
}
}
Loading

0 comments on commit 0a69b09

Please sign in to comment.