Skip to content

Commit

Permalink
randomized variables in operations and sanitize various stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon committed Feb 24, 2021
1 parent bba81b2 commit e6511d6
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 131 deletions.
222 changes: 104 additions & 118 deletions x/liquidity/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,14 @@ func SimulateMsgCreateLiquidityPool(ak types.AccountKeeper, bk types.BankKeeper,
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
/*
1. Mint new coins and send those minted coins to simulated random account
2. Create new liquidity pool
*/

simAccount, _ := simtypes.RandomAcc(r, accs)
denomA, denomB := setRandomMintedCoinsToAccount(ctx, r, simAccount.Address, bk)

denomA, denomB := randomDenoms(r)
reserveCoinDenoms := []string{denomA, denomB}
err := mintCoins(r, simAccount.Address, reserveCoinDenoms, bk, ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgCreateLiquidityPool, "unable to mint and send coins"), nil, nil
}

poolKey := types.GetPoolKey(reserveCoinDenoms, types.DefaultPoolTypeIndex)
reserveAcc := types.GetPoolReserveAcc(poolKey)

Expand Down Expand Up @@ -156,23 +155,20 @@ func SimulateMsgDepositToLiquidityPool(ak types.AccountKeeper, bk types.BankKeep
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
/*
1. Mint new coins and send those minted coins to simulated random account
2. Create new liquidity pool
3. Deposit coins to liquidity pool
*/
if len(k.GetAllLiquidityPools(ctx)) == 0 {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "number of liquidity pools equals zero"), nil, nil
}

simAccount, _ := simtypes.RandomAcc(r, accs)
denomA, denomB := setRandomMintedCoinsToAccount(ctx, r, simAccount.Address, bk)

balanceA := bk.GetBalance(ctx, simAccount.Address, denomA).Amount
if !balanceA.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "balanceA is negative"), nil, nil
pool, ok := randomLiquidity(r, k, ctx)
if !ok {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "unable to pick liquidity pool"), nil, nil
}

balanceB := bk.GetBalance(ctx, simAccount.Address, denomB).Amount
if !balanceB.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "balanceB is negative"), nil, nil
// mint pool denoms to the simulated account
err := mintCoins(r, simAccount.Address, pool.ReserveCoinDenoms, bk, ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "unable to mint and send coins"), nil, nil
}

account := ak.GetAccount(ctx, simAccount.Address)
Expand All @@ -183,29 +179,11 @@ func SimulateMsgDepositToLiquidityPool(ak types.AccountKeeper, bk types.BankKeep
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "unable to generate fees"), nil, err
}

poolCreator := account.GetAddress()
depositCoinA := randomDepositCoin(r, denomA)
depositCoinB := randomDepositCoin(r, denomB)
depositCoinA := randomNewDepositCoin(r, pool.ReserveCoinDenoms[0])
depositCoinB := randomNewDepositCoin(r, pool.ReserveCoinDenoms[1])
depositCoins := sdk.NewCoins(depositCoinA, depositCoinB)

createPoolMsg := types.NewMsgCreateLiquidityPool(poolCreator, types.DefaultPoolTypeIndex, depositCoins)
err, _ = k.CreateLiquidityPool(ctx, createPoolMsg)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "unable to create liquidity pool"), nil, err
}

poolId := uint64(1)
pool, found := k.GetLiquidityPool(ctx, poolId)
if !found {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "unable to get liquidity pool"), nil, err
}

depositor := account.GetAddress()
newDepositCoinA := randomNewDepositCoin(r, denomA)
newDepositCoinB := randomNewDepositCoin(r, denomB)
newDepositCoins := sdk.NewCoins(newDepositCoinA, newDepositCoinB)

msg := types.NewMsgDepositToLiquidityPool(depositor, pool.PoolId, newDepositCoins)
msg := types.NewMsgDepositToLiquidityPool(account.GetAddress(), pool.PoolId, depositCoins)

txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
Expand Down Expand Up @@ -237,23 +215,29 @@ func SimulateMsgWithdrawFromLiquidityPool(ak types.AccountKeeper, bk types.BankK
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
/*
1. Mint new coins and send those minted coins to simulated random account
2. Create new liquidity pool
3. Withdraw some coins from liquidity pool
*/
if len(k.GetAllLiquidityPools(ctx)) == 0 {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "number of liquidity pools equals zero"), nil, nil
}

