2020-03-30 15:02:43 +00:00
|
|
|
package simulation
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-04-12 03:54:45 +00:00
|
|
|
"math/rand"
|
|
|
|
"strings"
|
2020-03-30 15:02:43 +00:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2020-04-12 03:54:45 +00:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-03-30 15:02:43 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/module"
|
2020-04-12 03:54:45 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
|
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/supply"
|
2020-03-30 15:02:43 +00:00
|
|
|
"github.com/kava-labs/kava/x/bep3/types"
|
|
|
|
)
|
|
|
|
|
2020-04-12 03:54:45 +00:00
|
|
|
// Simulation parameter constants
|
|
|
|
const (
|
|
|
|
BnbDeputyAddress = "bnb_deputy_address"
|
|
|
|
MinBlockLock = "min_block_lock"
|
|
|
|
MaxBlockLock = "max_block_lock"
|
|
|
|
SupportedAssets = "supported_assets"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2020-04-17 18:05:36 +00:00
|
|
|
MaxSupplyLimit = sdk.NewInt(1000000000000)
|
2020-04-12 03:54:45 +00:00
|
|
|
Accs []simulation.Account
|
|
|
|
ConsistentDenoms = [3]string{"bnb", "xrp", "btc"}
|
|
|
|
)
|
|
|
|
|
|
|
|
// GenBnbDeputyAddress randomized BnbDeputyAddress
|
|
|
|
func GenBnbDeputyAddress(r *rand.Rand) sdk.AccAddress {
|
|
|
|
return simulation.RandomAcc(r, Accs).Address
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenMinBlockLock randomized MinBlockLock
|
|
|
|
func GenMinBlockLock(r *rand.Rand) int64 {
|
|
|
|
min := int(types.AbsoluteMinimumBlockLock)
|
|
|
|
max := int(types.AbsoluteMaximumBlockLock)
|
|
|
|
return int64(r.Intn(max-min) + min)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenMaxBlockLock randomized MaxBlockLock
|
|
|
|
func GenMaxBlockLock(r *rand.Rand, minBlockLock int64) int64 {
|
|
|
|
min := int(minBlockLock)
|
|
|
|
max := int(types.AbsoluteMaximumBlockLock)
|
|
|
|
return int64(r.Intn(max-min) + min)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GenSupportedAssets gets randomized SupportedAssets
|
|
|
|
func GenSupportedAssets(r *rand.Rand) types.AssetParams {
|
|
|
|
var assets types.AssetParams
|
2020-04-13 17:06:59 +00:00
|
|
|
numAssets := (r.Intn(10) + 1)
|
|
|
|
for i := 0; i < numAssets; i++ {
|
2020-04-12 03:54:45 +00:00
|
|
|
denom := strings.ToLower(simulation.RandStringOfLength(r, (r.Intn(3) + 3)))
|
|
|
|
asset := genSupportedAsset(r, denom)
|
|
|
|
assets = append(assets, asset)
|
|
|
|
}
|
|
|
|
// Add bnb, btc, or xrp as a supported asset for interactions with other modules
|
|
|
|
stableAsset := genSupportedAsset(r, ConsistentDenoms[r.Intn(3)])
|
|
|
|
assets = append(assets, stableAsset)
|
|
|
|
|
|
|
|
return assets
|
|
|
|
}
|
|
|
|
|
|
|
|
func genSupportedAsset(r *rand.Rand, denom string) types.AssetParam {
|
|
|
|
coinID, _ := simulation.RandPositiveInt(r, sdk.NewInt(100000))
|
|
|
|
limit, _ := simulation.RandPositiveInt(r, MaxSupplyLimit)
|
|
|
|
return types.AssetParam{
|
|
|
|
Denom: denom,
|
|
|
|
CoinID: int(coinID.Int64()),
|
|
|
|
Limit: limit,
|
|
|
|
Active: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 15:02:43 +00:00
|
|
|
// RandomizedGenState generates a random GenesisState
|
|
|
|
func RandomizedGenState(simState *module.SimulationState) {
|
2020-04-12 03:54:45 +00:00
|
|
|
Accs = simState.Accounts
|
2020-03-30 15:02:43 +00:00
|
|
|
|
2020-04-12 03:54:45 +00:00
|
|
|
bep3Genesis := loadRandomBep3GenState(simState)
|
|
|
|
fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, bep3Genesis))
|
|
|
|
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(bep3Genesis)
|
|
|
|
|
|
|
|
authGenesis, totalCoins := loadAuthGenState(simState, bep3Genesis)
|
|
|
|
simState.GenState[auth.ModuleName] = simState.Cdc.MustMarshalJSON(authGenesis)
|
|
|
|
|
|
|
|
// Update supply to match amount of coins in auth
|
|
|
|
var supplyGenesis supply.GenesisState
|
|
|
|
simState.Cdc.MustUnmarshalJSON(simState.GenState[supply.ModuleName], &supplyGenesis)
|
|
|
|
for _, deputyCoin := range totalCoins {
|
|
|
|
supplyGenesis.Supply = supplyGenesis.Supply.Add(deputyCoin)
|
|
|
|
}
|
|
|
|
simState.GenState[supply.ModuleName] = simState.Cdc.MustMarshalJSON(supplyGenesis)
|
|
|
|
}
|
|
|
|
|
|
|
|
func loadRandomBep3GenState(simState *module.SimulationState) types.GenesisState {
|
|
|
|
bnbDeputyAddress := simulation.RandomAcc(simState.Rand, simState.Accounts).Address
|
|
|
|
|
|
|
|
// min/max block lock are hardcoded to 50/100 for expected -NumBlocks=100
|
|
|
|
minBlockLock := int64(types.AbsoluteMinimumBlockLock)
|
|
|
|
maxBlockLock := minBlockLock * 2
|
|
|
|
|
|
|
|
var supportedAssets types.AssetParams
|
|
|
|
simState.AppParams.GetOrGenerate(
|
|
|
|
simState.Cdc, SupportedAssets, &supportedAssets, simState.Rand,
|
|
|
|
func(r *rand.Rand) { supportedAssets = GenSupportedAssets(r) },
|
|
|
|
)
|
|
|
|
|
|
|
|
bep3Genesis := types.GenesisState{
|
|
|
|
Params: types.Params{
|
|
|
|
BnbDeputyAddress: bnbDeputyAddress,
|
|
|
|
MinBlockLock: minBlockLock,
|
|
|
|
MaxBlockLock: maxBlockLock,
|
|
|
|
SupportedAssets: supportedAssets,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return bep3Genesis
|
|
|
|
}
|
|
|
|
|
|
|
|
func loadAuthGenState(simState *module.SimulationState, bep3Genesis types.GenesisState) (
|
|
|
|
auth.GenesisState, []sdk.Coins) {
|
|
|
|
var authGenesis auth.GenesisState
|
|
|
|
simState.Cdc.MustUnmarshalJSON(simState.GenState[auth.ModuleName], &authGenesis)
|
|
|
|
|
|
|
|
deputy, found := getAccount(authGenesis.Accounts, bep3Genesis.Params.BnbDeputyAddress)
|
|
|
|
if !found {
|
|
|
|
panic("deputy address not found in available accounts")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load total limit of each supported asset to deputy's account
|
|
|
|
var totalCoins []sdk.Coins
|
|
|
|
for _, asset := range bep3Genesis.Params.SupportedAssets {
|
|
|
|
assetCoin := sdk.NewCoins(sdk.NewCoin(asset.Denom, asset.Limit))
|
|
|
|
if err := deputy.SetCoins(deputy.GetCoins().Add(assetCoin)); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
totalCoins = append(totalCoins, assetCoin)
|
|
|
|
}
|
|
|
|
authGenesis.Accounts = replaceOrAppendAccount(authGenesis.Accounts, deputy)
|
|
|
|
|
|
|
|
return authGenesis, totalCoins
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return an account from a list of accounts that matches an address.
|
|
|
|
func getAccount(accounts []authexported.GenesisAccount, addr sdk.AccAddress) (authexported.GenesisAccount, bool) {
|
|
|
|
for _, a := range accounts {
|
|
|
|
if a.GetAddress().Equals(addr) {
|
|
|
|
return a, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, false
|
|
|
|
}
|
2020-03-30 15:02:43 +00:00
|
|
|
|
2020-04-12 03:54:45 +00:00
|
|
|
// In a list of accounts, replace the first account found with the same address. If not found, append the account.
|
|
|
|
func replaceOrAppendAccount(accounts []authexported.GenesisAccount, acc authexported.GenesisAccount) []authexported.GenesisAccount {
|
|
|
|
newAccounts := accounts
|
|
|
|
for i, a := range accounts {
|
|
|
|
if a.GetAddress().Equals(acc.GetAddress()) {
|
|
|
|
newAccounts[i] = acc
|
|
|
|
return newAccounts
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return append(newAccounts, acc)
|
2020-03-30 15:02:43 +00:00
|
|
|
}
|