Skip to content

Commit 26938c8

Browse files
authored
[CORE-517] add integration tests for prices governance messages (#808)
* add integration tests for prices governance messages * address comments
1 parent cf6c8e9 commit 26938c8

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package gov_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cometbft/cometbft/types"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
9+
"github.com/dydxprotocol/v4-chain/protocol/lib"
10+
testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app"
11+
"github.com/dydxprotocol/v4-chain/protocol/testutil/constants"
12+
pricestest "github.com/dydxprotocol/v4-chain/protocol/testutil/prices"
13+
clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
14+
perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types"
15+
pricestypes "github.com/dydxprotocol/v4-chain/protocol/x/prices/types"
16+
"github.com/stretchr/testify/require"
17+
)
18+
19+
var (
20+
GENESIS_MARKET_PARAM = pricestypes.MarketParam{
21+
Id: 0,
22+
Pair: "btc-adv4tnt",
23+
Exponent: -8,
24+
MinExchanges: 2,
25+
MinPriceChangePpm: 1_000,
26+
ExchangeConfigJson: "{}",
27+
}
28+
29+
MODIFIED_MARKET_PARAM = pricestypes.MarketParam{
30+
Id: GENESIS_MARKET_PARAM.Id,
31+
Pair: "eth-adv4tnt",
32+
Exponent: GENESIS_MARKET_PARAM.Exponent, // exponent cannot be updated
33+
MinExchanges: 3,
34+
MinPriceChangePpm: 2_002,
35+
ExchangeConfigJson: `{"exchanges":[{"exchangeName":"Bitfinex","ticker":"tBTCUSD"}]}`,
36+
}
37+
)
38+
39+
// This tests `MsgUpdateMarketParam` in `x/prices`.
40+
func TestUpdateMarketParam(t *testing.T) {
41+
tests := map[string]struct {
42+
msg *pricestypes.MsgUpdateMarketParam
43+
expectCheckTxFails bool
44+
expectSubmitProposalFails bool
45+
expectedProposalStatus govtypesv1.ProposalStatus
46+
}{
47+
"Success": {
48+
msg: &pricestypes.MsgUpdateMarketParam{
49+
Authority: lib.GovModuleAddress.String(),
50+
MarketParam: MODIFIED_MARKET_PARAM,
51+
},
52+
expectedProposalStatus: govtypesv1.ProposalStatus_PROPOSAL_STATUS_PASSED,
53+
},
54+
"Failure: market param does not exist": {
55+
msg: &pricestypes.MsgUpdateMarketParam{
56+
Authority: lib.GovModuleAddress.String(),
57+
MarketParam: pricestypes.MarketParam{
58+
Id: MODIFIED_MARKET_PARAM.Id + 1, // id does not exist
59+
Pair: MODIFIED_MARKET_PARAM.Pair,
60+
Exponent: MODIFIED_MARKET_PARAM.Exponent,
61+
MinExchanges: MODIFIED_MARKET_PARAM.MinExchanges,
62+
MinPriceChangePpm: MODIFIED_MARKET_PARAM.MinPriceChangePpm,
63+
ExchangeConfigJson: MODIFIED_MARKET_PARAM.ExchangeConfigJson,
64+
},
65+
},
66+
expectedProposalStatus: govtypesv1.ProposalStatus_PROPOSAL_STATUS_FAILED,
67+
},
68+
"Failure: exponent is updated": {
69+
msg: &pricestypes.MsgUpdateMarketParam{
70+
Authority: lib.GovModuleAddress.String(),
71+
MarketParam: pricestypes.MarketParam{
72+
Id: MODIFIED_MARKET_PARAM.Id,
73+
Pair: MODIFIED_MARKET_PARAM.Pair,
74+
Exponent: MODIFIED_MARKET_PARAM.Exponent + 1, // update to exponent is not permitted.
75+
MinExchanges: MODIFIED_MARKET_PARAM.MinExchanges,
76+
MinPriceChangePpm: MODIFIED_MARKET_PARAM.MinPriceChangePpm,
77+
ExchangeConfigJson: MODIFIED_MARKET_PARAM.ExchangeConfigJson,
78+
},
79+
},
80+
expectedProposalStatus: govtypesv1.ProposalStatus_PROPOSAL_STATUS_FAILED,
81+
},
82+
"Failure: empty pair": {
83+
msg: &pricestypes.MsgUpdateMarketParam{
84+
Authority: lib.GovModuleAddress.String(),
85+
MarketParam: pricestypes.MarketParam{
86+
Id: MODIFIED_MARKET_PARAM.Id,
87+
Pair: "", // invalid
88+
Exponent: MODIFIED_MARKET_PARAM.Exponent,
89+
MinExchanges: MODIFIED_MARKET_PARAM.MinExchanges,
90+
MinPriceChangePpm: MODIFIED_MARKET_PARAM.MinPriceChangePpm,
91+
ExchangeConfigJson: MODIFIED_MARKET_PARAM.ExchangeConfigJson,
92+
},
93+
},
94+
expectCheckTxFails: true,
95+
},
96+
"Failure: min exchanges is 0": {
97+
msg: &pricestypes.MsgUpdateMarketParam{
98+
Authority: lib.GovModuleAddress.String(),
99+
MarketParam: pricestypes.MarketParam{
100+
Id: MODIFIED_MARKET_PARAM.Id,
101+
Pair: MODIFIED_MARKET_PARAM.Pair,
102+
Exponent: MODIFIED_MARKET_PARAM.Exponent,
103+
MinExchanges: 0, // invalid
104+
MinPriceChangePpm: MODIFIED_MARKET_PARAM.MinPriceChangePpm,
105+
ExchangeConfigJson: MODIFIED_MARKET_PARAM.ExchangeConfigJson,
106+
},
107+
},
108+
expectCheckTxFails: true,
109+
},
110+
"Failure: malformed exchange config json": {
111+
msg: &pricestypes.MsgUpdateMarketParam{
112+
Authority: lib.GovModuleAddress.String(),
113+
MarketParam: pricestypes.MarketParam{
114+
Id: MODIFIED_MARKET_PARAM.Id,
115+
Pair: MODIFIED_MARKET_PARAM.Pair,
116+
Exponent: MODIFIED_MARKET_PARAM.Exponent,
117+
MinExchanges: MODIFIED_MARKET_PARAM.MinExchanges,
118+
MinPriceChangePpm: MODIFIED_MARKET_PARAM.MinPriceChangePpm,
119+
ExchangeConfigJson: `{{"exchanges":[{"exchangeName":"Bitfinex","ticker":"tBTCUSD"}]}`, // invalid
120+
},
121+
},
122+
expectCheckTxFails: true,
123+
},
124+
"Failure: invalid authority": {
125+
msg: &pricestypes.MsgUpdateMarketParam{
126+
Authority: constants.AliceAccAddress.String(),
127+
MarketParam: MODIFIED_MARKET_PARAM,
128+
},
129+
expectSubmitProposalFails: true,
130+
},
131+
}
132+
133+
for name, tc := range tests {
134+
t.Run(name, func(t *testing.T) {
135+
tApp := testapp.NewTestAppBuilder(t).WithGenesisDocFn(func() (genesis types.GenesisDoc) {
136+
genesis = testapp.DefaultGenesis()
137+
testapp.UpdateGenesisDocWithAppStateForModule(
138+
&genesis,
139+
func(genesisState *govtypesv1.GenesisState) {
140+
genesisState.Params.VotingPeriod = &testapp.TestVotingPeriod
141+
},
142+
)
143+
// Initialize prices module with genesis market param.
144+
testapp.UpdateGenesisDocWithAppStateForModule(
145+
&genesis,
146+
func(genesisState *pricestypes.GenesisState) {
147+
marketParamPrice := pricestest.GenerateMarketParamPrice(
148+
pricestest.WithId(GENESIS_MARKET_PARAM.Id),
149+
pricestest.WithPair(GENESIS_MARKET_PARAM.Pair),
150+
pricestest.WithExponent(GENESIS_MARKET_PARAM.Exponent),
151+
pricestest.WithMinExchanges(GENESIS_MARKET_PARAM.MinExchanges),
152+
pricestest.WithMinPriceChangePpm(GENESIS_MARKET_PARAM.MinPriceChangePpm),
153+
pricestest.WithExchangeConfigJson(GENESIS_MARKET_PARAM.ExchangeConfigJson),
154+
)
155+
genesisState.MarketParams = []pricestypes.MarketParam{marketParamPrice.Param}
156+
genesisState.MarketPrices = []pricestypes.MarketPrice{marketParamPrice.Price}
157+
},
158+
)
159+
// Initialize perpetuals module with no perpetuals.
160+
testapp.UpdateGenesisDocWithAppStateForModule(
161+
&genesis,
162+
func(genesisState *perptypes.GenesisState) {
163+
genesisState.Perpetuals = []perptypes.Perpetual{}
164+
},
165+
)
166+
// Initialize clob module with no clob pairs.
167+
testapp.UpdateGenesisDocWithAppStateForModule(
168+
&genesis,
169+
func(genesisState *clobtypes.GenesisState) {
170+
genesisState.ClobPairs = []clobtypes.ClobPair{}
171+
},
172+
)
173+
return genesis
174+
}).Build()
175+
ctx := tApp.InitChain()
176+
initialMarketParams := tApp.App.PricesKeeper.GetAllMarketParams(ctx)
177+
178+
// Submit and tally governance proposal that includes `MsgUpdateMarketParam`.
179+
ctx = testapp.SubmitAndTallyProposal(
180+
t,
181+
ctx,
182+
tApp,
183+
[]sdk.Msg{tc.msg},
184+
tc.expectCheckTxFails,
185+
tc.expectSubmitProposalFails,
186+
tc.expectedProposalStatus,
187+
)
188+
189+
if tc.expectedProposalStatus == govtypesv1.ProposalStatus_PROPOSAL_STATUS_PASSED {
190+
// If proposal is supposed to pass, verify that maret param is updated.
191+
updatedMarketParam, exists := tApp.App.PricesKeeper.GetMarketParam(ctx, tc.msg.MarketParam.Id)
192+
require.True(t, exists)
193+
require.Equal(t, tc.msg.MarketParam, updatedMarketParam)
194+
} else {
195+
// Otherwise, verify that market params are unchanged.
196+
require.Equal(t, initialMarketParams, tApp.App.PricesKeeper.GetAllMarketParams(ctx))
197+
}
198+
})
199+
}
200+
}

protocol/testutil/prices/market_param_price.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ func WithMinExchanges(minExchanges uint32) MarketParamPriceModifierOption {
4040
}
4141
}
4242

43+
func WithMinPriceChangePpm(minPriceChangePpm uint32) MarketParamPriceModifierOption {
44+
return func(cp *pricestypes.MarketParamPrice) {
45+
cp.Param.MinPriceChangePpm = minPriceChangePpm
46+
}
47+
}
48+
4349
func WithExchangeConfigJson(configJson string) MarketParamPriceModifierOption {
4450
return func(cp *pricestypes.MarketParamPrice) {
4551
cp.Param.ExchangeConfigJson = configJson

0 commit comments

Comments
 (0)