Skip to content

Commit

Permalink
Increase coverage for Amm keeper and types package (#1052)
Browse files Browse the repository at this point in the history
* increasse coverage for amm keepers

* swap by denom test for out route

* add more amm tests

* increase coverage for amm types package
  • Loading branch information
99adarsh authored Dec 9, 2024
1 parent 4349c0f commit 0dfa83f
Show file tree
Hide file tree
Showing 19 changed files with 1,452 additions and 19 deletions.
3 changes: 2 additions & 1 deletion x/amm/keeper/calc_in_route_spot_price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ func (suite *AmmKeeperTestSuite) TestCalcInRouteSpotPrice() {

tokenIn := sdk.NewCoin(ptypes.Elys, sdkmath.NewInt(100))
routes := []*types.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: ptypes.BaseCurrency}}
spotPrice, _, _, _, _, _, _, _, err := suite.app.AmmKeeper.CalcInRouteSpotPrice(suite.ctx, tokenIn, routes, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec())
spotPrice, _, _, totalDiscountedSwapFee, _, _, _, _, err := suite.app.AmmKeeper.CalcInRouteSpotPrice(suite.ctx, tokenIn, routes, sdkmath.LegacyZeroDec(), sdkmath.LegacyMustNewDecFromStr("0.1"))
suite.Require().NoError(err)
suite.Require().Equal(spotPrice.String(), sdkmath.LegacyOneDec().String())
suite.Require().Equal(sdkmath.LegacyMustNewDecFromStr("0.1"), totalDiscountedSwapFee)

routes = []*types.SwapAmountInRoute{
{PoolId: 1, TokenOutDenom: ptypes.BaseCurrency},
Expand Down
50 changes: 50 additions & 0 deletions x/amm/keeper/estimate_price_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,56 @@ func (suite *AmmKeeperTestSuite) TestEstimatePrice() {
suite.Require().Equal(math.LegacyMustNewDecFromStr("0.000001000000000000"), price)
},
},
{
"Asset Info Not found for tokenInDenom",
func() {
suite.ResetSuite()
suite.SetupCoinPrices()
},
func() {
suite.app.OracleKeeper.RemoveAssetInfo(suite.ctx, ptypes.BaseCurrency)
price := suite.app.AmmKeeper.GetTokenPrice(suite.ctx, ptypes.BaseCurrency, ptypes.BaseCurrency)
suite.Require().Equal(math.LegacyMustNewDecFromStr("0.000000000000000000"), price)
},
},
}

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

