-
Notifications
You must be signed in to change notification settings - Fork 47
/
WeightedStakingModule.sol
121 lines (112 loc) · 4.73 KB
/
WeightedStakingModule.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
pragma solidity ^0.5.17;
pragma experimental ABIEncoderV2;
import "./shared/CheckpointsShared.sol";
import "./shared/StakingShared.sol";
import "../../../proxy/modules/interfaces/IFunctionsList.sol";
/**
* @title Weighted Staking module contract.
* @notice Implements getters for weighted staking functionality
* */
contract WeightedStakingModule is IFunctionsList, StakingShared, CheckpointsShared {
/*************************** User Weighted Stake computation for fee sharing *******************************/
/**
* @notice Determine the prior weighted stake for an account as of a block number.
* Iterate through checkpoints adding up voting power.
* @dev Block number must be a finalized block or else this function will
* revert to prevent misinformation.
* Used for fee sharing, not voting.
*
* @param account The address of the account to check.
* @param blockNumber The block number to get the vote balance at.
* @param date The start date/timestamp from which to calculate the weighted stake.
* @return The weighted stake the account had as of the given block.
* */
function getPriorWeightedStake(
address account,
uint256 blockNumber,
uint256 date
) external view returns (uint96 priorWeightedStake) {
return _getPriorWeightedStake(account, blockNumber, date);
}
function _getPriorWeightedStake(
address account,
uint256 blockNumber,
uint256 date
) internal view returns (uint96 priorWeightedStake) {
/// @dev If date is not an exact break point, start weight computation from the previous break point (alternative would be the next).
uint256 start = _timestampToLockDate(date);
uint256 end = start + MAX_DURATION;
/// @dev Max 78 iterations.
for (uint256 i = start; i <= end; i += TWO_WEEKS) {
uint96 weightedStake = _weightedStakeByDate(account, i, start, blockNumber);
if (weightedStake > 0) {
priorWeightedStake = add96(
priorWeightedStake,
weightedStake,
"overflow on total weight calc"
); // WS12
}
}
}
/**
* @notice Compute the voting power for a specific date.
* Power = stake * weight
* @param account The user address.
* @param date The staking date to compute the power for. Adjusted to the previous valid lock date, if necessary.
* @param startDate The date for which we need to know the power of the stake. Adjusted to the previous valid lock date, if necessary.
* @param blockNumber The block number, needed for checkpointing.
* @return The staking power.
* */
function weightedStakeByDate(
address account,
uint256 date,
uint256 startDate,
uint256 blockNumber
) external view returns (uint96 power) {
date = _timestampToLockDate(date);
startDate = _timestampToLockDate(startDate);
return _weightedStakeByDate(account, date, startDate, blockNumber);
}
/**
* @notice Compute the voting power for a specific date.
* Power = stake * weight
* @param account The user address.
* @param date The staking date to compute the power for.
* @param startDate The date for which we need to know the power of the stake.
* @param blockNumber The block number, needed for checkpointing.
* @return The staking power.
* */
function _weightedStakeByDate(
address account,
uint256 date,
uint256 startDate,
uint256 blockNumber
) internal view returns (uint96 power) {
uint96 staked = _getPriorUserStakeByDate(account, date, blockNumber);
if (staked > 0) {
uint96 weight = _computeWeightByDate(date, startDate);
power = mul96(staked, weight, "mul overflow") / WEIGHT_FACTOR; // WS13
} else {
power = 0;
}
}
/**
* @notice Compute the weight for a specific date.
* @param date The unlocking date.
* @param startDate We compute the weight for the tokens staked until 'date' on 'startDate'.
* @return The weighted stake the account had as of the given block.
* */
function computeWeightByDate(
uint256 date,
uint256 startDate
) external pure returns (uint96 weight) {
return _computeWeightByDate(date, startDate);
}
function getFunctionsList() external pure returns (bytes4[] memory) {
bytes4[] memory functionsList = new bytes4[](3);
functionsList[0] = this.getPriorWeightedStake.selector;
functionsList[1] = this.weightedStakeByDate.selector;
functionsList[2] = this.computeWeightByDate.selector;
return functionsList;
}
}