simAccount, _ := simtypes.RandomAcc(r, accs)
denomA, denomB := setRandomMintedCoinsToAccount(ctx, r, simAccount.Address, bk)
pool, ok := randomLiquidity(r, k, ctx)
if !ok {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "unable to pick liquidity pool"), nil, nil
}

balanceA := bk.GetBalance(ctx, simAccount.Address, denomA).Amount
if !balanceA.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "balanceA is negative"), nil, nil
poolCoinDenom := pool.GetPoolCoinDenom()

// need to retrieve random simulation account to retrieve PrivKey
simAccount := accs[simtypes.RandIntBetween(r, 0, len(accs))]

// if simaccount.PrivKey == nil, delegation address does not exist in accs. Return error
if simAccount.PrivKey == nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "account private key is nil"), nil, nil
}

balanceB := bk.GetBalance(ctx, simAccount.Address, denomB).Amount
if !balanceB.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "balanceB is negative"), nil, nil
// mint pool coin to the simulated account
err := mintPoolCoin(r, simAccount.Address, poolCoinDenom, bk, ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgDepositToLiquidityPool, "unable to mint and send coins"), nil, nil
}

account := ak.GetAccount(ctx, simAccount.Address)
Expand All @@ -264,25 +248,8 @@ func SimulateMsgWithdrawFromLiquidityPool(ak types.AccountKeeper, bk types.BankK
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "unable to generate fees"), nil, err
}

poolCreator := account.GetAddress()
depositCoinA := randomDepositCoin(r, denomA)
depositCoinB := randomDepositCoin(r, denomB)
depositCoins := sdk.NewCoins(depositCoinA, depositCoinB)

createPoolMsg := types.NewMsgCreateLiquidityPool(poolCreator, types.DefaultPoolTypeIndex, depositCoins)
err, _ = k.CreateLiquidityPool(ctx, createPoolMsg)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "unable to create liquidity pool"), nil, err
}

poolId := uint64(1)
pool, found := k.GetLiquidityPool(ctx, poolId)
if !found {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgWithdrawFromLiquidityPool, "unable to get liquidity pool"), nil, err
}

withdrawer := account.GetAddress()
withdrawCoin := randomWithdrawCoin(r, pool.PoolCoinDenom)
withdrawCoin := randomWithdrawCoin(r, poolCoinDenom)

msg := types.NewMsgWithdrawFromLiquidityPool(withdrawer, pool.PoolId, withdrawCoin)

Expand Down Expand Up @@ -316,23 +283,20 @@ func SimulateMsgSwap(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keepe
return func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
/*
1. Mint new coins and send those minted coins to simulated random account
2. Create new liquidity pool
3. Swap coinA to coinB
*/
if len(k.GetAllLiquidityPools(ctx)) == 0 {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "number of liquidity pools equals zero"), nil, nil
}

simAccount, _ := simtypes.RandomAcc(r, accs)
denomA, denomB := setRandomMintedCoinsToAccount(ctx, r, simAccount.Address, bk)

balanceA := bk.GetBalance(ctx, simAccount.Address, denomA).Amount
if !balanceA.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "balanceA is negative"), nil, nil
pool, ok := randomLiquidity(r, k, ctx)
if !ok {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "unable to pick liquidity pool"), nil, nil
}

balanceB := bk.GetBalance(ctx, simAccount.Address, denomB).Amount
if !balanceB.IsPositive() {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "balanceB is negative"), nil, nil
// mint pool denoms to the simulated account
err := mintCoins(r, simAccount.Address, pool.ReserveCoinDenoms, bk, ctx)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "unable to mint and send coins"), nil, nil
}

account := ak.GetAccount(ctx, simAccount.Address)
Expand All @@ -343,34 +307,20 @@ func SimulateMsgSwap(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keepe
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "unable to generate fees"), nil, err
}

poolCreator := account.GetAddress()
depositCoinA := randomDepositCoin(r, denomA)
depositCoinB := randomDepositCoin(r, denomB)
depositCoins := sdk.NewCoins(depositCoinA, depositCoinB)

createPoolMsg := types.NewMsgCreateLiquidityPool(poolCreator, types.DefaultPoolTypeIndex, depositCoins)
err, _ = k.CreateLiquidityPool(ctx, createPoolMsg)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "unable to create liquidity pool"), nil, err
}

// params := k.GetParams(ctx)

swapRequester := account.GetAddress()
poolId := uint64(1)
swapType := types.DefaultSwapType
demandCoinDenom := denomB
demandCoinDenom := pool.ReserveCoinDenoms[1]
orderPrice := randomOrderPrice(r)