func (suite *AmmKeeperTestSuite) TestCalculateUSDValue() {
testCases := []struct {
name string
prerequisiteFunction func()
postValidateFunction func()
}{
{
"Success: get token value at oracle price",
func() {
suite.ResetSuite()
suite.SetupCoinPrices()
},
func() {
value := suite.app.AmmKeeper.CalculateUSDValue(suite.ctx, ptypes.ATOM, math.NewInt(1000))
suite.Require().Equal(value, math.LegacyMustNewDecFromStr("0.001"))
},
},
{
"Calculate Usd value for asset not found in AssetProfile",
func() {
suite.ResetSuite()
suite.SetupCoinPrices()
},
func() {
value := suite.app.AmmKeeper.CalculateUSDValue(suite.ctx, "dummy", math.NewInt(1000))
suite.Require().Equal(value.String(), math.LegacyZeroDec().String())
},
},
}

for _, tc := range testCases {
Expand Down
21 changes: 20 additions & 1 deletion x/amm/keeper/fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,39 @@ func (suite *AmmKeeperTestSuite) TestOnCollectFee() {
poolInitBalance sdk.Coins
expRevenueBalance sdk.Coins
expPass bool
useOracle bool
}{
{
desc: "multiple fees collected",
fee: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
poolInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
expRevenueBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1999)},
expPass: true,
useOracle: false,
},
{
desc: "zero fees collected",
fee: sdk.Coins{},
poolInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
expRevenueBalance: sdk.Coins{},
expPass: true,
useOracle: false,
},
{
desc: "base currency fee collected",
fee: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
poolInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
expRevenueBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
expPass: true,
useOracle: false,
},
{
desc: "fee collected after weight recovery fee deduction",
fee: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
poolInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
expRevenueBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 900)},
expPass: true,
useOracle: true,
},
} {
suite.Run(tc.desc, func() {
Expand Down Expand Up @@ -87,7 +99,7 @@ func (suite *AmmKeeperTestSuite) TestOnCollectFee() {
RebalanceTreasury: treasuryAddr.String(),
PoolParams: types.PoolParams{
SwapFee: sdkmath.LegacyZeroDec(),
UseOracle: false,
UseOracle: tc.useOracle,
FeeDenom: ptypes.BaseCurrency,
},
TotalShares: sdk.NewCoin(types.GetPoolShareDenom(1), sdkmath.ZeroInt()),
Expand Down Expand Up @@ -149,6 +161,13 @@ func (suite *AmmKeeperTestSuite) TestSwapFeesToRevenueToken() {
expRevenueBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
expPass: true,
},
{
desc: "token not available in pools for swap",
fee: sdk.Coins{sdk.NewInt64Coin("dummy", 1000)},
poolInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Elys, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
expRevenueBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 1000)},
expPass: false,
},
} {
suite.Run(tc.desc, func() {
suite.SetupTest()
Expand Down
57 changes: 57 additions & 0 deletions x/amm/keeper/keeper_create_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package keeper_test

import (
"github.com/elys-network/elys/x/amm/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
"github.com/stretchr/testify/require"
)

func (suite *AmmKeeperTestSuite) TestCreatePool() {
// Define test cases
testCases := []struct {
name string
setup func() *types.MsgCreatePool
expectedErrMsg string
}{
{
"asset profile not found",
func() *types.MsgCreatePool {
addr := suite.AddAccounts(1, nil)
suite.app.AssetprofileKeeper.RemoveEntry(suite.ctx, ptypes.BaseCurrency)
return &types.MsgCreatePool{
Sender: addr[0].String(),
PoolParams: types.PoolParams{},
PoolAssets: []types.PoolAsset{},
}
},
"asset profile not found for denom",
},
{
"Balance pool Create Error",
func() *types.MsgCreatePool {
suite.ResetSuite()
addr := suite.AddAccounts(1, nil)
return &types.MsgCreatePool{
Sender: addr[0].String(),
PoolParams: types.PoolParams{},
PoolAssets: []types.PoolAsset{},
}
},
"swap_fee is nil",
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
msg := tc.setup()
poolId, err := suite.app.AmmKeeper.CreatePool(suite.ctx, msg)
if tc.expectedErrMsg != "" {
require.Error(suite.T(), err)
require.Contains(suite.T(), err.Error(), tc.expectedErrMsg)
} else {
require.NoError(suite.T(), err)
require.NotZero(suite.T(), poolId)
}
})
}
}
57 changes: 57 additions & 0 deletions x/amm/keeper/keeper_exit_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package keeper_test

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

func (suite *AmmKeeperTestSuite) TestExitPool() {
testCases := []struct {
name string
setup func() (sdk.AccAddress, uint64, math.Int, sdk.Coins, string, bool)
expectedErrMsg string
}{
{
"pool does not exist",
func() (sdk.AccAddress, uint64, math.Int, sdk.Coins, string, bool) {
addr := suite.AddAccounts(1, nil)
return addr[0], 1, math.NewInt(100), sdk.NewCoins(sdk.NewCoin("uatom", math.NewInt(100))), "uatom", false
},
"invalid pool id",
},
{
"exiting more shares than available",
func() (sdk.AccAddress, uint64, math.Int, sdk.Coins, string, bool) {
suite.SetupCoinPrices()
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100000000000)
pool := suite.CreateNewAmmPool(addr[0], true, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), ptypes.ATOM, amount.MulRaw(10), amount.MulRaw(10))
return addr[0], 1, pool.TotalShares.Amount.Add(sdkmath.NewInt(10)), sdk.NewCoins(sdk.NewCoin("uatom", math.NewInt(100))), "uatom", false
},
"Trying to exit >= the number of shares contained in the pool",
},
{
"exiting negative shares",
func() (sdk.AccAddress, uint64, math.Int, sdk.Coins, string, bool) {
addr := suite.AddAccounts(1, nil)
return addr[0], 1, sdkmath.NewInt(1).Neg(), sdk.NewCoins(sdk.NewCoin("uatom", math.NewInt(100))), "uatom", false
},
"Trying to exit a negative amount of shares",
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
exiter, poolId, inShares, minTokensOut, tokenOutDenom, isLiq := tc.setup()
_, err := suite.app.AmmKeeper.ExitPool(suite.ctx, exiter, poolId, inShares, minTokensOut, tokenOutDenom, isLiq)
if tc.expectedErrMsg != "" {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expectedErrMsg)
} else {
suite.Require().NoError(err)
}
})
}
}
91 changes: 91 additions & 0 deletions x/amm/keeper/keeper_join_pool_no_swap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package keeper_test

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

