protocol_fee_reward_state.gno
10.53 Kb · 303 lines
1package staker
2
3import (
4 bptree "gno.land/p/nt/bptree/v0"
5 ufmt "gno.land/p/nt/ufmt/v0"
6
7 u256 "gno.land/p/gnoswap/uint256/v1"
8)
9
10// ProtocolFeeRewardState tracks the protocol fee rewards of one staker.
11//
12// Ordinary stake changes append one ProtocolFeeStakeEvent; Redelegate performs
13// a remove plus an add and appends two events. Each token is settled on its own
14// from those events, so the state keeps a per-token cursor into the event
15// history rather than a reward debt for every token at once.
16type ProtocolFeeRewardState struct {
17 // stakedAmount is the current amount staked
18 stakedAmount int64
19 // stakeEvents records the staked amount in force from each stake change, by index
20 stakeEvents *UintTree // index -> *ProtocolFeeStakeEvent
21 // stakeEventCount is the number of recorded stake events
22 stakeEventCount int64
23 // tokenStates maps a token path to the settlement state of that token
24 tokenStates *bptree.BPTree // tokenPath -> *ProtocolFeeTokenRewardState
25 // claimedTimestamp is the last timestamp at which every token was collected
26 claimedTimestamp int64
27}
28
29// ProtocolFeeStakeEvent is one stake change: from epoch on, stakedAmount was staked.
30type ProtocolFeeStakeEvent struct {
31 epoch int64
32 stakedAmount int64
33}
34
35// GetEpoch returns the accrual epoch from which this stake event applies.
36//
37// Returns:
38// - int64: epoch at which the stake amount became effective
39func (e *ProtocolFeeStakeEvent) GetEpoch() int64 { return e.epoch }
40
41// GetStakedAmount returns the stake amount in force for this event.
42//
43// Returns:
44// - int64: staked amount associated with the event
45func (e *ProtocolFeeStakeEvent) GetStakedAmount() int64 { return e.stakedAmount }
46
47// ProtocolFeeTokenRewardState is the settlement state of one token for one staker.
48//
49// Stake events up to eventCursor are folded into earnedX128. The open segment starts
50// where the last folded event left the accumulator (segmentStartX128) with
51// segmentStakedAmount staked.
52type ProtocolFeeTokenRewardState struct {
53 // eventCursor is the number of stake events already folded in
54 eventCursor int64
55 // segmentStakedAmount is the amount staked during the open segment
56 segmentStakedAmount int64
57 // segmentStartX128 is the accumulated fee per stake at the start of the open segment
58 segmentStartX128 *u256.Uint
59 // earnedX128 is the reward earned by closed segments and not yet collected, scaled by 2^128
60 earnedX128 *u256.Uint
61 // claimedReward is the total reward collected so far
62 claimedReward int64
63}
64
65// NewProtocolFeeRewardState creates an empty state for a staker with no stake.
66//
67// Returns:
68// - *ProtocolFeeRewardState: initialized reward state with empty event and token trees
69func NewProtocolFeeRewardState() *ProtocolFeeRewardState {
70 return &ProtocolFeeRewardState{
71 stakedAmount: 0,
72 stakeEvents: NewUintTree(),
73 stakeEventCount: 0,
74 tokenStates: bptree.NewBPTreeN(16),
75 claimedTimestamp: 0,
76 }
77}
78
79// NewProtocolFeeTokenRewardState creates the settlement state of a token whose open
80// segment starts at the given cursor, stake and accumulator value.
81//
82// Parameters:
83// - eventCursor: number of stake events already folded into this token state
84// - segmentStakedAmount: stake amount in force during the open segment
85// - segmentStartX128: accumulated fee-per-stake value at the open segment start, scaled by 2^128
86//
87// Returns:
88// - *ProtocolFeeTokenRewardState: token settlement state with zero closed-segment earnings and claimed reward
89func NewProtocolFeeTokenRewardState(eventCursor int64, segmentStakedAmount int64, segmentStartX128 *u256.Uint) *ProtocolFeeTokenRewardState {
90 return &ProtocolFeeTokenRewardState{
91 eventCursor: eventCursor,
92 segmentStakedAmount: segmentStakedAmount,
93 segmentStartX128: u256.Zero().Set(segmentStartX128),
94 earnedX128: u256.Zero(),
95 claimedReward: 0,
96 }
97}
98
99/* ProtocolFeeRewardState getters */
100
101// GetStakedAmount returns the current stake amount tracked for the staker.
102//
103// Returns:
104// - int64: current staked amount
105func (p *ProtocolFeeRewardState) GetStakedAmount() int64 {
106 return p.stakedAmount
107}
108
109// GetStakeEventCount returns the number of stake-change events recorded.
110//
111// Returns:
112// - int64: count of indexed stake events
113func (p *ProtocolFeeRewardState) GetStakeEventCount() int64 {
114 return p.stakeEventCount
115}
116
117// GetStakeEvent returns the indexed stake event.
118//
119// Parameters:
120// - index: zero-based stake-event index
121//
122// Returns:
123// - *ProtocolFeeStakeEvent: event at index, or nil when no event is stored there
124// - bool: true when an event exists at index; false when the index is absent
125func (p *ProtocolFeeRewardState) GetStakeEvent(index int64) (*ProtocolFeeStakeEvent, bool) {
126 ei, ok := p.stakeEvents.Get(index)
127 if !ok {
128 return nil, false
129 }
130 event, castOk := ei.(*ProtocolFeeStakeEvent)
131 if !castOk {
132 panic(ufmt.Sprintf("failed to cast stake event: %T", ei))
133 }
134 return event, true
135}
136
137// GetTokenState returns the settlement state of tokenPath, or false when the token was
138// never settled for this staker.
139//
140// Parameters:
141// - tokenPath: registered token path whose per-staker settlement state is requested
142//
143// Returns:
144// - *ProtocolFeeTokenRewardState: token settlement state, or nil when it has not been initialized
145// - bool: true when tokenPath has a stored settlement state, otherwise false
146func (p *ProtocolFeeRewardState) GetTokenState(tokenPath string) (*ProtocolFeeTokenRewardState, bool) {
147 ti := p.tokenStates.Get(tokenPath)
148 if ti == nil {
149 return nil, false
150 }
151 tokenState, castOk := ti.(*ProtocolFeeTokenRewardState)
152 if !castOk {
153 panic(ufmt.Sprintf("failed to cast token reward state: %T", ti))
154 }
155 return tokenState, true
156}
157
158// GetTokenPaths returns every token path settled for this staker, in key order.
159//
160// Returns:
161// - []string: token paths with stored settlement state, ordered by the underlying tree keys
162func (p *ProtocolFeeRewardState) GetTokenPaths() []string {
163 tokenPaths := make([]string, 0, p.tokenStates.Size())
164 p.tokenStates.Iterate("", "", func(key string, _ any) bool {
165 tokenPaths = append(tokenPaths, key)
166 return false
167 })
168 return tokenPaths
169}
170
171// GetClaimedReward returns the total reward of tokenPath collected so far.
172//
173// Parameters:
174// - tokenPath: token path whose accumulated claimed reward is requested
175//
176// Returns:
177// - int64: total reward collected for tokenPath, or zero when no token state exists
178func (p *ProtocolFeeRewardState) GetClaimedReward(tokenPath string) int64 {
179 tokenState, ok := p.GetTokenState(tokenPath)
180 if !ok {
181 return 0
182 }
183 return tokenState.GetClaimedReward()
184}
185
186// GetClaimedTimestamp returns the last timestamp at which all token rewards were collected.
187//
188// Returns:
189// - int64: Unix timestamp recorded for the most recent all-token collection
190func (p *ProtocolFeeRewardState) GetClaimedTimestamp() int64 {
191 return p.claimedTimestamp
192}
193
194/* ProtocolFeeRewardState setters */
195
196// SetStakedAmount updates the current stake amount tracked for the staker.
197//
198// Parameters:
199// - stakedAmount: new current staked amount
200func (p *ProtocolFeeRewardState) SetStakedAmount(stakedAmount int64) {
201 p.stakedAmount = stakedAmount
202}
203
204// AppendStakeEvent records that stakedAmount is staked from epoch on.
205//
206// Parameters:
207// - epoch: accrual epoch at which this stake amount becomes effective
208// - stakedAmount: stake amount in force from epoch onward
209func (p *ProtocolFeeRewardState) AppendStakeEvent(epoch int64, stakedAmount int64) {
210 p.stakeEvents.Set(p.stakeEventCount, &ProtocolFeeStakeEvent{
211 epoch: epoch,
212 stakedAmount: stakedAmount,
213 })
214 p.stakeEventCount++
215}
216
217// SetTokenState stores the settlement state for a token path.
218//
219// Parameters:
220// - tokenPath: token path used as the settlement-state key
221// - tokenState: per-token settlement state to store
222func (p *ProtocolFeeRewardState) SetTokenState(tokenPath string, tokenState *ProtocolFeeTokenRewardState) {
223 p.tokenStates.Set(tokenPath, tokenState)
224}
225
226// SetClaimedTimestamp records the timestamp at which all token rewards were collected.
227//
228// Parameters:
229// - claimedTimestamp: Unix timestamp of the all-token collection
230func (p *ProtocolFeeRewardState) SetClaimedTimestamp(claimedTimestamp int64) {
231 p.claimedTimestamp = claimedTimestamp
232}
233
234/* ProtocolFeeTokenRewardState getters and setters */
235
236// GetEventCursor returns the number of stake events already folded for this token.
237//
238// Returns:
239// - int64: count of folded stake events
240func (t *ProtocolFeeTokenRewardState) GetEventCursor() int64 {
241 return t.eventCursor
242}
243
244// GetSegmentStakedAmount returns the stake amount in the open segment.
245//
246// Returns:
247// - int64: stake amount used while settling the open segment
248func (t *ProtocolFeeTokenRewardState) GetSegmentStakedAmount() int64 {
249 return t.segmentStakedAmount
250}
251
252// GetSegmentStartX128 returns the accumulator value at the open segment start.
253//
254// Returns:
255// - *u256.Uint: fee-per-stake accumulator at segment start, scaled by 2^128
256func (t *ProtocolFeeTokenRewardState) GetSegmentStartX128() *u256.Uint {
257 return t.segmentStartX128
258}
259
260// GetEarnedX128 returns closed-segment earnings awaiting collection.
261//
262// Returns:
263// - *u256.Uint: unclaimed reward accumulator scaled by 2^128
264func (t *ProtocolFeeTokenRewardState) GetEarnedX128() *u256.Uint {
265 return t.earnedX128
266}
267
268// GetClaimedReward returns the total reward collected for this token state.
269//
270// Returns:
271// - int64: cumulative collected reward amount
272func (t *ProtocolFeeTokenRewardState) GetClaimedReward() int64 {
273 return t.claimedReward
274}
275
276// SetSegment moves the open segment: events up to eventCursor are folded, and the
277// segment starts at segmentStartX128 with segmentStakedAmount staked.
278//
279// Parameters:
280// - eventCursor: number of stake events folded into the new segment
281// - segmentStakedAmount: stake amount in force for the new open segment
282// - segmentStartX128: fee-per-stake accumulator at the new segment start, scaled by 2^128
283func (t *ProtocolFeeTokenRewardState) SetSegment(eventCursor int64, segmentStakedAmount int64, segmentStartX128 *u256.Uint) {
284 t.eventCursor = eventCursor
285 t.segmentStakedAmount = segmentStakedAmount
286 t.segmentStartX128 = u256.Zero().Set(segmentStartX128)
287}
288
289// SetEarnedX128 replaces the closed-segment earnings accumulator.
290//
291// Parameters:
292// - earnedX128: unclaimed earnings accumulator scaled by 2^128
293func (t *ProtocolFeeTokenRewardState) SetEarnedX128(earnedX128 *u256.Uint) {
294 t.earnedX128 = u256.Zero().Set(earnedX128)
295}
296
297// SetClaimedReward replaces the cumulative collected reward amount.
298//
299// Parameters:
300// - claimedReward: total reward collected for this token state
301func (t *ProtocolFeeTokenRewardState) SetClaimedReward(claimedReward int64) {
302 t.claimedReward = claimedReward
303}