funding.gno
3.71 Kb · 126 lines
1package game_vault
2
3import (
4 "chain"
5 "chain/banker"
6 "strconv"
7
8 "gno.land/p/akkadia/beta/accesscontrol"
9 "gno.land/r/akkadia/beta/admin"
10)
11
12type SystemFunding struct {
13 ID uint64
14 PoolID uint64
15 FundingKey string
16 Depositor address
17 Amount int64
18 Refunded bool
19}
20
21func DepositSystemFunding(cur realm, poolID uint64, fundingKey string) uint64 {
22 depositor := accesscontrol.MustGetAdminOrOperatorCaller(0, cur, admin.IsAdmin, admin.IsOperator)
23 assertKeyLength(fundingKey, "funding key")
24 if systemFundingIDs.Has(fundingKey) {
25 panic("funding key already processed")
26 }
27 pool := GetRewardPool(poolID)
28 if pool.Status != RewardPoolStatusOpen {
29 panic("reward pool is not open")
30 }
31 amount := getAttachedUgnotDeposit()
32 if latestSystemFundingID == maxUint64 {
33 panic("system funding id exhausted")
34 }
35 if pool.Balance > maxInt64-amount || pool.SystemFundedTotal > maxInt64-amount || accountedUgnotTotal > maxInt64-amount {
36 panic("vault fund amount overflow")
37 }
38
39 latestSystemFundingID++
40 fundingID := latestSystemFundingID
41 treeSet(systemFundings, fundingID, SystemFunding{
42 ID: fundingID,
43 PoolID: poolID,
44 FundingKey: fundingKey,
45 Depositor: depositor,
46 Amount: amount,
47 })
48 systemFundingIDs.Set(fundingKey, fundingID)
49 getOrCreateIDSet(poolSystemFundingIDs, poolID).Set(uint64Key(fundingID), true)
50 pool.SystemFundedTotal += amount
51 pool.Balance += amount
52 treeSet(rewardPools, poolID, pool)
53 accountedUgnotTotal += amount
54 return fundingID
55}
56
57func RefundSystemFunding(cur realm, poolID uint64, fundingKey, operationKey string) uint64 {
58 executor := accesscontrol.MustGetAdminOrOperatorCaller(0, cur, admin.IsAdmin, admin.IsOperator)
59 assertNoAttachedCoins()
60 assertNewOperationKey(operationKey)
61 pool := GetRewardPool(poolID)
62 if pool.Status != RewardPoolStatusCanceled {
63 panic("reward pool must be canceled before refund")
64 }
65 funding := GetSystemFundingByKey(fundingKey)
66 if funding.PoolID != poolID {
67 panic("system funding belongs to another reward pool")
68 }
69 if funding.Refunded {
70 panic("system funding already refunded")
71 }
72 if pool.Balance < funding.Amount {
73 panic("insufficient system funding balance")
74 }
75
76 pool.Balance -= funding.Amount
77 pool.SystemRefundedTotal += funding.Amount
78 treeSet(rewardPools, poolID, pool)
79 funding.Refunded = true
80 treeSet(systemFundings, funding.ID, funding)
81 return recordAndSendRefund(cross(cur), poolID, operationKey, fundingKey, funding.Depositor, funding.Amount, "system", executor)
82}
83
84func GetSystemFunding(fundingID uint64) SystemFunding {
85 value, found := treeGet(systemFundings, fundingID)
86 if !found {
87 panic("system funding not found: " + strconv.FormatUint(fundingID, 10))
88 }
89 return value.(SystemFunding)
90}
91
92func GetLatestSystemFundingID() uint64 { return latestSystemFundingID }
93
94func GetSystemFundingByKey(fundingKey string) SystemFunding {
95 assertKeyLength(fundingKey, "funding key")
96 value, found := stringGet(systemFundingIDs, fundingKey)
97 if !found {
98 panic("system funding not found: " + fundingKey)
99 }
100 return GetSystemFunding(value.(uint64))
101}
102
103func GetSystemFundingCountByPool(poolID uint64) int {
104 GetRewardPool(poolID)
105 ids, found := getIDSet(poolSystemFundingIDs, poolID)
106 if !found {
107 return 0
108 }
109 return ids.Size()
110}
111
112func ListSystemFundingIDsByPool(poolID uint64, page, count int) []uint64 {
113 GetRewardPool(poolID)
114 ids, _ := getIDSet(poolSystemFundingIDs, poolID)
115 return listIDs(ids, page, count)
116}
117
118func GetAccountedUgnotTotal() int64 { return accountedUgnotTotal }
119
120func GetUnaccountedUgnotTotal() int64 {
121 actual := banker.NewReadonlyBanker().GetCoins(chain.PackageAddress("gno.land/r/akkadia/beta/game_vault")).AmountOf("ugnot")
122 if actual < accountedUgnotTotal {
123 panic("vault fund accounting exceeds realm balance")
124 }
125 return actual - accountedUgnotTotal
126}