github.com/gravity-devs/liquidity@v1.5.3/x/liquidity/keeper/liquidity_pool_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"testing"
     7  
     8  	sdk "github.com/cosmos/cosmos-sdk/types"
     9  	distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/gravity-devs/liquidity/app"
    13  	"github.com/gravity-devs/liquidity/x/liquidity"
    14  	"github.com/gravity-devs/liquidity/x/liquidity/keeper"
    15  	"github.com/gravity-devs/liquidity/x/liquidity/types"
    16  )
    17  
    18  func TestLiquidityPool(t *testing.T) {
    19  	app, ctx := createTestInput()
    20  	lp := types.Pool{
    21  		Id:                    0,
    22  		TypeId:                0,
    23  		ReserveCoinDenoms:     []string{"a", "b"},
    24  		ReserveAccountAddress: "",
    25  		PoolCoinDenom:         "poolCoin",
    26  	}
    27  	app.LiquidityKeeper.SetPool(ctx, lp)
    28  
    29  	lpGet, found := app.LiquidityKeeper.GetPool(ctx, 0)
    30  	require.True(t, found)
    31  	require.Equal(t, lp, lpGet)
    32  }
    33  
    34  func TestCreatePool(t *testing.T) {
    35  	simapp, ctx := createTestInput()
    36  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
    37  	params := simapp.LiquidityKeeper.GetParams(ctx)
    38  
    39  	poolTypeID := types.DefaultPoolTypeID
    40  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
    41  
    42  	denomA := "uETH"
    43  	denomB := "uUSD"
    44  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
    45  
    46  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
    47  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
    48  
    49  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
    50  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
    51  	depositBalance := sdk.NewCoins(depositA, depositB)
    52  
    53  	require.Equal(t, deposit, depositBalance)
    54  
    55  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
    56  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
    57  	require.NoError(t, err)
    58  
    59  	invalidMsg := types.NewMsgCreatePool(addrs[0], 2, depositBalance)
    60  	_, err = simapp.LiquidityKeeper.CreatePool(ctx, invalidMsg)
    61  	require.ErrorIs(t, err, types.ErrPoolTypeNotExists)
    62  
    63  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
    64  	require.Equal(t, 1, len(pools))
    65  	require.Equal(t, uint64(1), pools[0].Id)
    66  	require.Equal(t, uint64(1), simapp.LiquidityKeeper.GetNextPoolID(ctx)-1)
    67  	require.Equal(t, denomA, pools[0].ReserveCoinDenoms[0])
    68  	require.Equal(t, denomB, pools[0].ReserveCoinDenoms[1])
    69  
    70  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])
    71  	creatorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom)
    72  	require.Equal(t, poolCoin, creatorBalance.Amount)
    73  
    74  	_, err = simapp.LiquidityKeeper.CreatePool(ctx, msg)
    75  	require.ErrorIs(t, err, types.ErrPoolAlreadyExists)
    76  }
    77  
    78  func TestCreatePoolInsufficientAmount(t *testing.T) {
    79  	simapp, ctx := createTestInput()
    80  	params := simapp.LiquidityKeeper.GetParams(ctx)
    81  
    82  	depositCoins := sdk.NewCoins(sdk.NewInt64Coin(DenomX, 1000), sdk.NewInt64Coin(DenomY, 1000))
    83  	creator := app.AddRandomTestAddr(simapp, ctx, depositCoins.Add(params.PoolCreationFee...))
    84  
    85  	// Depositing coins that are less than params.MinInitDepositAmount.
    86  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, types.NewMsgCreatePool(creator, types.DefaultPoolTypeID, depositCoins))
    87  	require.ErrorIs(t, err, types.ErrLessThanMinInitDeposit)
    88  
    89  	fakeDepositCoins := depositCoins.Add(
    90  		sdk.NewCoin(DenomX, params.MinInitDepositAmount),
    91  		sdk.NewCoin(DenomY, params.MinInitDepositAmount),
    92  	)
    93  	// Depositing coins that are greater than the depositor has.
    94  	_, err = simapp.LiquidityKeeper.CreatePool(
    95  		ctx, types.NewMsgCreatePool(creator, types.DefaultPoolTypeID, fakeDepositCoins),
    96  	)
    97  	require.ErrorIs(t, err, types.ErrInsufficientBalance)
    98  }
    99  
   100  func TestPoolCreationFee(t *testing.T) {
   101  	simapp, ctx := createTestInput()
   102  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   103  	params := simapp.LiquidityKeeper.GetParams(ctx)
   104  
   105  	poolTypeID := types.DefaultPoolTypeID
   106  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   107  
   108  	denomA := "uETH"
   109  	denomB := "uUSD"
   110  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   111  
   112  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   113  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   114  
   115  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   116  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   117  	depositBalance := sdk.NewCoins(depositA, depositB)
   118  
   119  	require.Equal(t, deposit, depositBalance)
   120  
   121  	// Set PoolCreationFee for fail (insufficient balances for pool creation fee)
   122  	params.PoolCreationFee = depositBalance
   123  	simapp.LiquidityKeeper.SetParams(ctx, params)
   124  
   125  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   126  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
   127  	require.ErrorIs(t, types.ErrInsufficientPoolCreationFee, err)
   128  
   129  	// Set PoolCreationFee for success
   130  	params.PoolCreationFee = types.DefaultPoolCreationFee
   131  	simapp.LiquidityKeeper.SetParams(ctx, params)
   132  	feePoolAcc := simapp.AccountKeeper.GetModuleAddress(distrtypes.ModuleName)
   133  	feePoolBalance := simapp.BankKeeper.GetAllBalances(ctx, feePoolAcc)
   134  	msg = types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   135  	_, err = simapp.LiquidityKeeper.CreatePool(ctx, msg)
   136  	require.NoError(t, err)
   137  
   138  	// Verify PoolCreationFee pay successfully
   139  	feePoolBalance = feePoolBalance.Add(params.PoolCreationFee...)
   140  	require.Equal(t, params.PoolCreationFee, feePoolBalance)
   141  	require.Equal(t, feePoolBalance, simapp.BankKeeper.GetAllBalances(ctx, feePoolAcc))
   142  }
   143  
   144  func TestExecuteDeposit(t *testing.T) {
   145  	simapp, ctx := createTestInput()
   146  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   147  	params := simapp.LiquidityKeeper.GetParams(ctx)
   148  
   149  	poolTypeID := types.DefaultPoolTypeID
   150  	addrs := app.AddTestAddrs(simapp, ctx, 4, params.PoolCreationFee)
   151  
   152  	denomA := "uETH"
   153  	denomB := "uUSD"
   154  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   155  
   156  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   157  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   158  	app.SaveAccount(simapp, ctx, addrs[1], deposit)
   159  
   160  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   161  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   162  	depositBalance := sdk.NewCoins(depositA, depositB)
   163  
   164  	require.Equal(t, deposit, depositBalance)
   165  
   166  	depositA = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomA)
   167  	depositB = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomB)
   168  	depositBalance = sdk.NewCoins(depositA, depositB)
   169  
   170  	require.Equal(t, deposit, depositBalance)
   171  
   172  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   173  
   174  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   175  	require.NoError(t, err)
   176  
   177  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   178  	pool := pools[0]
   179  
   180  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   181  
   182  	depositMsg := types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit)
   183  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   184  	require.NoError(t, err)
   185  
   186  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
   187  	require.True(t, found)
   188  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
   189  	require.Equal(t, 1, len(msgs))
   190  
   191  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
   192  	require.NoError(t, err)
   193  
   194  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   195  	depositorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom)
   196  	require.Equal(t, poolCoin.Sub(poolCoinBefore), depositorBalance.Amount)
   197  }
   198  
   199  func TestExecuteDepositTruncation(t *testing.T) {
   200  	simapp, ctx := createTestInput()
   201  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   202  	params := simapp.LiquidityKeeper.GetParams(ctx)
   203  
   204  	poolTypeID := types.DefaultPoolTypeID
   205  	addrs := app.AddTestAddrs(simapp, ctx, 4, params.PoolCreationFee)
   206  
   207  	denomA := "uETH"
   208  	denomB := "uUSD"
   209  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   210  
   211  	initDeposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(10000000*1000000)), sdk.NewCoin(denomB, sdk.NewInt(200000000*1000000)))
   212  	app.SaveAccount(simapp, ctx, addrs[0], initDeposit)
   213  	app.SaveAccount(simapp, ctx, addrs[1], initDeposit)
   214  
   215  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   216  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   217  	depositBalance := sdk.NewCoins(depositA, depositB)
   218  
   219  	require.Equal(t, initDeposit, depositBalance)
   220  
   221  	depositA = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomA)
   222  	depositB = simapp.BankKeeper.GetBalance(ctx, addrs[1], denomB)
   223  	depositBalance = sdk.NewCoins(depositA, depositB)
   224  
   225  	require.Equal(t, initDeposit, depositBalance)
   226  
   227  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   228  
   229  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   230  	require.NoError(t, err)
   231  
   232  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   233  	pool := pools[0]
   234  
   235  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   236  
   237  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(19*1000000)), sdk.NewCoin(denomB, sdk.NewInt(400*1000000)))
   238  	depositMsg := types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit)
   239  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   240  	require.NoError(t, err)
   241  
   242  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
   243  	require.True(t, found)
   244  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
   245  	require.Equal(t, 1, len(msgs))
   246  
   247  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
   248  	require.NoError(t, err)
   249  
   250  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   251  	depositorBalancePoolCoin := simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom)
   252  	depositorBalanceDenomA := simapp.BankKeeper.GetBalance(ctx, addrs[1], denomA)
   253  	depositorBalanceDenomB := simapp.BankKeeper.GetBalance(ctx, addrs[1], denomB)
   254  	require.Equal(t, depositBalance.AmountOf(denomA).Sub(sdk.NewInt(10*1000000)), depositorBalanceDenomA.Amount)
   255  	require.Equal(t, depositBalance.AmountOf(denomB).Sub(sdk.NewInt(200*1000000)), depositorBalanceDenomB.Amount)
   256  	require.Equal(t, depositorBalancePoolCoin.Amount, sdk.OneInt())
   257  	require.Equal(t, poolCoin.Sub(poolCoinBefore), depositorBalancePoolCoin.Amount)
   258  }
   259  
   260  func TestDepositDecimalTruncation(t *testing.T) {
   261  	simapp, ctx := createTestInput()
   262  	params := simapp.LiquidityKeeper.GetParams(ctx)
   263  	params.WithdrawFeeRate = sdk.ZeroDec()
   264  
   265  	// Suppose that atom price is $40.
   266  	denomA := "uatom"
   267  	denomB := "uusd"
   268  
   269  	addrs := app.AddTestAddrs(simapp, ctx, 2, sdk.NewCoins())
   270  	creator, depositor := addrs[0], addrs[1]
   271  
   272  	// Create a pool with initial value of $10M.
   273  	depositCoins := sdk.NewCoins(sdk.NewInt64Coin(denomA, 125000*1000000), sdk.NewInt64Coin(denomB, 5000000*1000000))
   274  	err := app.FundAccount(simapp, ctx, creator, depositCoins.Add(params.PoolCreationFee...))
   275  	require.NoError(t, err)
   276  	pool, err := simapp.LiquidityKeeper.CreatePool(ctx, types.NewMsgCreatePool(creator, types.DefaultPoolTypeID, depositCoins))
   277  	require.NoError(t, err)
   278  
   279  	// Deposit 19$.
   280  	depositCoins = sdk.NewCoins(sdk.NewInt64Coin(denomA, 0.2375*1000000), sdk.NewInt64Coin(denomB, 9.5*1000000))
   281  	err = app.FundAccount(simapp, ctx, depositor, depositCoins)
   282  	require.NoError(t, err)
   283  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(depositor, pool.Id, depositCoins))
   284  	require.NoError(t, err)
   285  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   286  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   287  	depositMsgStates := simapp.LiquidityKeeper.GetAllDepositMsgStates(ctx)
   288  	require.Len(t, depositMsgStates, 0)
   289  
   290  	depositorPoolCoin := simapp.BankKeeper.GetBalance(ctx, depositor, pool.PoolCoinDenom)
   291  	require.True(sdk.IntEq(t, sdk.OneInt(), depositorPoolCoin.Amount))
   292  	require.True(t, simapp.BankKeeper.GetBalance(ctx, depositor, denomA).Amount.IsPositive())
   293  	require.True(t, simapp.BankKeeper.GetBalance(ctx, depositor, denomB).Amount.IsPositive())
   294  
   295  	// Withdraw.
   296  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(depositor, pool.Id, depositorPoolCoin))
   297  	require.NoError(t, err)
   298  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   299  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   300  	withdrawMsgStates := simapp.LiquidityKeeper.GetAllWithdrawMsgStates(ctx)
   301  	require.Len(t, withdrawMsgStates, 0)
   302  
   303  	depositorCoinsDelta := depositCoins.Sub(simapp.BankKeeper.GetAllBalances(ctx, depositor))
   304  	require.True(t, depositorCoinsDelta.IsZero())
   305  }
   306  
   307  func TestDepositDecimalTruncation2(t *testing.T) {
   308  	simapp, ctx := createTestInput()
   309  	params := simapp.LiquidityKeeper.GetParams(ctx)
   310  	params.WithdrawFeeRate = sdk.ZeroDec()
   311  
   312  	// Suppose that atom price is $40.
   313  	denomA := "uatom"
   314  	denomB := "uusd"
   315  
   316  	addrs := app.AddTestAddrs(simapp, ctx, 2, sdk.NewCoins())
   317  	creator, depositor := addrs[0], addrs[1]
   318  
   319  	// Create a pool with initial value of $10M.
   320  	depositCoins := sdk.NewCoins(sdk.NewInt64Coin(denomA, 125000*1000000), sdk.NewInt64Coin(denomB, 5000000*1000000))
   321  	err := app.FundAccount(simapp, ctx, creator, depositCoins.Add(params.PoolCreationFee...))
   322  	require.NoError(t, err)
   323  	pool, err := simapp.LiquidityKeeper.CreatePool(ctx, types.NewMsgCreatePool(creator, types.DefaultPoolTypeID, depositCoins))
   324  	require.NoError(t, err)
   325  
   326  	// Deposit 9$.
   327  	depositCoins = sdk.NewCoins(sdk.NewInt64Coin(denomA, 0.1125*1000000), sdk.NewInt64Coin(denomB, 4.5*1000000))
   328  	err = app.FundAccount(simapp, ctx, depositor, depositCoins)
   329  	require.NoError(t, err)
   330  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(depositor, pool.Id, depositCoins))
   331  	require.NoError(t, err)
   332  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   333  
   334  	depositorPoolCoin := simapp.BankKeeper.GetBalance(ctx, depositor, pool.PoolCoinDenom)
   335  	require.True(sdk.IntEq(t, sdk.ZeroInt(), depositorPoolCoin.Amount))
   336  	require.True(t, simapp.BankKeeper.GetAllBalances(ctx, depositor).IsEqual(depositCoins))
   337  	depositMsgStates := simapp.LiquidityKeeper.GetAllDepositMsgStates(ctx)
   338  	require.Len(t, depositMsgStates, 1)
   339  	require.True(t, depositMsgStates[0].Executed)
   340  	require.False(t, depositMsgStates[0].Succeeded)
   341  	require.True(t, depositMsgStates[0].ToBeDeleted)
   342  
   343  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   344  	depositMsgStates = simapp.LiquidityKeeper.GetAllDepositMsgStates(ctx)
   345  	require.Len(t, depositMsgStates, 0)
   346  }
   347  
   348  func TestReserveCoinLimit(t *testing.T) {
   349  	simapp, ctx := createTestInput()
   350  	params := types.DefaultParams()
   351  	params.MaxReserveCoinAmount = sdk.NewInt(1000000000000)
   352  	simapp.LiquidityKeeper.SetParams(ctx, params)
   353  
   354  	poolTypeID := types.DefaultPoolTypeID
   355  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   356  
   357  	denomA := "uETH"
   358  	denomB := "uUSD"
   359  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   360  
   361  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, params.MaxReserveCoinAmount), sdk.NewCoin(denomB, sdk.NewInt(1000000)))
   362  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   363  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   364  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   365  	depositBalance := sdk.NewCoins(depositA, depositB)
   366  	require.Equal(t, deposit, depositBalance)
   367  
   368  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   369  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
   370  	require.Equal(t, types.ErrExceededReserveCoinLimit, err)
   371  
   372  	params.MaxReserveCoinAmount = sdk.ZeroInt()
   373  	simapp.LiquidityKeeper.SetParams(ctx, params)
   374  	_, err = simapp.LiquidityKeeper.CreatePool(ctx, msg)
   375  	require.NoError(t, err)
   376  
   377  	params.MaxReserveCoinAmount = sdk.NewInt(1000000000000)
   378  	simapp.LiquidityKeeper.SetParams(ctx, params)
   379  
   380  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   381  	pool := pools[0]
   382  
   383  	deposit = sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(1000000)), sdk.NewCoin(denomB, sdk.NewInt(1000000)))
   384  	app.SaveAccount(simapp, ctx, addrs[1], deposit)
   385  	depositMsg := types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit)
   386  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   387  	require.Equal(t, types.ErrExceededReserveCoinLimit, err)
   388  
   389  	params.MaxReserveCoinAmount = sdk.ZeroInt()
   390  	simapp.LiquidityKeeper.SetParams(ctx, params)
   391  
   392  	depositMsg = types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit)
   393  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   394  	require.NoError(t, err)
   395  
   396  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
   397  	require.True(t, found)
   398  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
   399  	require.Equal(t, 1, len(msgs))
   400  
   401  	simapp.LiquidityKeeper.ExecutePoolBatches(ctx)
   402  	require.NoError(t, err)
   403  
   404  	ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
   405  	simapp.LiquidityKeeper.DeleteAndInitPoolBatches(ctx)
   406  	app.SaveAccount(simapp, ctx, addrs[1], deposit)
   407  	depositMsg = types.NewMsgDepositWithinBatch(addrs[1], pool.Id, deposit)
   408  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   409  	require.NoError(t, err)
   410  
   411  	params.MaxReserveCoinAmount = sdk.NewInt(1000000000000)
   412  	simapp.LiquidityKeeper.SetParams(ctx, params)
   413  
   414  	poolBatch, found = simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
   415  	require.True(t, found)
   416  	msgs = simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
   417  	require.Equal(t, 1, len(msgs))
   418  
   419  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
   420  	require.Equal(t, types.ErrExceededReserveCoinLimit, err)
   421  }
   422  
   423  func TestExecuteWithdrawal(t *testing.T) {
   424  	simapp, ctx := createTestInput()
   425  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   426  	params := simapp.LiquidityKeeper.GetParams(ctx)
   427  
   428  	poolTypeID := types.DefaultPoolTypeID
   429  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   430  
   431  	denomA := "uETH"
   432  	denomB := "uUSD"
   433  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   434  
   435  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   436  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   437  
   438  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   439  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   440  	depositBalance := sdk.NewCoins(depositA, depositB)
   441  
   442  	require.Equal(t, deposit, depositBalance)
   443  
   444  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   445  
   446  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   447  	require.NoError(t, err)
   448  
   449  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   450  	pool := pools[0]
   451  
   452  	// Case for normal withdrawing
   453  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   454  	withdrawerPoolCoinBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   455  
   456  	require.Equal(t, poolCoinBefore, withdrawerPoolCoinBefore.Amount)
   457  	withdrawMsg := types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, withdrawerPoolCoinBefore.Amount.QuoRaw(2)))
   458  
   459  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   460  	require.NoError(t, err)
   461  
   462  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   463  	require.True(t, found)
   464  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   465  	require.Equal(t, 1, len(msgs))
   466  
   467  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   468  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   469  
   470  	poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   471  	withdrawerPoolCoinAfter := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   472  
   473  	require.Equal(t, poolCoinAfter, poolCoinBefore.QuoRaw(2))
   474  	require.Equal(t, withdrawerPoolCoinAfter.Amount, withdrawerPoolCoinBefore.Amount.QuoRaw(2))
   475  	withdrawerDenomABalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   476  	withdrawerDenomBBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   477  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[0]).QuoRaw(2).ToDec().Mul(sdk.OneDec().Sub(params.WithdrawFeeRate)).TruncateInt(), withdrawerDenomABalance.Amount)
   478  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]).QuoRaw(2).ToDec().Mul(sdk.OneDec().Sub(params.WithdrawFeeRate)).TruncateInt(), withdrawerDenomBBalance.Amount)
   479  
   480  	// Case for withdrawing all reserve coins
   481  	poolCoinBefore = simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   482  	withdrawerPoolCoinBefore = simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   483  
   484  	require.Equal(t, poolCoinBefore, withdrawerPoolCoinBefore.Amount)
   485  	withdrawMsg = types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, poolCoinBefore))
   486  
   487  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   488  	require.NoError(t, err)
   489  
   490  	poolBatch, found = simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   491  	require.True(t, found)
   492  	msgs = simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   493  	require.Equal(t, 1, len(msgs))
   494  
   495  	err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, msgs[0], poolBatch)
   496  	require.NoError(t, err)
   497  
   498  	poolCoinAfter = simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   499  	withdrawerPoolCoinAfter = simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   500  
   501  	require.True(t, true, poolCoinAfter.IsZero())
   502  	require.True(t, true, withdrawerPoolCoinAfter.IsZero())
   503  	withdrawerDenomABalance = simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   504  	withdrawerDenomBBalance = simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   505  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[0]), withdrawerDenomABalance.Amount)
   506  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]), withdrawerDenomBBalance.Amount)
   507  }
   508  
   509  func TestSmallWithdrawalCase(t *testing.T) {
   510  	simapp, ctx := createTestInput()
   511  	params := types.DefaultParams()
   512  	params.InitPoolCoinMintAmount = sdk.NewInt(1_000000_000000)
   513  	simapp.LiquidityKeeper.SetParams(ctx, params)
   514  
   515  	poolTypeID := types.DefaultPoolTypeID
   516  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   517  
   518  	denomA := "uETH"
   519  	denomB := "uUSD"
   520  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   521  
   522  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(1250001*1000000)), sdk.NewCoin(denomB, sdk.NewInt(9*1000000)))
   523  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   524  
   525  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   526  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   527  	depositBalance := sdk.NewCoins(depositA, depositB)
   528  
   529  	require.Equal(t, deposit, depositBalance)
   530  
   531  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   532  
   533  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   534  	require.NoError(t, err)
   535  
   536  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   537  	pool := pools[0]
   538  
   539  	// Case for normal withdrawing
   540  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   541  	withdrawerPoolCoinBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   542  
   543  	withdrawerDenomABalanceBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   544  	withdrawerDenomBBalanceBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   545  
   546  	require.Equal(t, poolCoinBefore, withdrawerPoolCoinBefore.Amount)
   547  	withdrawMsg := types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, sdk.NewInt(1)))
   548  
   549  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   550  	require.NoError(t, err)
   551  
   552  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   553  	require.True(t, found)
   554  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   555  	require.Equal(t, 1, len(msgs))
   556  
   557  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   558  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   559  
   560  	poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   561  	withdrawerPoolCoinAfter := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   562  
   563  	require.Equal(t, poolCoinAfter, poolCoinBefore)
   564  	require.Equal(t, withdrawerPoolCoinAfter.Amount, withdrawerPoolCoinBefore.Amount)
   565  	withdrawerDenomABalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   566  	withdrawerDenomBBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   567  
   568  	reservePoolBalanceA := simapp.BankKeeper.GetBalance(ctx, pool.GetReserveAccount(), pool.ReserveCoinDenoms[0])
   569  	reservePoolBalanceB := simapp.BankKeeper.GetBalance(ctx, pool.GetReserveAccount(), pool.ReserveCoinDenoms[1])
   570  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[0]), reservePoolBalanceA.Amount)
   571  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]), reservePoolBalanceB.Amount)
   572  	require.Equal(t, withdrawerDenomABalanceBefore, withdrawerDenomABalance)
   573  	require.Equal(t, withdrawerDenomBBalanceBefore, withdrawerDenomBBalance)
   574  }
   575  
   576  func TestReinitializePool(t *testing.T) {
   577  	simapp, ctx := createTestInput()
   578  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   579  	params := simapp.LiquidityKeeper.GetParams(ctx)
   580  	params.WithdrawFeeRate = sdk.ZeroDec()
   581  	simapp.LiquidityKeeper.SetParams(ctx, params)
   582  
   583  	poolTypeID := types.DefaultPoolTypeID
   584  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   585  
   586  	denomA := "uETH"
   587  	denomB := "uUSD"
   588  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   589  
   590  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(100*1000000)))
   591  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   592  
   593  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   594  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   595  	depositBalance := sdk.NewCoins(depositA, depositB)
   596  
   597  	require.Equal(t, deposit, depositBalance)
   598  
   599  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   600  
   601  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   602  	require.NoError(t, err)
   603  
   604  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   605  	pool := pools[0]
   606  
   607  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   608  	withdrawerPoolCoinBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   609  
   610  	reserveCoins := simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
   611  	require.True(t, reserveCoins.IsEqual(deposit))
   612  
   613  	require.Equal(t, poolCoinBefore, withdrawerPoolCoinBefore.Amount)
   614  	withdrawMsg := types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, poolCoinBefore))
   615  
   616  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   617  	require.NoError(t, err)
   618  
   619  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   620  	require.True(t, found)
   621  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   622  	require.Equal(t, 1, len(msgs))
   623  
   624  	err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, msgs[0], poolBatch)
   625  	require.NoError(t, err)
   626  
   627  	poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   628  	withdrawerPoolCoinAfter := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   629  	require.True(t, true, poolCoinAfter.IsZero())
   630  	require.True(t, true, withdrawerPoolCoinAfter.IsZero())
   631  	withdrawerDenomABalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   632  	withdrawerDenomBBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   633  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[0]), withdrawerDenomABalance.Amount)
   634  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]), withdrawerDenomBBalance.Amount)
   635  
   636  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
   637  	require.True(t, reserveCoins.IsZero())
   638  
   639  	// error when swap request to depleted pool
   640  	offerCoin := sdk.NewCoin(denomA, withdrawerDenomABalance.Amount.QuoRaw(2))
   641  	swapMsg := types.NewMsgSwapWithinBatch(addrs[0], pool.Id, types.DefaultSwapTypeID, offerCoin, denomB, sdk.MustNewDecFromStr("0.1"), params.SwapFeeRate)
   642  	_, err = simapp.LiquidityKeeper.SwapWithinBatch(ctx, swapMsg, 0)
   643  	require.ErrorIs(t, err, types.ErrDepletedPool)
   644  
   645  	depositMsg := types.NewMsgDepositWithinBatch(addrs[0], pool.Id, deposit)
   646  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
   647  	require.NoError(t, err)
   648  
   649  	depositMsgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
   650  	require.Equal(t, 1, len(depositMsgs))
   651  
   652  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, depositMsgs[0], poolBatch)
   653  	require.NoError(t, err)
   654  
   655  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   656  	depositorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   657  	require.Equal(t, poolCoin, depositorBalance.Amount)
   658  
   659  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
   660  	require.True(t, reserveCoins.IsEqual(deposit))
   661  }
   662  
   663  func TestReserveAccManipulation(t *testing.T) {
   664  	simapp, ctx := createTestInput()
   665  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   666  	params := simapp.LiquidityKeeper.GetParams(ctx)
   667  
   668  	poolTypeID := types.DefaultPoolTypeID
   669  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   670  
   671  	denomA := "uETH"
   672  	denomB := "uUSD"
   673  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   674  
   675  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   676  
   677  	// depositor, withdrawer
   678  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   679  	// reserveAccount manipulator
   680  	app.SaveAccount(simapp, ctx, addrs[1], deposit)
   681  
   682  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   683  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   684  	depositBalance := sdk.NewCoins(depositA, depositB)
   685  
   686  	// reserveAcc manipulation coinA
   687  	manipulationReserveA1 := sdk.NewCoin(denomA, sdk.NewInt(30*1000000))
   688  	manipulationReserveA2 := sdk.NewCoin(denomA, sdk.NewInt(70*1000000))
   689  	// reserveAcc manipulation coin other than reserve coins
   690  	manipulationReserveOther := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100*1000000))
   691  	// manipulated reserve coinA
   692  	addedDepositA := depositA.Add(manipulationReserveA1).Add(manipulationReserveA2)
   693  
   694  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   695  
   696  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
   697  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   698  	pool := pools[0]
   699  
   700  	reserveAcc := pool.GetReserveAccount()
   701  	reserveAccBalances := simapp.BankKeeper.GetAllBalances(ctx, reserveAcc)
   702  	require.Equal(t, reserveAccBalances, sdk.NewCoins(depositA, depositB))
   703  
   704  	// send coin to manipulate reserve account
   705  	simapp.BankKeeper.SendCoins(ctx, addrs[1], reserveAcc, sdk.NewCoins(manipulationReserveA1))
   706  	metadata := simapp.LiquidityKeeper.GetPoolMetaData(ctx, pool)
   707  	require.Equal(t, depositA.Add(manipulationReserveA1).Amount, metadata.ReserveCoins.AmountOf(denomA))
   708  
   709  	poolCoinBefore := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   710  	withdrawerPoolCoinBefore := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   711  	withdrawMsg := types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, withdrawerPoolCoinBefore.Amount.QuoRaw(2)))
   712  	simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   713  
   714  	poolBatch, _ := simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   715  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   716  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   717  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   718  
   719  	// send coin to manipulate reserve account
   720  	simapp.BankKeeper.SendCoins(ctx, addrs[1], reserveAcc, sdk.NewCoins(manipulationReserveA2))
   721  	simapp.BankKeeper.SendCoins(ctx, addrs[1], reserveAcc, sdk.NewCoins(manipulationReserveOther))
   722  	reserveAccBalances = simapp.BankKeeper.GetAllBalances(ctx, reserveAcc)
   723  	metadata = simapp.LiquidityKeeper.GetPoolMetaData(ctx, pool)
   724  	require.NotEqual(t, manipulationReserveOther, metadata.ReserveCoins.AmountOf(sdk.DefaultBondDenom))
   725  
   726  	// Case for withdrawing all reserve coins after manipulation
   727  	poolCoinBefore = simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   728  	withdrawerPoolCoinBefore = simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.PoolCoinDenom)
   729  	withdrawMsg = types.NewMsgWithdrawWithinBatch(addrs[0], pool.Id, sdk.NewCoin(pool.PoolCoinDenom, poolCoinBefore))
   730  
   731  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, withdrawMsg)
   732  	require.NoError(t, err)
   733  
   734  	poolBatch, _ = simapp.LiquidityKeeper.GetPoolBatch(ctx, withdrawMsg.PoolId)
   735  	msgs = simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
   736  
   737  	err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, msgs[0], poolBatch)
   738  	require.NoError(t, err)
   739  
   740  	withdrawerDenomABalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[0])
   741  	withdrawerDenomBBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pool.ReserveCoinDenoms[1])
   742  	withdrawerDenomOtherBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], sdk.DefaultBondDenom)
   743  	require.Equal(t, addedDepositA, withdrawerDenomABalance)
   744  	require.Equal(t, deposit.AmountOf(pool.ReserveCoinDenoms[1]), withdrawerDenomBBalance.Amount)
   745  	require.NotEqual(t, manipulationReserveOther, withdrawerDenomOtherBalance)
   746  }
   747  
   748  func TestGetLiquidityPoolMetadata(t *testing.T) {
   749  	simapp, ctx := createTestInput()
   750  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   751  	params := simapp.LiquidityKeeper.GetParams(ctx)
   752  
   753  	poolTypeID := types.DefaultPoolTypeID
   754  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   755  
   756  	denomA := "uETH"
   757  	denomB := "uUSD"
   758  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   759  
   760  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   761  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   762  
   763  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   764  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   765  	depositBalance := sdk.NewCoins(depositA, depositB)
   766  
   767  	require.Equal(t, deposit, depositBalance)
   768  
   769  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   770  
   771  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
   772  	require.NoError(t, err)
   773  
   774  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   775  	require.Equal(t, 1, len(pools))
   776  	require.Equal(t, uint64(1), pools[0].Id)
   777  	require.Equal(t, uint64(1), simapp.LiquidityKeeper.GetNextPoolID(ctx)-1)
   778  	require.Equal(t, denomA, pools[0].ReserveCoinDenoms[0])
   779  	require.Equal(t, denomB, pools[0].ReserveCoinDenoms[1])
   780  
   781  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])
   782  	creatorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom)
   783  	require.Equal(t, poolCoin, creatorBalance.Amount)
   784  
   785  	_, err = simapp.LiquidityKeeper.CreatePool(ctx, msg)
   786  	require.ErrorIs(t, err, types.ErrPoolAlreadyExists)
   787  
   788  	metaData := simapp.LiquidityKeeper.GetPoolMetaData(ctx, pools[0])
   789  	require.Equal(t, pools[0].Id, metaData.PoolId)
   790  
   791  	reserveCoin := simapp.LiquidityKeeper.GetReserveCoins(ctx, pools[0])
   792  	require.Equal(t, reserveCoin, metaData.ReserveCoins)
   793  	require.Equal(t, msg.DepositCoins, metaData.ReserveCoins)
   794  
   795  	totalSupply := sdk.NewCoin(pools[0].PoolCoinDenom, simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0]))
   796  	require.Equal(t, totalSupply, metaData.PoolCoinTotalSupply)
   797  	require.Equal(t, creatorBalance, metaData.PoolCoinTotalSupply)
   798  }
   799  
   800  func TestIsPoolCoinDenom(t *testing.T) {
   801  	simapp, ctx := createTestInput()
   802  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   803  	params := simapp.LiquidityKeeper.GetParams(ctx)
   804  
   805  	poolTypeID := types.DefaultPoolTypeID
   806  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   807  
   808  	denomA := "denomA"
   809  	denomB := "denomB"
   810  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   811  
   812  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   813  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   814  
   815  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   816  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   817  	depositBalance := sdk.NewCoins(depositA, depositB)
   818  
   819  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   820  
   821  	pool, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
   822  	require.NoError(t, err)
   823  	getPool, found := simapp.LiquidityKeeper.GetPool(ctx, pool.Id)
   824  	require.True(t, found)
   825  	require.Equal(t, pool, getPool)
   826  
   827  	require.Equal(t, "denomA/denomB/1", pool.Name())
   828  	poolCoinDenom := types.GetPoolCoinDenom(pool.Name())
   829  	require.Equal(t, pool.PoolCoinDenom, poolCoinDenom)
   830  	require.True(t, simapp.LiquidityKeeper.IsPoolCoinDenom(ctx, pool.PoolCoinDenom))
   831  	require.False(t, simapp.LiquidityKeeper.IsPoolCoinDenom(ctx, pool.Name()))
   832  }
   833  
   834  func TestGetPoolByReserveAccIndex(t *testing.T) {
   835  	simapp, ctx := createTestInput()
   836  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
   837  	params := simapp.LiquidityKeeper.GetParams(ctx)
   838  
   839  	poolTypeID := types.DefaultPoolTypeID
   840  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
   841  
   842  	denomA := "uETH"
   843  	denomB := "uUSD"
   844  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
   845  
   846  	deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
   847  	app.SaveAccount(simapp, ctx, addrs[0], deposit)
   848  
   849  	depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
   850  	depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
   851  	depositBalance := sdk.NewCoins(depositA, depositB)
   852  
   853  	require.Equal(t, deposit, depositBalance)
   854  
   855  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, depositBalance)
   856  	pool, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
   857  	require.NoError(t, err)
   858  
   859  	fmt.Println(pool)
   860  	poolStored, found := simapp.LiquidityKeeper.GetPool(ctx, pool.Id)
   861  	require.True(t, found)
   862  	require.Equal(t, pool, poolStored)
   863  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
   864  	require.Equal(t, pool, pools[0])
   865  
   866  	poolByReserveAcc, found := simapp.LiquidityKeeper.GetPoolByReserveAccIndex(ctx, pool.GetReserveAccount())
   867  	require.True(t, found)
   868  	require.Equal(t, pool, poolByReserveAcc)
   869  
   870  	poolCoinDenom := types.GetPoolCoinDenom(pool.Name())
   871  	require.Equal(t, pool.PoolCoinDenom, poolCoinDenom)
   872  	require.True(t, simapp.LiquidityKeeper.IsPoolCoinDenom(ctx, pool.PoolCoinDenom))
   873  	require.False(t, simapp.LiquidityKeeper.IsPoolCoinDenom(ctx, pool.Name()))
   874  	//SetPoolByReserveAccIndex
   875  }
   876  
   877  func TestDepositWithdrawEdgecase(t *testing.T) {
   878  	for seed := int64(0); seed < 20; seed++ {
   879  		r := rand.New(rand.NewSource(seed))
   880  
   881  		simapp, ctx := createTestInput()
   882  		params := simapp.LiquidityKeeper.GetParams(ctx)
   883  
   884  		X := params.MinInitDepositAmount.Add(app.GetRandRange(r, 0, 1_000_000))
   885  		Y := params.MinInitDepositAmount.Add(app.GetRandRange(r, 0, 1_000_000))
   886  
   887  		creatorCoins := sdk.NewCoins(sdk.NewCoin(DenomX, X), sdk.NewCoin(DenomY, Y))
   888  		creatorAddr := app.AddRandomTestAddr(simapp, ctx, creatorCoins.Add(params.PoolCreationFee...))
   889  
   890  		pool, err := simapp.LiquidityKeeper.CreatePool(ctx, types.NewMsgCreatePool(creatorAddr, types.DefaultPoolTypeID, creatorCoins))
   891  		require.NoError(t, err)
   892  
   893  		for i := 0; i < 500; i++ {
   894  			liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   895  			type action int
   896  			const (
   897  				deposit action = iota + 1
   898  				withdraw
   899  			)
   900  			actions := []action{}
   901  			balanceX := simapp.BankKeeper.GetBalance(ctx, creatorAddr, DenomX)
   902  			balanceY := simapp.BankKeeper.GetBalance(ctx, creatorAddr, DenomY)
   903  			balancePoolCoin := simapp.BankKeeper.GetBalance(ctx, creatorAddr, pool.PoolCoinDenom)
   904  			if balanceX.IsPositive() || balanceY.IsPositive() {
   905  				actions = append(actions, deposit)
   906  			}
   907  			if balancePoolCoin.Amount.GT(sdk.OneInt()) {
   908  				actions = append(actions, withdraw)
   909  			}
   910  			require.Positive(t, len(actions))
   911  			switch actions[r.Intn(len(actions))] {
   912  			case deposit:
   913  				depositAmtA := sdk.OneInt().Add(sdk.NewInt(r.Int63n(balanceX.Amount.Int64())))
   914  				depositAmtB := sdk.OneInt().Add(sdk.NewInt(r.Int63n(balanceY.Amount.Int64())))
   915  				depositCoins := sdk.NewCoins(sdk.NewCoin(DenomX, depositAmtA), sdk.NewCoin(DenomY, depositAmtB))
   916  				_, err := simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(
   917  					creatorAddr, pool.Id, depositCoins))
   918  				require.NoError(t, err)
   919  			case withdraw:
   920  				totalPoolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
   921  				withdrawAmt := sdk.OneInt().Add(sdk.NewInt(r.Int63n(balancePoolCoin.Amount.Int64())))
   922  				withdrawCoin := sdk.NewCoin(pool.PoolCoinDenom, sdk.MinInt(totalPoolCoin.Sub(sdk.OneInt()), withdrawAmt))
   923  				_, err := simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(
   924  					creatorAddr, pool.Id, withdrawCoin))
   925  				require.NoError(t, err)
   926  			}
   927  
   928  			liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   929  		}
   930  	}
   931  }
   932  
   933  func TestWithdrawEdgecase(t *testing.T) {
   934  	simapp, ctx := createTestInput()
   935  	params := simapp.LiquidityKeeper.GetParams(ctx)
   936  
   937  	X, Y := sdk.NewInt(1_000_000), sdk.NewInt(10_000_000)
   938  
   939  	depositCoins := sdk.NewCoins(sdk.NewCoin(DenomX, X), sdk.NewCoin(DenomY, Y))
   940  	creatorAddr := app.AddRandomTestAddr(simapp, ctx, depositCoins.Add(params.PoolCreationFee...))
   941  
   942  	pool, err := simapp.LiquidityKeeper.CreatePool(ctx, types.NewMsgCreatePool(creatorAddr, types.DefaultPoolTypeID, depositCoins))
   943  	require.NoError(t, err)
   944  
   945  	creatorBalance := simapp.BankKeeper.GetBalance(ctx, creatorAddr, pool.PoolCoinDenom).Sub(sdk.NewCoin(pool.PoolCoinDenom, sdk.NewInt(2)))
   946  
   947  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   948  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, creatorBalance))
   949  	require.NoError(t, err)
   950  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   951  
   952  	fmt.Println(simapp.LiquidityKeeper.GetPoolCoinTotal(ctx, pool))
   953  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, creatorAddr))
   954  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, pool.GetReserveAccount()))
   955  
   956  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   957  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewCoin(pool.PoolCoinDenom, sdk.OneInt())))
   958  	require.NoError(t, err)
   959  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   960  
   961  	fmt.Println(simapp.LiquidityKeeper.GetPoolCoinTotal(ctx, pool))
   962  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, creatorAddr))
   963  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, pool.GetReserveAccount()))
   964  
   965  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewCoin(pool.PoolCoinDenom, sdk.OneInt())))
   966  	require.NoError(t, err)
   967  
   968  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   969  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   970  
   971  	fmt.Println(simapp.LiquidityKeeper.GetPoolCoinTotal(ctx, pool))
   972  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, creatorAddr))
   973  	fmt.Println(simapp.BankKeeper.GetAllBalances(ctx, pool.GetReserveAccount()))
   974  }
   975  
   976  func TestWithdrawEdgecase2(t *testing.T) {
   977  	simapp, ctx, pool, creatorAddr, err := createTestPool(sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 1500000))
   978  	require.NoError(t, err)
   979  
   980  	for i := 0; i < 1002; i++ {
   981  		liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   982  		_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewInt64Coin(pool.PoolCoinDenom, 998)))
   983  		require.NoError(t, err)
   984  		liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   985  	}
   986  
   987  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   988  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewInt64Coin(pool.PoolCoinDenom, 1)))
   989  	require.NoError(t, err)
   990  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
   991  }
   992  
   993  func TestWithdrawSmallAmount(t *testing.T) {
   994  	simapp, ctx, pool, creatorAddr, err := createTestPool(sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 1500000))
   995  	require.NoError(t, err)
   996  
   997  	require.NotPanics(t, func() {
   998  		liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
   999  		_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewInt64Coin(pool.PoolCoinDenom, 1)))
  1000  		require.NoError(t, err)
  1001  		liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1002  	})
  1003  }
  1004  
  1005  func TestGetReserveCoins(t *testing.T) {
  1006  	simapp, ctx, pool, creatorAddr, err := createTestPool(sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 1000000))
  1007  	require.NoError(t, err)
  1008  
  1009  	reserveCoins := simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1010  	require.Len(t, reserveCoins, 2)
  1011  	require.True(t, reserveCoins.AmountOf(DenomX).Equal(sdk.NewInt(1000000)))
  1012  	require.True(t, reserveCoins.AmountOf(DenomY).Equal(sdk.NewInt(1000000)))
  1013  
  1014  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1015  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, sdk.NewInt64Coin(pool.PoolCoinDenom, 1000000)))
  1016  	require.NoError(t, err)
  1017  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1018  
  1019  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1020  	require.Len(t, reserveCoins, 2)
  1021  	require.True(t, reserveCoins.AmountOf(DenomX).IsZero())
  1022  	require.True(t, reserveCoins.AmountOf(DenomY).IsZero())
  1023  }
  1024  
  1025  func TestDepositToDepletedPool(t *testing.T) {
  1026  	simapp, ctx, pool, creatorAddr, err := createTestPool(sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 1000000))
  1027  	require.NoError(t, err)
  1028  	params := simapp.LiquidityKeeper.GetParams(ctx)
  1029  
  1030  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1031  	pc := simapp.BankKeeper.GetBalance(ctx, creatorAddr, pool.PoolCoinDenom)
  1032  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(creatorAddr, pool.Id, pc))
  1033  	require.NoError(t, err)
  1034  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1035  
  1036  	reserveCoins := simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1037  	require.True(t, reserveCoins.AmountOf(DenomX).IsZero())
  1038  	require.True(t, reserveCoins.AmountOf(DenomY).IsZero())
  1039  
  1040  	require.True(t, simapp.LiquidityKeeper.IsDepletedPool(ctx, pool))
  1041  
  1042  	err = simapp.BankKeeper.SendCoins(ctx, creatorAddr, pool.GetReserveAccount(), sdk.NewCoins(sdk.NewInt64Coin(DenomX, 10000)))
  1043  	require.NoError(t, err)
  1044  
  1045  	// Deposit request must be rejected since the pool is depleted and
  1046  	// depositing coins amount is smaller than MinInitDepositAmount.
  1047  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1048  	depositCoins := sdk.NewCoins(sdk.NewInt64Coin(DenomX, 10000), sdk.NewInt64Coin(DenomY, 10000))
  1049  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(creatorAddr, pool.Id, depositCoins))
  1050  	require.NoError(t, err)
  1051  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1052  
  1053  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1054  	require.True(t, reserveCoins.AmountOf(DenomX).Equal(sdk.NewInt(10000)))
  1055  	require.True(t, reserveCoins.AmountOf(DenomY).IsZero())
  1056  	creatorCoins := simapp.BankKeeper.GetAllBalances(ctx, creatorAddr)
  1057  	require.True(t, creatorCoins.AmountOf(DenomX).Equal(sdk.NewInt(990000)))
  1058  	require.True(t, creatorCoins.AmountOf(DenomY).Equal(sdk.NewInt(1000000)))
  1059  
  1060  	// This time the request will be accepted since depositCoins + reserveCoins > MinInitDepositAmount.
  1061  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1062  	depositCoins = sdk.NewCoins(sdk.NewInt64Coin(DenomX, 990000), sdk.NewInt64Coin(DenomY, 1000000))
  1063  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(creatorAddr, pool.Id, depositCoins))
  1064  	require.NoError(t, err)
  1065  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1066  
  1067  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1068  	require.True(t, reserveCoins.AmountOf(DenomX).Equal(sdk.NewInt(1000000)))
  1069  	require.True(t, reserveCoins.AmountOf(DenomY).Equal(sdk.NewInt(1000000)))
  1070  	creatorCoins = simapp.BankKeeper.GetAllBalances(ctx, creatorAddr)
  1071  	require.True(t, creatorCoins.AmountOf(DenomX).Equal(sdk.NewInt(0)))
  1072  	require.True(t, creatorCoins.AmountOf(DenomY).Equal(sdk.NewInt(0)))
  1073  	require.True(t, creatorCoins.AmountOf(pool.PoolCoinDenom).Equal(params.InitPoolCoinMintAmount))
  1074  }
  1075  
  1076  func TestDepositWithCoinsSent(t *testing.T) {
  1077  	simapp, ctx, pool, _, err := createTestPool(sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 1000000))
  1078  	require.NoError(t, err)
  1079  
  1080  	// Send extra coins to the pool reserve account, which causes the pool price to change.
  1081  	// Any other coins(coins with denom "denomZ" here) than pool's reserve coins will not have any effect.
  1082  	extraCoins := sdk.NewCoins(
  1083  		sdk.NewInt64Coin(DenomX, 1000000), sdk.NewInt64Coin(DenomY, 2000000), sdk.NewInt64Coin("denomZ", 1000000))
  1084  	addr := app.AddRandomTestAddr(simapp, ctx, extraCoins)
  1085  	err = simapp.BankKeeper.SendCoins(ctx, addr, pool.GetReserveAccount(), extraCoins)
  1086  	require.NoError(t, err)
  1087  	reserveCoins := simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1088  	require.Len(t, reserveCoins, 2) // denomZ coins are ignored
  1089  	require.True(sdk.IntEq(t, sdk.NewInt(2000000), reserveCoins.AmountOf(DenomX)))
  1090  	require.True(sdk.IntEq(t, sdk.NewInt(3000000), reserveCoins.AmountOf(DenomY)))
  1091  
  1092  	// Add more coins to deposit.
  1093  	depositCoins := sdk.NewCoins(sdk.NewInt64Coin(DenomX, 3000000), sdk.NewInt64Coin(DenomY, 3000000))
  1094  	app.SaveAccount(simapp, ctx, addr, depositCoins)
  1095  
  1096  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1097  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, types.NewMsgDepositWithinBatch(addr, pool.Id, depositCoins))
  1098  	require.NoError(t, err)
  1099  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1100  
  1101  	reserveCoins = simapp.LiquidityKeeper.GetReserveCoins(ctx, pool)
  1102  	require.True(sdk.IntEq(t, sdk.NewInt(4000000), reserveCoins.AmountOf(DenomX)))
  1103  	require.True(sdk.IntEq(t, sdk.NewInt(6000000), reserveCoins.AmountOf(DenomY)))
  1104  	balances := simapp.BankKeeper.GetAllBalances(ctx, addr)
  1105  	require.True(sdk.IntEq(t, sdk.NewInt(1000000), balances.AmountOf(DenomX)))
  1106  	require.True(sdk.IntEq(t, sdk.NewInt(0), balances.AmountOf(DenomY)))
  1107  	require.True(sdk.IntEq(t, sdk.NewInt(1000000), balances.AmountOf(pool.PoolCoinDenom)))
  1108  }
  1109  
  1110  func TestCreatePoolEqualDenom(t *testing.T) {
  1111  	simapp, ctx := createTestInput()
  1112  	params := types.DefaultParams()
  1113  	simapp.LiquidityKeeper.SetParams(ctx, params)
  1114  	addrs := app.AddTestAddrs(simapp, ctx, 1, params.PoolCreationFee)
  1115  
  1116  	msg := types.NewMsgCreatePool(addrs[0], types.DefaultPoolTypeID,
  1117  		sdk.Coins{
  1118  			sdk.NewCoin(DenomA, sdk.NewInt(1000000)),
  1119  			sdk.NewCoin(DenomA, sdk.NewInt(1000000))})
  1120  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
  1121  	require.ErrorIs(t, err, types.ErrEqualDenom)
  1122  }
  1123  
  1124  func TestOverflowAndZeroCases(t *testing.T) {
  1125  	simapp, ctx := createTestInput()
  1126  	params := types.DefaultParams()
  1127  	simapp.LiquidityKeeper.SetParams(ctx, params)
  1128  	keeper.BatchLogicInvariantCheckFlag = false
  1129  
  1130  	poolTypeID := types.DefaultPoolTypeID
  1131  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
  1132  
  1133  	denomA := "uETH"
  1134  	denomB := "uUSD"
  1135  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
  1136  
  1137  	// Check overflow case on deposit
  1138  	deposit := sdk.NewCoins(
  1139  		sdk.NewCoin(denomA, sdk.NewInt(1_000_000)),
  1140  		sdk.NewCoin(denomB, sdk.NewInt(2_000_000_000_000*1_000_000).MulRaw(1_000_000)))
  1141  	hugeCoins := sdk.NewCoins(
  1142  		sdk.NewCoin(denomA, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000)),
  1143  		sdk.NewCoin(denomB, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000)))
  1144  	hugeCoins2 := sdk.NewCoins(
  1145  		sdk.NewCoin(denomA, sdk.NewInt(1_000_000_000_000_000_000)),
  1146  		sdk.NewCoin(denomB, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000)))
  1147  	app.SaveAccount(simapp, ctx, addrs[0], deposit.Add(hugeCoins.Add(hugeCoins2...)...))
  1148  
  1149  	msg := types.NewMsgCreatePool(addrs[0], poolTypeID, deposit)
  1150  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
  1151  	require.NoError(t, err)
  1152  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
  1153  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])
  1154  
  1155  	depositorBalance := simapp.BankKeeper.GetAllBalances(ctx, addrs[0])
  1156  	depositMsg := types.NewMsgDepositWithinBatch(addrs[0], pools[0].Id, hugeCoins)
  1157  	depositMsg2 := types.NewMsgDepositWithinBatch(addrs[0], pools[0].Id, hugeCoins2)
  1158  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
  1159  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg2)
  1160  	require.NoError(t, err)
  1161  
  1162  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
  1163  	require.True(t, found)
  1164  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
  1165  	require.Equal(t, 2, len(msgs))
  1166  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
  1167  	require.ErrorIs(t, err, types.ErrOverflowAmount)
  1168  	err = simapp.LiquidityKeeper.RefundDeposit(ctx, msgs[0], poolBatch)
  1169  	require.NoError(t, err)
  1170  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[1], poolBatch)
  1171  	require.ErrorIs(t, err, types.ErrOverflowAmount)
  1172  	err = simapp.LiquidityKeeper.RefundDeposit(ctx, msgs[1], poolBatch)
  1173  	require.NoError(t, err)
  1174  
  1175  	poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])
  1176  	depositorPoolCoinBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom)
  1177  	require.Equal(t, poolCoin, poolCoinAfter)
  1178  	require.Equal(t, poolCoinAfter, depositorPoolCoinBalance.Amount)
  1179  	require.Equal(t, depositorBalance.AmountOf(pools[0].PoolCoinDenom), depositorPoolCoinBalance.Amount)
  1180  
  1181  	hugeCoins3 := sdk.NewCoins(
  1182  		sdk.NewCoin(denomA, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000)),
  1183  		sdk.NewCoin(denomB, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000)))
  1184  	depositMsg = types.NewMsgDepositWithinBatch(addrs[0], pools[0].Id, hugeCoins3)
  1185  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
  1186  	require.NoError(t, err)
  1187  	msgs = simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
  1188  	require.Equal(t, 3, len(msgs))
  1189  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[2], poolBatch)
  1190  	require.NoError(t, err)
  1191  
  1192  	// Check overflow case on withdraw
  1193  	depositorPoolCoinBalance = simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom)
  1194  	_, err = simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(addrs[0], pools[0].Id, depositorPoolCoinBalance.SubAmount(sdk.NewInt(1))))
  1195  	require.NoError(t, err)
  1196  
  1197  	poolBatch, found = simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
  1198  	require.True(t, found)
  1199  	withdrawMsgs := simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
  1200  	require.Equal(t, 1, len(withdrawMsgs))
  1201  	err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, withdrawMsgs[0], poolBatch)
  1202  	require.ErrorIs(t, err, types.ErrOverflowAmount)
  1203  	err = simapp.LiquidityKeeper.RefundWithdrawal(ctx, withdrawMsgs[0], poolBatch)
  1204  	require.NoError(t, err)
  1205  
  1206  	// Check overflow, division by zero case on swap
  1207  	swapUserBalanceBefore := simapp.BankKeeper.GetAllBalances(ctx, addrs[0])
  1208  	offerCoinA := sdk.NewCoin(denomA, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000))
  1209  	orderPriceA := sdk.MustNewDecFromStr("110000000000000000000000000000000000000000000000000000000000.000000000000000001")
  1210  	offerCoinB := sdk.NewCoin(denomB, sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000))
  1211  	orderPriceB := sdk.MustNewDecFromStr("0.000000000000000001")
  1212  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1213  	_, err = simapp.LiquidityKeeper.SwapWithinBatch(
  1214  		ctx,
  1215  		types.NewMsgSwapWithinBatch(addrs[0], pools[0].Id, types.DefaultSwapTypeID, offerCoinA, denomB, orderPriceA, params.SwapFeeRate),
  1216  		0)
  1217  	require.ErrorIs(t, err, types.ErrOverflowAmount)
  1218  	_, err = simapp.LiquidityKeeper.SwapWithinBatch(
  1219  		ctx,
  1220  		types.NewMsgSwapWithinBatch(addrs[0], pools[0].Id, types.DefaultSwapTypeID, offerCoinB, denomA, orderPriceB, params.SwapFeeRate),
  1221  		0)
  1222  	require.NoError(t, err)
  1223  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1224  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1225  	swapUserBalanceAfter := simapp.BankKeeper.GetAllBalances(ctx, addrs[0])
  1226  	require.Equal(t, swapUserBalanceBefore, swapUserBalanceAfter)
  1227  	depositMsgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
  1228  	require.Equal(t, 0, len(depositMsgs))
  1229  	withdrawMsgs = simapp.LiquidityKeeper.GetAllPoolBatchWithdrawMsgStates(ctx, poolBatch)
  1230  	require.Equal(t, 0, len(withdrawMsgs))
  1231  	swapMsgs := simapp.LiquidityKeeper.GetAllPoolBatchSwapMsgStates(ctx, poolBatch)
  1232  	require.Equal(t, 0, len(swapMsgs))
  1233  }
  1234  
  1235  func TestExecuteBigDeposit(t *testing.T) {
  1236  	simapp, ctx := createTestInput()
  1237  	simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
  1238  	params := simapp.LiquidityKeeper.GetParams(ctx)
  1239  	keeper.BatchLogicInvariantCheckFlag = false
  1240  
  1241  	poolTypeID := types.DefaultPoolTypeID
  1242  	addrs := app.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)
  1243  
  1244  	denomA := "uETH"
  1245  	denomB := "uUSD"
  1246  	denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)
  1247  
  1248  	// 2^63-1
  1249  	hugeInt := int64(9223372036854775807)
  1250  	initDeposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(hugeInt)), sdk.NewCoin(denomB, sdk.NewInt(hugeInt)))
  1251  	app.SaveAccount(simapp, ctx, addrs[0], initDeposit)
  1252  	app.SaveAccount(simapp, ctx, addrs[1], initDeposit)
  1253  	app.SaveAccount(simapp, ctx, addrs[2], initDeposit)
  1254  
  1255  	createBalance := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(1*1000000)), sdk.NewCoin(denomB, sdk.NewInt(1*1000000)))
  1256  
  1257  	createMsg := types.NewMsgCreatePool(addrs[0], poolTypeID, createBalance)
  1258  
  1259  	_, err := simapp.LiquidityKeeper.CreatePool(ctx, createMsg)
  1260  	require.NoError(t, err)
  1261  
  1262  	pools := simapp.LiquidityKeeper.GetAllPools(ctx)
  1263  	pool := pools[0]
  1264  
  1265  	poolCoinInit := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
  1266  	require.Equal(t, poolCoinInit, sdk.NewInt(1*1000000))
  1267  
  1268  	depositMsg := types.NewMsgDepositWithinBatch(addrs[1], pool.Id, initDeposit)
  1269  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
  1270  	require.NoError(t, err)
  1271  
  1272  	poolBatch, found := simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
  1273  	require.True(t, found)
  1274  	msgs := simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
  1275  	require.Equal(t, 1, len(msgs))
  1276  
  1277  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
  1278  	require.NoError(t, err)
  1279  
  1280  	poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
  1281  	require.Equal(t, poolCoin.Sub(poolCoinInit), simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom).Amount)
  1282  
  1283  	simapp.LiquidityKeeper.DeleteAllReadyPoolBatchDepositMsgStates(ctx, poolBatch)
  1284  
  1285  	depositMsg = types.NewMsgDepositWithinBatch(addrs[2], pool.Id, initDeposit)
  1286  	_, err = simapp.LiquidityKeeper.DepositWithinBatch(ctx, depositMsg)
  1287  	require.NoError(t, err)
  1288  
  1289  	poolBatch, found = simapp.LiquidityKeeper.GetPoolBatch(ctx, depositMsg.PoolId)
  1290  	require.True(t, found)
  1291  	msgs = simapp.LiquidityKeeper.GetAllPoolBatchDepositMsgs(ctx, poolBatch)
  1292  	require.Equal(t, 1, len(msgs))
  1293  
  1294  	err = simapp.LiquidityKeeper.ExecuteDeposit(ctx, msgs[0], poolBatch)
  1295  	require.NoError(t, err)
  1296  
  1297  	poolCoinAfter := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pool)
  1298  	require.Equal(t, poolCoinAfter.Sub(poolCoin), simapp.BankKeeper.GetBalance(ctx, addrs[2], pool.PoolCoinDenom).Amount)
  1299  	require.Equal(t, simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom).Amount, simapp.BankKeeper.GetBalance(ctx, addrs[2], pool.PoolCoinDenom).Amount)
  1300  
  1301  	require.True(t, simapp.BankKeeper.GetBalance(ctx, addrs[1], denomA).IsZero())
  1302  	require.True(t, simapp.BankKeeper.GetBalance(ctx, addrs[1], denomB).IsZero())
  1303  
  1304  	// Error due to decimal operation exceeding precision
  1305  	require.Equal(t, sdk.NewInt(8), simapp.BankKeeper.GetBalance(ctx, addrs[2], denomA).Amount)
  1306  	require.Equal(t, sdk.NewInt(8), simapp.BankKeeper.GetBalance(ctx, addrs[2], denomB).Amount)
  1307  
  1308  	poolCoinAmt := simapp.BankKeeper.GetBalance(ctx, addrs[1], pool.PoolCoinDenom)
  1309  	state, err := simapp.LiquidityKeeper.WithdrawWithinBatch(ctx, types.NewMsgWithdrawWithinBatch(addrs[1], pool.Id, poolCoinAmt))
  1310  	require.NoError(t, err)
  1311  
  1312  	err = simapp.LiquidityKeeper.ExecuteWithdrawal(ctx, state, poolBatch)
  1313  	require.NoError(t, err)
  1314  
  1315  	balanceAfter := simapp.BankKeeper.GetAllBalances(ctx, addrs[1])
  1316  	liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
  1317  	liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
  1318  
  1319  	// Error due to decimal operation exceeding precision
  1320  	require.Equal(t, sdk.ZeroInt(), balanceAfter.AmountOf(pool.PoolCoinDenom))
  1321  	require.Equal(t, sdk.NewInt(-4), balanceAfter.AmountOf(denomA).SubRaw(hugeInt))
  1322  	require.Equal(t, sdk.NewInt(-4), balanceAfter.AmountOf(denomB).SubRaw(hugeInt))
  1323  }