protocol_fee_token_accumulator.gno
4.42 Kb · 137 lines
1package staker
2
3import (
4 ufmt "gno.land/p/nt/ufmt/v0"
5
6 u256 "gno.land/p/gnoswap/uint256/v1"
7)
8
9// ProtocolFeeTokenAccumulator tracks the accumulated protocol fee per stake of one token.
10//
11// Fees are folded in per accrual epoch, each against the total stake in force during
12// that epoch. The value after folding each epoch is kept in history so that a staker's
13// reward can be settled later against the accumulator as it stood at any epoch.
14type ProtocolFeeTokenAccumulator struct {
15 // accumulatedX128PerStake is the latest accumulated fee per stake, scaled by 2^128
16 accumulatedX128PerStake *u256.Uint
17 // history maps an epoch to the accumulated value after that epoch's fees were folded
18 history *UintTree // epoch -> *u256.Uint
19 // firstEpoch is the first epoch a fee was folded for, or -1 when none was
20 firstEpoch int64
21 // foldedEpoch is the last epoch whose fees are known to be fully folded, or -1
22 foldedEpoch int64
23 // protocolFeeAmount is the total fee amount folded in
24 protocolFeeAmount int64
25}
26
27// NewProtocolFeeTokenAccumulator creates an empty accumulator with no folded
28// epochs or protocol fees recorded.
29//
30// Returns:
31// - *ProtocolFeeTokenAccumulator: accumulator initialized with zero values and
32// empty epoch history.
33func NewProtocolFeeTokenAccumulator() *ProtocolFeeTokenAccumulator {
34 return &ProtocolFeeTokenAccumulator{
35 accumulatedX128PerStake: u256.Zero(),
36 history: NewUintTree(),
37 firstEpoch: -1,
38 foldedEpoch: -1,
39 protocolFeeAmount: 0,
40 }
41}
42
43/* Getters */
44
45// GetAccumulatedX128PerStake returns the latest accumulated protocol fee per stake,
46// scaled by 2^128.
47//
48// Returns:
49// - *u256.Uint: latest accumulated fee-per-stake value in Q128 fixed-point form.
50func (a *ProtocolFeeTokenAccumulator) GetAccumulatedX128PerStake() *u256.Uint {
51 return a.accumulatedX128PerStake
52}
53
54// GetAccumulatedX128PerStakeAt returns the accumulated value after the fees of the
55// latest folded epoch at or before epoch, or zero when no fee was folded by then.
56//
57// Parameters:
58// - epoch: accrual epoch whose latest post-fold value is requested.
59//
60// Returns:
61// - *u256.Uint: accumulated fee per stake in Q128 fixed-point form, or zero
62// when no fee was folded by epoch.
63func (a *ProtocolFeeTokenAccumulator) GetAccumulatedX128PerStakeAt(epoch int64) *u256.Uint {
64 if epoch < 0 {
65 return u256.Zero()
66 }
67
68 accumulated := u256.Zero()
69 a.history.ReverseIterate(0, epoch, func(_ int64, value any) bool {
70 stored, castOk := value.(*u256.Uint)
71 if !castOk {
72 panic(ufmt.Sprintf("failed to cast accumulated value: %T", value))
73 }
74 accumulated = stored
75 return true
76 })
77
78 return accumulated
79}
80
81// GetFirstEpoch returns the first epoch for which a fee was folded.
82//
83// Returns:
84// - int64: first folded epoch, or -1 when no fee has been folded.
85func (a *ProtocolFeeTokenAccumulator) GetFirstEpoch() int64 {
86 return a.firstEpoch
87}
88
89// GetFoldedEpoch returns the last epoch known to be fully folded.
90//
91// Returns:
92// - int64: last fully folded epoch, or -1 when no epoch is fully folded.
93func (a *ProtocolFeeTokenAccumulator) GetFoldedEpoch() int64 {
94 return a.foldedEpoch
95}
96
97// GetProtocolFeeAmount returns the total protocol fee amount folded into the
98// accumulator.
99//
100// Returns:
101// - int64: total fee amount folded for this token.
102func (a *ProtocolFeeTokenAccumulator) GetProtocolFeeAmount() int64 {
103 return a.protocolFeeAmount
104}
105
106/* Setters */
107
108// SetAccumulatedX128PerStakeAt stores value as the accumulated amount after epoch's
109// fees and makes it the latest value.
110//
111// Parameters:
112// - epoch: epoch whose post-fold accumulator value is being stored.
113// - value: accumulated fee-per-stake value in Q128 fixed-point form.
114func (a *ProtocolFeeTokenAccumulator) SetAccumulatedX128PerStakeAt(epoch int64, value *u256.Uint) {
115 stored := u256.Zero().Set(value)
116 a.accumulatedX128PerStake = stored
117 a.history.Set(epoch, stored)
118 if a.firstEpoch < 0 || epoch < a.firstEpoch {
119 a.firstEpoch = epoch
120 }
121}
122
123// SetFoldedEpoch records the last epoch whose protocol fees are fully folded.
124//
125// Parameters:
126// - epoch: latest fully folded accrual epoch.
127func (a *ProtocolFeeTokenAccumulator) SetFoldedEpoch(epoch int64) {
128 a.foldedEpoch = epoch
129}
130
131// SetProtocolFeeAmount records the total protocol fee amount folded so far.
132//
133// Parameters:
134// - amount: total folded protocol fee amount for this token.
135func (a *ProtocolFeeTokenAccumulator) SetProtocolFeeAmount(amount int64) {
136 a.protocolFeeAmount = amount
137}