protocol_fee_state.gno
7.10 Kb · 209 lines
1package protocol_fee
2
3import (
4 bptree "gno.land/p/nt/bptree/v0"
5 ufmt "gno.land/p/nt/ufmt/v0"
6
7 gnsmath "gno.land/p/gnoswap/gnsmath"
8 prabc "gno.land/p/gnoswap/rbac"
9 "gno.land/r/gnoswap/access"
10 "gno.land/r/gnoswap/common"
11 "gno.land/r/gnoswap/protocol_fee"
12)
13
14// protocolFeeState holds all the state variables for protocol fee management
15type protocolFeeState struct {
16 store protocol_fee.IProtocolFeeStore
17}
18
19// DevOpsPct returns the percentage of protocol fees allocated to DevOps.
20func (pfs *protocolFeeState) DevOpsPct() int64 {
21 return pfs.store.GetDevOpsPct()
22}
23
24// GovStakerPct returns the percentage of protocol fees allocated to Gov/Staker.
25func (pfs *protocolFeeState) GovStakerPct() int64 {
26 return 10000 - pfs.store.GetDevOpsPct()
27}
28
29// AccuToGovStaker returns the accumulated amounts distributed to Gov/Staker.
30func (pfs *protocolFeeState) AccuToGovStaker() *bptree.BPTree {
31 return pfs.store.GetAccuToGovStaker()
32}
33
34// AccuToDevOps returns the accumulated amounts distributed to DevOps.
35func (pfs *protocolFeeState) AccuToDevOps() *bptree.BPTree {
36 return pfs.store.GetAccuToDevOps()
37}
38
39// ActualDistributedToGovStaker returns the cumulative amounts actually distributed to Gov/Staker.
40func (pfs *protocolFeeState) ActualDistributedToGovStaker() *bptree.BPTree {
41 return pfs.store.GetDistributedToGovStakerHistory()
42}
43
44// ActualDistributedToDevOps returns the cumulative amounts actually distributed to DevOps.
45func (pfs *protocolFeeState) ActualDistributedToDevOps() *bptree.BPTree {
46 return pfs.store.GetDistributedToDevOpsHistory()
47}
48
49// ReservedTokens returns token paths reserved for distribution.
50func (pfs *protocolFeeState) ReservedTokens() []string {
51 return pfs.store.GetReservedTokens()
52}
53
54// distributeToDevOps distributes tokens to DevOps and updates related state.
55// Amount should be greater than 0 (already checked in DistributeProtocolFee).
56func (pfs *protocolFeeState) distributeToDevOps(_ int, rlm realm, token string, amount int64) error {
57 devOpsAddr := access.MustGetAddress(prabc.ROLE_DEVOPS.String())
58
59 if err := pfs.addActualDistributedToDevOps(0, rlm, token, amount); err != nil {
60 return err
61 }
62 common.SafeGRC20Transfer(cross(rlm), token, devOpsAddr, amount)
63
64 return nil
65}
66
67// distributeToGovStaker distributes tokens to Gov/Staker and updates related state.
68// Amount should be greater than 0 (already checked in DistributeProtocolFee).
69func (pfs *protocolFeeState) distributeToGovStaker(_ int, rlm realm, token string, amount int64) error {
70 govStakerAddr := access.MustGetAddress(prabc.ROLE_GOV_STAKER.String())
71
72 if err := pfs.addActualDistributedToGovStaker(0, rlm, token, amount); err != nil {
73 return err
74 }
75 common.SafeGRC20Transfer(cross(rlm), token, govStakerAddr, amount)
76
77 return nil
78}
79
80// setDevOpsPct sets the devOpsPct.
81func (pfs *protocolFeeState) setDevOpsPct(_ int, rlm realm, pct int64) (int64, error) {
82 if pct < 0 {
83 return 0, makeErrorWithDetail(
84 errInvalidPct,
85 ufmt.Sprintf("pct(%d) should not be negative", pct),
86 )
87 }
88 if pct > 10000 {
89 return 0, makeErrorWithDetail(
90 errInvalidPct,
91 ufmt.Sprintf("pct(%d) should not be bigger than 10000", pct),
92 )
93 }
94
95 if err := pfs.store.SetDevOpsPct(0, rlm, pct); err != nil {
96 return 0, err
97 }
98
99 return pct, nil
100}
101
102// setGovStakerPct sets the govStakerPct by calculating devOpsPct.
103func (pfs *protocolFeeState) setGovStakerPct(_ int, rlm realm, pct int64) (int64, error) {
104 if pct < 0 {
105 return 0, makeErrorWithDetail(
106 errInvalidPct,
107 ufmt.Sprintf("pct(%d) should not be negative", pct),
108 )
109 }
110
111 devOpsPct := 10000 - pct
112
113 if _, err := pfs.setDevOpsPct(0, rlm, devOpsPct); err != nil {
114 return 0, err
115 }
116
117 return pct, nil
118}
119
120// addAccuToGovStaker adds the amount to the accuToGovStaker by token path.
121func (pfs *protocolFeeState) addAccuToGovStaker(_ int, rlm realm, tokenPath string, amount int64) error {
122 before := pfs.GetAccuTransferToGovStakerByTokenPath(tokenPath)
123
124 // Check for overflow
125 after := gnsmath.SafeAddInt64(before, amount)
126 if err := pfs.store.SetAccuToGovStakerItem(0, rlm, tokenPath, after); err != nil {
127 return err
128 }
129 return nil
130}
131
132// addAccuToDevOps adds the amount to the accuToDevOps by token path.
133func (pfs *protocolFeeState) addAccuToDevOps(_ int, rlm realm, tokenPath string, amount int64) error {
134 before := pfs.GetAccuTransferToDevOpsByTokenPath(tokenPath)
135
136 // Check for overflow
137 after := gnsmath.SafeAddInt64(before, amount)
138 if err := pfs.store.SetAccuToDevOpsItem(0, rlm, tokenPath, after); err != nil {
139 return err
140 }
141 return nil
142}
143
144// addActualDistributedToGovStaker adds the amount to the actual distributed amount to gov/staker by token path.
145func (pfs *protocolFeeState) addActualDistributedToGovStaker(_ int, rlm realm, tokenPath string, amount int64) error {
146 before := pfs.GetActualDistributedToGovStakerByTokenPath(tokenPath)
147 after := gnsmath.SafeAddInt64(before, amount)
148 if err := pfs.store.SetDistributedToGovStakerHistoryItem(0, rlm, tokenPath, after); err != nil {
149 return err
150 }
151 return nil
152}
153
154// addActualDistributedToDevOps adds the amount to the actual distributed amount to devOps by token path.
155func (pfs *protocolFeeState) addActualDistributedToDevOps(_ int, rlm realm, tokenPath string, amount int64) error {
156 before := pfs.GetActualDistributedToDevOpsByTokenPath(tokenPath)
157 after := gnsmath.SafeAddInt64(before, amount)
158 if err := pfs.store.SetDistributedToDevOpsHistoryItem(0, rlm, tokenPath, after); err != nil {
159 return err
160 }
161 return nil
162}
163
164// GetAccuTransferToGovStakerByTokenPath gets the accumulated amount to gov/staker by token path.
165func (pfs *protocolFeeState) GetAccuTransferToGovStakerByTokenPath(tokenPath string) int64 {
166 return retrieveAmount(pfs.store.GetAccuToGovStaker(), tokenPath)
167}
168
169// GetAccuTransferToDevOpsByTokenPath gets the accumulated amount to devOps by token path.
170func (pfs *protocolFeeState) GetAccuTransferToDevOpsByTokenPath(tokenPath string) int64 {
171 return retrieveAmount(pfs.store.GetAccuToDevOps(), tokenPath)
172}
173
174// GetActualDistributedToGovStakerByTokenPath gets the actual distributed amount to gov/staker by token path.
175func (pfs *protocolFeeState) GetActualDistributedToGovStakerByTokenPath(tokenPath string) int64 {
176 return retrieveAmount(pfs.store.GetDistributedToGovStakerHistory(), tokenPath)
177}
178
179// GetActualDistributedToDevOpsByTokenPath gets the actual distributed amount to devOps by token path.
180func (pfs *protocolFeeState) GetActualDistributedToDevOpsByTokenPath(tokenPath string) int64 {
181 return retrieveAmount(pfs.store.GetDistributedToDevOpsHistory(), tokenPath)
182}
183
184// clearReservedTokens clears the reserved token index after distribution.
185func (pfs *protocolFeeState) clearReservedTokens(_ int, rlm realm) error {
186 if err := pfs.store.SetReservedTokens(0, rlm, []string{}); err != nil {
187 return err
188 }
189 return nil
190}
191
192// NewProtocolFeeState creates a new instance of protocolFeeState with initialized values
193func NewProtocolFeeStateBy(protocolFeeStore protocol_fee.IProtocolFeeStore) *protocolFeeState {
194 return &protocolFeeState{
195 store: protocolFeeStore,
196 }
197}
198
199func retrieveAmount(tree *bptree.BPTree, key string) int64 {
200 amountI := tree.Get(key)
201 if amountI == nil {
202 return 0
203 }
204 res, ok := amountI.(int64)
205 if !ok {
206 panic(ufmt.Sprintf("failed to cast amount to int64: %T", amountI))
207 }
208 return res
209}