func (suite *AmmKeeperTestSuite) TestJoinPoolNoSwap() {
// Define test cases
testCases := []struct {
name string
setup func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins)
expectedErrMsg string
}{
{
"pool does not exist",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
return sdk.AccAddress([]byte("sender")), 1, sdkmath.NewInt(100), sdk.Coins{}
},
"invalid pool id",
},
{
"successful join pool No oracle",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
suite.SetupCoinPrices()
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100000000000)
pool := suite.CreateNewAmmPool(addr[0], false, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), types.ATOM, amount.MulRaw(10), amount.MulRaw(10))
return addr[0], 1, pool.TotalShares.Amount, sdk.Coins{sdk.NewCoin(types.ATOM, amount.MulRaw(10)), sdk.NewCoin(types.BaseCurrency, amount.MulRaw(10))}
},
"",
},
{
"successful join pool with oracle",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
suite.SetupCoinPrices()
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100000000000)
pool := suite.CreateNewAmmPool(addr[0], true, sdkmath.LegacyZeroDec(), sdkmath.LegacyZeroDec(), types.ATOM, amount.MulRaw(10), amount.MulRaw(10))
return addr[0], 2, pool.TotalShares.Amount, sdk.Coins{sdk.NewCoin(types.ATOM, amount.MulRaw(10))}
},
"",
},
{
"Needed LpLiquidity is more than tokenInMaxs",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100)
share, _ := sdkmath.NewIntFromString("20000000000000000000000000000000")
return addr[0], 1, share, sdk.Coins{sdk.NewCoin(types.ATOM, amount), sdk.NewCoin(types.BaseCurrency, amount)}
},
"TokenInMaxs is less than the needed LP liquidity to this JoinPoolNoSwap",
},
{
"tokenInMaxs does not contain Needed LpLiquidity coins",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100)
share, _ := sdkmath.NewIntFromString("20000000000000000000000000000000")
return addr[0], 1, share, sdk.Coins{sdk.NewCoin("nocoin", amount), sdk.NewCoin(types.BaseCurrency, amount)}
},
"TokenInMaxs does not include all the tokens that are part of the target pool",
},
{
"tokenInMaxs does not contain Needed LpLiquidity coins",
func() (sdk.AccAddress, uint64, sdkmath.Int, sdk.Coins) {
addr := suite.AddAccounts(1, nil)
amount := sdkmath.NewInt(100)
share, _ := sdkmath.NewIntFromString("20000000000000000000000000000000")
return addr[0], 1, share, sdk.Coins{sdk.NewCoin("nocoin", amount), sdk.NewCoin(types.ATOM, amount), sdk.NewCoin(types.BaseCurrency, amount)}
},
"TokenInMaxs includes tokens that are not part of the target pool",
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
sender, poolId, shareOutAmount, tokenInMaxs := tc.setup()
tokenIn, sharesOut, err := suite.app.AmmKeeper.JoinPoolNoSwap(suite.ctx, sender, poolId, shareOutAmount, tokenInMaxs)
if tc.expectedErrMsg != "" {
suite.Require().Error(err)
suite.Require().Contains(err.Error(), tc.expectedErrMsg)
} else {
suite.Require().NoError(err)
suite.Require().True(tokenIn.IsAllLTE(tokenInMaxs))
suite.Require().True(sharesOut.LTE(shareOutAmount))
}
})
}
}
Loading

0 comments on commit 0dfa83f

Please sign in to comment.