offerAmount, err := simtypes.RandPositiveInt(r, balanceA)
offerAmount, err := simtypes.RandPositiveInt(r, sdk.NewInt(r.Int63()))
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgSwap, "unable to generate positive amount"), nil, err
}

offerCoin := sdk.NewCoin(denomA, offerAmount)
offerCoin := sdk.NewCoin(pool.ReserveCoinDenoms[0], offerAmount)
swapFeeRate := GenSwapFeeRate(r)

msg := types.NewMsgSwap(swapRequester, poolId, swapType, offerCoin, demandCoinDenom, orderPrice, swapFeeRate)
msg := types.NewMsgSwap(swapRequester, pool.PoolId, types.DefaultSwapType,
offerCoin, demandCoinDenom, orderPrice, swapFeeRate)

txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := helpers.GenTx(
Expand All @@ -396,30 +346,66 @@ func SimulateMsgSwap(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keepe
}
}

// setRandomMintedCoinsToAccount creates simulated random account and have new minted coins
func setRandomMintedCoinsToAccount(ctx sdk.Context, r *rand.Rand, address sdk.AccAddress, bk types.BankKeeper) (string, string) {
// random denom with a length from 4 to 6 characters
denomA := simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 4, 6))
denomB := simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 4, 6))
denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)

// mintCoins mints coins relative to the denoms and send them to the simulated account
func mintCoins(r *rand.Rand, address sdk.AccAddress, denoms []string, bk types.BankKeeper, ctx sdk.Context) error {
// mint random amounts of denomA and denomB coins
mintCoinA := randomMintAmount(r, denomA)
mintCoinB := randomMintAmount(r, denomB)
mintCoinA := randomMintAmount(r, denoms[0])
mintCoinB := randomMintAmount(r, denoms[1])
mintCoins := sdk.NewCoins(mintCoinA, mintCoinB)
bk.MintCoins(ctx, types.ModuleName, mintCoins)
err := bk.MintCoins(ctx, types.ModuleName, mintCoins)
if err != nil {
return err
}

// transfer random amounts to the simulated random account
coinA := sdk.NewCoin(denomA, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e12, 1e15))))
coinB := sdk.NewCoin(denomB, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e12, 1e15))))
bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, address, sdk.NewCoins(coinA, coinB))
coinA := sdk.NewCoin(denoms[0], sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e12, 1e14))))
coinB := sdk.NewCoin(denoms[1], sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e12, 1e14))))
coins := sdk.NewCoins(coinA, coinB)
err = bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, address, coins)
if err != nil {
return err
}
return nil
}

// mintPoolCoin mints pool coin and send random amount to the simulated account
func mintPoolCoin(r *rand.Rand, address sdk.AccAddress, poolCoinDenom string, bk types.BankKeeper, ctx sdk.Context) error {
mintCoins := sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e7, 1e8)))))
err := bk.MintCoins(ctx, types.ModuleName, mintCoins)
if err != nil {
return err
}

coins := sdk.NewCoins(sdk.NewCoin(poolCoinDenom, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e5, 1e6)))))
err = bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, address, coins)
if err != nil {
return err
}
return nil
}

// randomDenoms randomizes denoms with a length from 4 to 6 characters
func randomDenoms(r *rand.Rand) (string, string) {
denomA := simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 4, 6))
denomB := simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 4, 6))
return denomA, denomB
}

// randomMintAmount randomizes minting coins in a range of 1e12 to 1e15
func randomMintAmount(r *rand.Rand, denom string) sdk.Coin {
return sdk.NewCoin(denom, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e12, 1e15))))
return sdk.NewCoin(denom, sdk.NewInt(int64(simtypes.RandIntBetween(r, 1e14, 1e15))))
}

// randomLiquidity returns a random liquidity pool given access to the keeper and ctx
func randomLiquidity(r *rand.Rand, k keeper.Keeper, ctx sdk.Context) (pool types.LiquidityPool, ok bool) {
pools := k.GetAllLiquidityPools(ctx)
if len(pools) == 0 {
return types.LiquidityPool{}, false
}

i := r.Intn(len(pools))

return pools[i], true
}

// randomDepositCoin randomizes deposit coin greater than DefaultMinInitDepositToPool
Expand Down
Loading

0 comments on commit e6511d6

Please sign in to comment.