-
Notifications
You must be signed in to change notification settings - Fork 0
/
genesis.go
213 lines (182 loc) · 7.84 KB
/
genesis.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package simulation
// DONTCOVER
import (
"fmt"
"math"
"math/big"
"math/rand"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/jinxprotocol/v4-chain/protocol/dtypes"
"github.com/jinxprotocol/v4-chain/protocol/lib"
"github.com/jinxprotocol/v4-chain/protocol/testutil/sim_helpers"
"github.com/jinxprotocol/v4-chain/protocol/x/perpetuals/types"
pricestypes "github.com/jinxprotocol/v4-chain/protocol/x/prices/types"
"github.com/cosmos/cosmos-sdk/types/module"
)
// genNumPerpetuals returns randomized number of perpetuals.
func genNumPerpetuals(r *rand.Rand, isReasonableGenesis bool, numMarkets int) int {
return simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinNumPerpetuals, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxNumPerpetuals, isReasonableGenesis)+1,
)
}
// genNumLiquidityTiers returns a randomized number of liquidity tiers.
func genNumLiquidityTiers(r *rand.Rand, isReasonableGenesis bool) int {
return simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinNumLiquidityTiers, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxNumLiquidityTiers, isReasonableGenesis),
)
}
// genPerpetualToMarketMap returns a list of `Market.Id` that should correspond to each`perpetual.Params.Id`.
func genPerpetualToMarketMap(r *rand.Rand, numPerpetuals, numMarkets int) []uint32 {
markets := sim_helpers.MakeRange(uint32(numMarkets))
// Pad more markets if there are more perpetuals.
if numPerpetuals > numMarkets {
diff := numPerpetuals - numMarkets
extraMarkets := make([]uint32, diff)
for i := 0; i < diff; i++ {
randomIdx := simtypes.RandIntBetween(r, 0, numMarkets)
extraMarkets[i] = markets[randomIdx]
}
markets = append(markets, extraMarkets...)
}
// Shuffle markets, so we randomize which `Perpetual` gets matched with which `Market`.
r.Shuffle(numPerpetuals, func(i, j int) { markets[i], markets[j] = markets[j], markets[i] })
return markets
}
// genTicker returns a randomized string used for `perpetual.Params.Ticker`.
func genTicker(r *rand.Rand) string {
return simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 3, 6)) + "-USD"
}
// genAtomicResolution returns a randomized int used for `perpetual.Params.AtomicResolution`.
func genAtomicResolution(r *rand.Rand, isReasonableGenesis bool) int32 {
return int32(simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinAtomicResolution, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxAtomicResolution, isReasonableGenesis)+1,
))
}
// genDefaultFundingPpm returns a randomized int used for `perpetual.Params.DefaultFundingPpm`.
func genDefaultFundingPpm(r *rand.Rand) int32 {
defaultFundingPpmAbs := sim_helpers.GetRandomBucketValue(r, sim_helpers.DefaultFundingPpmAbsBuckets)
if sim_helpers.RandBool(r) {
return -int32(defaultFundingPpmAbs)
}
return int32(defaultFundingPpmAbs)
}
// genInitialAndMaintenanceMargin returns a randomized set of ints used for Initial and Maintenance margins.
func genInitialAndMaintenanceFraction(r *rand.Rand) (uint32, uint32) {
initialMargin := sim_helpers.GetRandomBucketValue(r, sim_helpers.InitialMarginBuckets)
// MaintenanceFraction must be less than or equal to 100%.
maintenanceFraction := simtypes.RandIntBetween(r, 0, 1_000_000)
return uint32(initialMargin), uint32(maintenanceFraction)
}
// calculateImpactNotional calculates impact notional as 500 USDC / initial margin fraction.
func calculateImpactNotional(initialMarginPpm uint32) uint64 {
// If initial margin is 0, return max uint64.
if initialMarginPpm == 0 {
return math.MaxUint64
}
impactNotional := big.NewInt(500_000_000) // 500 USDC in quote quantums
impactNotional.Mul(impactNotional, lib.BigIntOneMillion())
impactNotional.Quo(impactNotional, big.NewInt(int64(initialMarginPpm)))
return impactNotional.Uint64()
}
func genParams(r *rand.Rand, isReasonableGenesis bool) types.Params {
return types.Params{
FundingRateClampFactorPpm: genFundingRateClampFactorPpm(r, isReasonableGenesis),
PremiumVoteClampFactorPpm: genPremiumVoteClampFactorPpm(r, isReasonableGenesis),
MinNumVotesPerSample: genMinNumVotesPerSample(r, isReasonableGenesis),
}
}
func genFundingRateClampFactorPpm(r *rand.Rand, isReasonableGenesis bool) uint32 {
return uint32(
simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinFundingRateClampFactorPpm, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxFundingRateClampFactorPpm, isReasonableGenesis)+1,
),
)
}
// genPremiumVoteClampFactorPpm returns a randomized uint32 for premium vote clamp factor ppm.
func genPremiumVoteClampFactorPpm(r *rand.Rand, isReasonableGenesis bool) uint32 {
return uint32(
simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinPremiumVoteClampFactorPpm, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxPremiumVoteClampFactorPpm, isReasonableGenesis)+1,
),
)
}
// genMinNumVotesPerSample returns a randomized uint32 for minimum number of votes per sample.
func genMinNumVotesPerSample(r *rand.Rand, isReasonableGenesis bool) uint32 {
return uint32(
simtypes.RandIntBetween(
r,
sim_helpers.PickGenesisParameter(sim_helpers.MinMinNumVotesPerSample, isReasonableGenesis),
sim_helpers.PickGenesisParameter(sim_helpers.MaxMinNumVotesPerSample, isReasonableGenesis)+1,
),
)
}
// RandomizedGenState generates a random GenesisState for `Perpetuals`.
func RandomizedGenState(simState *module.SimulationState) {
r := simState.Rand
isReasonableGenesis := sim_helpers.ShouldGenerateReasonableGenesis(r, simState.GenTimestamp)
// Generate `Params`.
params := genParams(r, isReasonableGenesis)
// Generate `LiquidityTier`s.
numLiquidityTiers := genNumLiquidityTiers(r, isReasonableGenesis)
liquidityTiers := make([]types.LiquidityTier, numLiquidityTiers)
for i := 0; i < numLiquidityTiers; i++ {
initialMarginPpm, maintenanceFractionPpm := genInitialAndMaintenanceFraction(r)
impactNotional := calculateImpactNotional(initialMarginPpm)
liquidityTiers[i] = types.LiquidityTier{
Id: uint32(i),
Name: fmt.Sprintf("%d", i),
InitialMarginPpm: initialMarginPpm,
MaintenanceFractionPpm: maintenanceFractionPpm,
ImpactNotional: impactNotional,
}
}
// Get number of `Prices.Markets`.
cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
pricesGenesisBytes := simState.GenState[pricestypes.ModuleName]
var pricesGenesis pricestypes.GenesisState
if err := cdc.UnmarshalJSON(pricesGenesisBytes, &pricesGenesis); err != nil {
panic(fmt.Sprintf("Could not unmarshal Prices GenesisState %s", err))
}
numMarkets := len(pricesGenesis.GetMarketParams())
if numMarkets == 0 {
panic("Number of Markets cannot be zero")
}
// Generate number of `Perpetuals`.
numPerpetuals := genNumPerpetuals(r, isReasonableGenesis, numMarkets)
// Generate `Market`s for each `Perpetual`.
marketsForPerp := genPerpetualToMarketMap(r, numPerpetuals, numMarkets)
// Generate `Perpetuals`.
perpetuals := make([]types.Perpetual, numPerpetuals)
for i := 0; i < numPerpetuals; i++ {
marketId := marketsForPerp[i]
perpetuals[i] = types.Perpetual{
Params: types.PerpetualParams{
Id: uint32(i),
Ticker: genTicker(r),
MarketId: marketId,
AtomicResolution: genAtomicResolution(r, isReasonableGenesis),
DefaultFundingPpm: genDefaultFundingPpm(r),
LiquidityTier: uint32(simtypes.RandIntBetween(r, 0, numLiquidityTiers)),
},
FundingIndex: dtypes.ZeroInt(),
}
}
perpetualsGenesis := types.GenesisState{
Perpetuals: perpetuals,
LiquidityTiers: liquidityTiers,
Params: params,
}
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&perpetualsGenesis)
}