Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

vault_test.gno

15.43 Kb · 318 lines
  1package game_vault
  2
  3import (
  4	"chain"
  5	"strconv"
  6	"strings"
  7	"testing"
  8
  9	"gno.land/p/nt/uassert/v0"
 10)
 11
 12func TestParticipationProcessFundingAndSettlement(cur realm, t *testing.T) {
 13	vaultTest.Setup(cross(cur), t)
 14	poolID := vaultTest.CreatePool(cross(cur), "pool:1")
 15	processID := vaultTest.CreateParticipationProcess(cross(cur), "participation:1", "pool:1", 25)
 16
 17	firstFundID := vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:1", 25)
 18	secondFundID := vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:2", 25)
 19	vaultTest.DepositParticipation(cross(cur), vaultTest.Player2, processID, "participant:1", "payment:1", 25)
 20
 21	uassert.Equal(t, firstFundID, GetParticipationFundID(processID, vaultTest.Player1, "payment:1"))
 22	uassert.Equal(t, 2, GetParticipationFundCount(processID, vaultTest.Player1, "participant:1"))
 23	ids := ListParticipationFundIDs(processID, vaultTest.Player1, "participant:1", 1, 10)
 24	uassert.Equal(t, 2, len(ids))
 25	uassert.Equal(t, secondFundID, ids[0])
 26	uassert.Equal(t, firstFundID, ids[1])
 27
 28	testing.SetOriginCaller(vaultTest.Operator)
 29	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
 30	testing.SetOriginSend(chain.Coins{})
 31	CloseParticipationProcess(cross(cur), processID)
 32	CommitParticipationProcess(cross(cur), processID, "commit:1")
 33	uassert.Equal(t, int(ParticipationProcessStatusCommitted), int(GetParticipationProcess(processID).Status))
 34	processView := GetParticipationProcessByKey("participation:1")
 35	uassert.Equal(t, "pool:1", processView.RewardPoolKey)
 36	uassert.Equal(t, int(ParticipationFundStatusCommitted), int(GetParticipationFundEffectiveStatus(firstFundID)))
 37	uassert.Equal(t, int64(75), GetRewardPool(poolID).Balance)
 38
 39	vaultTest.DepositSystemFunding(cross(cur), poolID, "system:1", 25)
 40	testing.SetOriginCaller(vaultTest.Operator)
 41	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
 42	testing.SetOriginSend(chain.Coins{})
 43	LockRewardPool(cross(cur), "pool:1")
 44	DistributeReward(cross(cur), "pool:1", "distribution:1", vaultTest.Player2.String(), "100")
 45	distributionView := GetRewardDistributionByOperationKey("distribution:1")
 46	uassert.Equal(t, "pool:1", distributionView.PoolKey)
 47	SettleRewardPool(cross(cur), "pool:1")
 48	uassert.Equal(t, int(RewardPoolStatusSettled), int(GetRewardPoolByKey("pool:1").Status))
 49}
 50
 51func TestListParticipationProcessStates(cur realm, t *testing.T) {
 52	vaultTest.Setup(cross(cur), t)
 53	vaultTest.CreatePool(cross(cur), "pool:process-states")
 54	processID := vaultTest.CreateParticipationProcess(cross(cur), "process:states", "pool:process-states", 25)
 55
 56	states := ListParticipationProcessStates("process:missing", "process:states")
 57	uassert.Equal(t, 2, len(states))
 58	uassert.Equal(t, "0", states[0]["processId"])
 59	uassert.Equal(t, strconv.FormatUint(processID, 10), states[1]["processId"])
 60	uassert.Equal(t, "pool:process-states", states[1]["rewardPoolKey"])
 61	uassert.Equal(t, "25", states[1]["participationFee"])
 62}
 63
 64func TestListParticipationFundStates(cur realm, t *testing.T) {
 65	vaultTest.Setup(cross(cur), t)
 66	vaultTest.CreatePool(cross(cur), "pool:fund-states")
 67	processID := vaultTest.CreateParticipationProcess(cross(cur), "process:fund-states", "pool:fund-states", 25)
 68	fundID := vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participation:1", "payment:1", 25)
 69
 70	states := ListParticipationFundStates(
 71		strconv.FormatUint(processID, 10), vaultTest.Player1.String(), "payment:missing",
 72		strconv.FormatUint(processID, 10), vaultTest.Player1.String(), "payment:1",
 73	)
 74	uassert.Equal(t, 2, len(states))
 75	uassert.Equal(t, "0", states[0]["fundId"])
 76	uassert.Equal(t, strconv.FormatUint(fundID, 10), states[1]["fundId"])
 77	uassert.Equal(t, strconv.Itoa(int(ParticipationFundStatusHeld)), states[1]["fundEffectiveStatus"])
 78}
 79
 80func TestParticipationStateQueriesRejectInvalidBatch(cur realm, t *testing.T) {
 81	uassert.PanicsWithMessage(t, cur, "participation fund value count mismatch", func() {
 82		ListParticipationFundStates("1", vaultTest.Player1.String())
 83	})
 84
 85	processKeys := []string{}
 86	fundValues := []string{}
 87	for index := 0; index <= gameVaultList; index++ {
 88		processKeys = append(processKeys, "process:1")
 89		fundValues = append(fundValues, "1", vaultTest.Player1.String(), "payment:1")
 90	}
 91	uassert.PanicsWithMessage(t, cur, "count exceeds game vault list limit", func() {
 92		ListParticipationProcessStates(processKeys...)
 93	})
 94	uassert.PanicsWithMessage(t, cur, "count exceeds game vault list limit", func() {
 95		ListParticipationFundStates(fundValues...)
 96	})
 97}
 98
 99func TestListEntryRefundStates(cur realm, t *testing.T) {
100	vaultTest.Setup(cross(cur), t)
101	processID := vaultTest.CreateEntryProcess(cross(cur), "entry:states", 25)
102	fundID := vaultTest.DepositEntry(cross(cur), vaultTest.Player1, processID, "participation:1", "entry:1", 25)
103
104	states := ListEntryRefundStates(
105		"entry:missing,entry:states,entry:states,entry:states",
106		strings.Repeat(vaultTest.Player1.String()+",", 3)+vaultTest.Player1.String(),
107		"entry:1,entry:missing,entry:1,entry:1",
108	)
109	uassert.Equal(t, 4, len(states))
110	uassert.Equal(t, "entry:missing", states[0]["requestedProcessKey"])
111	uassert.Equal(t, "0", states[0]["processId"])
112	uassert.Equal(t, "0", states[0]["fundId"])
113	uassert.Equal(t, strconv.FormatUint(processID, 10), states[1]["processId"])
114	uassert.Equal(t, "0", states[1]["fundId"])
115	uassert.Equal(t, "25", states[2]["entryFee"])
116	uassert.Equal(t, strconv.FormatUint(fundID, 10), states[2]["fundId"])
117	uassert.Equal(t, vaultTest.Player1.String(), states[2]["fundOwner"])
118	uassert.Equal(t, "entry:1", states[2]["fundEntryKey"])
119	uassert.Equal(t, "participation:1", states[2]["participationKey"])
120	uassert.Equal(t, "false", states[2]["fundRefunded"])
121	states[2]["fundOwner"] = "changed"
122	uassert.Equal(t, vaultTest.Player1.String(), states[3]["fundOwner"])
123	uassert.Equal(t, vaultTest.Player1, GetEntryFund(fundID).Owner)
124
125	testing.SetOriginCaller(vaultTest.Operator)
126	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
127	testing.SetOriginSend(chain.Coins{})
128	RefundEntryFund(cross(cur), fundID, "refund:entry-states")
129	states = ListEntryRefundStates("entry:states", vaultTest.Player1.String(), "entry:1")
130	uassert.Equal(t, "true", states[0]["fundRefunded"])
131	uassert.Equal(t, "25", states[0]["fundAmount"])
132}
133
134func TestPaymentStateQueriesCSV(cur realm, t *testing.T) {
135	vaultTest.Setup(cross(cur), t)
136	queries := []struct {
137		query    func(string, string, string) []map[string]string
138		mismatch string
139		keyName  string
140	}{
141		{ListEntryRefundStates, "entry refund value count mismatch", "entry key"},
142		{ListParticipationPaymentStates, "participation payment value count mismatch", "payment key"},
143	}
144	for _, item := range queries {
145		uassert.Equal(t, 0, len(item.query("", "", "")))
146		uassert.PanicsWithMessage(t, cur, item.mismatch, func() {
147			item.query("missing,missing", vaultTest.Player1.String(), "key")
148		})
149		uassert.PanicsWithMessage(t, cur, "process key length must be between 1 and 128", func() {
150			item.query("", vaultTest.Player1.String(), "key")
151		})
152		uassert.PanicsWithMessage(t, cur, "invalid participation owner", func() {
153			item.query("missing", "invalid", "key")
154		})
155		uassert.PanicsWithMessage(t, cur, item.keyName+" length must be between 1 and 128", func() {
156			item.query("missing", vaultTest.Player1.String(), "")
157		})
158		uassert.PanicsWithMessage(t, cur, "process key length must be between 1 and 128", func() {
159			item.query("missing,", vaultTest.Player1.String()+",", "key,")
160		})
161		uassert.PanicsWithMessage(t, cur, "process key length must be between 1 and 128", func() {
162			item.query("missing,,missing", strings.Repeat(vaultTest.Player1.String()+",", 2)+vaultTest.Player1.String(), "key,key,key")
163		})
164		processes := strings.Repeat("missing,", gameVaultList-1) + "missing"
165		owners := strings.Repeat(vaultTest.Player1.String()+",", gameVaultList-1) + vaultTest.Player1.String()
166		keys := strings.Repeat("key,", gameVaultList-1) + "key"
167		uassert.Equal(t, gameVaultList, len(item.query(processes, owners, keys)))
168		uassert.PanicsWithMessage(t, cur, "count exceeds game vault list limit", func() {
169			item.query(processes+",missing", owners+","+vaultTest.Player1.String(), keys+",key")
170		})
171	}
172}
173
174func TestListParticipationPaymentStates(cur realm, t *testing.T) {
175	vaultTest.Setup(cross(cur), t)
176	vaultTest.CreatePool(cross(cur), "pool:payment-states")
177	processID := vaultTest.CreateParticipationProcess(cross(cur), "process:states", "pool:payment-states", 25)
178	fundID := vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participation:1", "payment:1", 25)
179	states := ListParticipationPaymentStates(
180		"process:missing,process:states,process:states,process:states",
181		strings.Repeat(vaultTest.Player1.String()+",", 3)+vaultTest.Player1.String(),
182		"payment:1,payment:missing,payment:1,payment:1",
183	)
184	uassert.Equal(t, 4, len(states))
185	uassert.Equal(t, "process:missing", states[0]["requestedProcessKey"])
186	uassert.Equal(t, "0", states[0]["processId"])
187	uassert.Equal(t, "0", states[0]["fundId"])
188	uassert.Equal(t, strconv.FormatUint(processID, 10), states[1]["processId"])
189	uassert.Equal(t, "0", states[1]["fundId"])
190	uassert.Equal(t, "25", states[2]["participationFee"])
191	uassert.Equal(t, strconv.FormatUint(fundID, 10), states[2]["fundId"])
192	uassert.Equal(t, "payment:1", states[2]["fundPaymentKey"])
193	uassert.Equal(t, "participation:1", states[2]["participationKey"])
194	uassert.Equal(t, "1", states[2]["fundEffectiveStatus"])
195	states[2]["fundOwner"] = "changed"
196	uassert.Equal(t, vaultTest.Player1.String(), states[3]["fundOwner"])
197	uassert.Equal(t, vaultTest.Player1, GetParticipationFund(fundID).Owner)
198
199	testing.SetOriginCaller(vaultTest.Operator)
200	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
201	testing.SetOriginSend(chain.Coins{})
202	RefundParticipationFund(cross(cur), fundID, "refund:payment-states")
203	states = ListParticipationPaymentStates("process:states", vaultTest.Player1.String(), "payment:1")
204	uassert.Equal(t, "true", states[0]["fundRefunded"])
205	uassert.Equal(t, "3", states[0]["fundEffectiveStatus"])
206	CloseParticipationProcess(cross(cur), processID)
207	CommitParticipationProcess(cross(cur), processID, "commit:payment-states")
208	states = ListParticipationPaymentStates("process:states", vaultTest.Player1.String(), "payment:1")
209	uassert.Equal(t, "3", states[0]["processStatus"])
210	uassert.Equal(t, "3", states[0]["fundEffectiveStatus"])
211}
212
213func TestParticipationPaymentValidation(cur realm, t *testing.T) {
214	vaultTest.Setup(cross(cur), t)
215	vaultTest.CreatePool(cross(cur), "pool:validation")
216	processID := vaultTest.CreateParticipationProcess(cross(cur), "participation:validation", "pool:validation", 25)
217
218	uassert.AbortsWithMessage(t, cur, "exact payment required: expected 25ugnot, got 24ugnot", func() {
219		vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:under", 24)
220	})
221	uassert.AbortsWithMessage(t, cur, "exact payment required: expected 25ugnot, got 26ugnot", func() {
222		vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:over", 26)
223	})
224	testing.SetOriginCaller(vaultTest.Player1)
225	testing.SetRealm(testing.NewUserRealm(vaultTest.Player1))
226	wrongDenom := chain.Coins{{"utest", 25}}
227	testing.IssueCoins(chain.PackageAddress("gno.land/r/akkadia/beta/game_vault"), wrongDenom)
228	testing.SetOriginSend(wrongDenom)
229	uassert.AbortsWithMessage(t, cur, "exact payment required: expected 25ugnot, got 25utest", func() {
230		DepositParticipation(cross(cur), processID, "participant:1", "payment:wrong-denom")
231	})
232	vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:1", 25)
233	uassert.AbortsWithMessage(t, cur, "payment key already processed", func() {
234		vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:2", "payment:1", 25)
235	})
236}
237
238func TestVaultRejectsUnexpectedCoinsAndOverflow(cur realm, t *testing.T) {
239	vaultTest.Setup(cross(cur), t)
240	testing.SetOriginCaller(vaultTest.Operator)
241	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
242	coins := chain.Coins{{"ugnot", 1}}
243	testing.IssueCoins(chain.PackageAddress("gno.land/r/akkadia/beta/game_vault"), coins)
244	testing.SetOriginSend(coins)
245	uassert.AbortsWithMessage(t, cur, "attached coins not allowed", func() {
246		CreateRewardPool(cross(cur), "pool:coins", vaultTest.GameWorldID)
247	})
248
249	vaultTest.CreatePool(cross(cur), "pool:overflow")
250	processID := vaultTest.CreateParticipationProcess(cross(cur), "participation:overflow", "pool:overflow", 1)
251	accountedUgnotTotal = maxInt64
252	uassert.AbortsWithMessage(t, cur, "vault fund amount overflow", func() {
253		vaultTest.DepositParticipation(cross(cur), vaultTest.Player1, processID, "participant:1", "payment:overflow", 1)
254	})
255}
256
257func TestVaultRejectsMissingGameWorld(cur realm, t *testing.T) {
258	vaultTest.Setup(cross(cur), t)
259	testing.SetOriginCaller(vaultTest.Operator)
260	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
261	testing.SetOriginSend(chain.Coins{})
262
263	uassert.AbortsWithMessage(t, cur, "game world not found: 2", func() {
264		CreateRewardPool(cross(cur), "pool:missing-world", vaultTest.GameWorldID+1)
265	})
266}
267
268func TestParticipationProcessRequiresRewardPoolKey(cur realm, t *testing.T) {
269	vaultTest.Setup(cross(cur), t)
270	uassert.AbortsWithMessage(t, cur, "reward pool not found: pool:missing", func() {
271		vaultTest.CreateParticipationProcess(cross(cur), "participation:missing", "pool:missing", 10)
272	})
273}
274
275func TestEntryProcessFundingAndRefund(cur realm, t *testing.T) {
276	vaultTest.Setup(cross(cur), t)
277	processID := vaultTest.CreateEntryProcess(cross(cur), "entry:1", 10)
278
279	firstFundID := vaultTest.DepositEntry(cross(cur), vaultTest.Player1, processID, "participant:1", "entry:1", 10)
280	secondFundID := vaultTest.DepositEntry(cross(cur), vaultTest.Player1, processID, "participant:1", "entry:2", 10)
281	vaultTest.DepositEntry(cross(cur), vaultTest.Player2, processID, "participant:1", "entry:1", 10)
282
283	uassert.Equal(t, firstFundID, GetEntryFundID(processID, vaultTest.Player1, "entry:1"))
284	uassert.Equal(t, 2, GetEntryFundCount(processID, vaultTest.Player1, "participant:1"))
285	ids := ListEntryFundIDs(processID, vaultTest.Player1, "participant:1", 1, 10)
286	uassert.Equal(t, 2, len(ids))
287	uassert.Equal(t, secondFundID, ids[0])
288	uassert.Equal(t, firstFundID, ids[1])
289
290	testing.SetOriginCaller(vaultTest.Operator)
291	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
292	testing.SetOriginSend(chain.Coins{})
293	CloseEntryProcess(cross(cur), processID)
294	RefundEntryFund(cross(cur), firstFundID, "entry-refund:1")
295	uassert.Equal(t, int(EntryFundStatusRefunded), int(GetEntryFundStatus(firstFundID)))
296	uassert.Equal(t, int64(20), GetEntryProcess(processID).HeldBalance)
297}
298
299func TestEntryProcessValidationAndCancel(cur realm, t *testing.T) {
300	vaultTest.Setup(cross(cur), t)
301	uassert.AbortsWithMessage(t, cur, "entry fee must be positive", func() {
302		vaultTest.CreateEntryProcess(cross(cur), "entry:free", 0)
303	})
304	processID := vaultTest.CreateEntryProcess(cross(cur), "entry:cancel", 10)
305	vaultTest.DepositEntry(cross(cur), vaultTest.Player1, processID, "participant:1", "entry:1", 10)
306	uassert.AbortsWithMessage(t, cur, "entry key already processed", func() {
307		vaultTest.DepositEntry(cross(cur), vaultTest.Player1, processID, "participant:2", "entry:1", 10)
308	})
309
310	testing.SetOriginCaller(vaultTest.Operator)
311	testing.SetRealm(testing.NewUserRealm(vaultTest.Operator))
312	testing.SetOriginSend(chain.Coins{})
313	CancelEntryProcess(cross(cur), processID)
314	uassert.Equal(t, int(EntryProcessStatusCanceled), int(GetEntryProcess(processID).Status))
315	uassert.AbortsWithMessage(t, cur, "entry process is not open", func() {
316		vaultTest.DepositEntry(cross(cur), vaultTest.Player2, processID, "participant:2", "entry:2", 10)
317	})
318}