Skip to content

Commit 1a6d91c

Browse files
authored
docs(protocol-contracts): add missing NatSpec docstrings to staking contracts (L-02) (#1685)
1 parent d54108e commit 1a6d91c

File tree

3 files changed

+159
-20
lines changed

3 files changed

+159
-20
lines changed

protocol-contracts/staking/contracts/OperatorRewarder.sol

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,35 @@ contract OperatorRewarder {
3535
mapping(address => int256) private _rewardsPaid;
3636
mapping(address => address) private _authorizedClaimers;
3737

38-
/// @notice Emitted when the beneficiary is transferred.
38+
/**
39+
* @notice Emitted when the beneficiary is transferred.
40+
* @param oldBeneficiary The previous beneficiary address.
41+
* @param newBeneficiary The new beneficiary address.
42+
*/
3943
event BeneficiaryTransferred(address oldBeneficiary, address newBeneficiary);
4044

4145
/// @notice Emitted when the contract is shut down.
4246
event Shutdown();
4347

44-
/// @notice Emitted when the maximum fee is updated.
48+
/**
49+
* @notice Emitted when the maximum fee is updated.
50+
* @param oldFee The previous maximum fee in basis points.
51+
* @param newFee The new maximum fee in basis points.
52+
*/
4553
event MaxFeeUpdated(uint16 oldFee, uint16 newFee);
4654

47-
/// @notice Emitted when the fee is updated.
55+
/**
56+
* @notice Emitted when the fee is updated.
57+
* @param oldFee The previous fee in basis points.
58+
* @param newFee The new fee in basis points.
59+
*/
4860
event FeeUpdated(uint16 oldFee, uint16 newFee);
4961

50-
/// @notice Emitted when an address is authorized to claim rewards on behalf of the receiver address.
62+
/**
63+
* @notice Emitted when an address is authorized to claim rewards on behalf of the receiver address.
64+
* @param receiver The address that will receive the rewards.
65+
* @param claimer The address authorized to claim rewards on behalf of the receiver.
66+
*/
5167
event ClaimerAuthorized(address receiver, address claimer);
5268

5369
/// @notice Error for invalid claimer address.
@@ -326,19 +342,34 @@ contract OperatorRewarder {
326342
return SafeCast.toUint256(SignedMath.max(0, allocation - _rewardsPaid[account]));
327343
}
328344

345+
/**
346+
* @notice Returns the total historical rewards distributed.
347+
* @dev This amount is computed as the sum of:
348+
* - the total rewards accumulated in the contract (see `_totalAssetsPlusPaidRewards()`) from
349+
* the start of the contract
350+
* - minus the fees not yet claimed by the beneficiary (see `_unpaidFee()`)
351+
* @return The total historical rewards amount.
352+
*/
329353
function historicalReward() public view virtual returns (uint256) {
330354
uint256 totalAssetsPlusPaidRewards = _totalAssetsPlusPaidRewards();
331355
return totalAssetsPlusPaidRewards - _unpaidFee(totalAssetsPlusPaidRewards);
332356
}
333357

334358
/**
335-
* @notice Returns unpaid fee.
359+
* @notice Returns unpaid fee (not yet claimed by the beneficiary).
336360
* @return Amount of unpaid fee.
337361
*/
338362
function unpaidFee() public view virtual returns (uint256) {
339363
return _unpaidFee(_totalAssetsPlusPaidRewards());
340364
}
341365

366+
/**
367+
* @notice Transfers the specified amount of tokens to the specified address.
368+
* @dev If the amount to transfer is greater than the balance of the rewarder, it will first
369+
* claim rewards from the ProtocolStaking contract.
370+
* @param to The address to transfer the tokens to.
371+
* @param amount The amount of tokens to transfer.
372+
*/
342373
function _doTransferOut(address to, uint256 amount) internal {
343374
IERC20 token_ = token();
344375
if (amount > token_.balanceOf(address(this))) {
@@ -370,7 +401,12 @@ contract OperatorRewarder {
370401
function _claimFee() internal virtual {
371402
uint256 totalAssetsPlusPaidRewards = _totalAssetsPlusPaidRewards();
372403
uint256 unpaidFee_ = _unpaidFee(totalAssetsPlusPaidRewards);
404+
405+
// Update the last claim value used to define the next unpaid fee (see `_unpaidFee()`).
406+
// This amount is exactly the same as `historicalReward()`, but we need to get the unpaid
407+
// fee separately in order to send the fee to the beneficiary below.
373408
_lastClaimTotalAssetsPlusPaidRewards = totalAssetsPlusPaidRewards - unpaidFee_;
409+
374410
if (unpaidFee_ > 0) {
375411
_doTransferOut(beneficiary(), unpaidFee_);
376412
}
@@ -410,19 +446,52 @@ contract OperatorRewarder {
410446
_feeBasisPoints = basisPoints;
411447
}
412448

449+
/**
450+
* @notice Returns the total assets plus earned rewards plus paid rewards.
451+
* @dev This amount is computed as the sum of:
452+
* - the balance of the rewarder contract (includes: total claimed but unpaid rewards + total donation + unpaid fees)
453+
* - the earned rewards by the operator staking contract (total earned but unpaid rewards)
454+
* - the total rewards paid to the delegators (total paid rewards)
455+
* @return Total assets plus earned rewards plus paid rewards.
456+
*/
413457
function _totalAssetsPlusPaidRewards() internal view returns (uint256) {
414458
return
415459
token().balanceOf(address(this)) +
416460
(isShutdown() ? 0 : protocolStaking().earned(address(operatorStaking()))) +
417461
_totalRewardsPaid;
418462
}
419463

464+
/**
465+
* @notice Returns the unpaid fee.
466+
* @dev This amount is computed as a percentage (defined in basis points) of the amount of rewards
467+
* accumulated since the last time fees were claimed. This works because:
468+
* - claiming fees snapshots the historical rewards amount in the `_lastClaimTotalAssetsPlusPaidRewards`
469+
* value, which monitors all rewards accumulated since the start of the contract by excluding fees.
470+
* - the total rewards amount (`_totalAssetsPlusPaidRewards()`) is computed such as it is always
471+
* increasing, except when fees are claimed (where fees are transferred to the beneficiary).
472+
* This makes sure that the difference between both above values does not take claimed fees
473+
* into account when computing the next unpaid fees.
474+
* @param totalAssetsPlusPaidRewards The total assets plus earned rewards plus paid rewards.
475+
* @return Amount of unpaid fee.
476+
*/
420477
function _unpaidFee(uint256 totalAssetsPlusPaidRewards) internal view returns (uint256) {
421478
uint256 totalAssetsPlusPaidRewardsDelta = totalAssetsPlusPaidRewards - _lastClaimTotalAssetsPlusPaidRewards;
422479
return (totalAssetsPlusPaidRewardsDelta * feeBasisPoints()) / 10_000;
423480
}
424481

425-
/// @dev Compute total allocation based on number of shares and total shares. Must take paid rewards into account after.
482+
/**
483+
* @notice Compute total allocation based on number of shares and total shares.
484+
* @param share The number of shares.
485+
* @param total The total number of shares.
486+
* @return The total allocation.
487+
* The allocation corresponds to the rewards (both real and virtual) a user would receive if
488+
* the current weight distribution, with their updated stake, was constant since the deployment
489+
* of the protocol.
490+
* Total reward amount is computed as the sum of:
491+
* - historical rewards: total of all rewards generated up to that point
492+
* - paid virtual rewards: a pool of "virtual" rewards that account for changes in the weight distribution
493+
* Note: the `mulDiv` rounds down: floor(totalRewards * share / total)
494+
*/
426495
function _allocation(uint256 share, uint256 total) private view returns (uint256) {
427496
return
428497
SafeCast.toUint256(SafeCast.toInt256(historicalReward()) + _totalVirtualRewardsPaid).mulDiv(share, total);

protocol-contracts/staking/contracts/OperatorStaking.sol

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,23 @@ contract OperatorStaking is ERC1363Upgradeable, ReentrancyGuardTransient, UUPSUp
4747
bytes32 private constant OPERATOR_STAKING_STORAGE_LOCATION =
4848
0x7fc851282090a0d8832502c48739eac98a0856539351f17cb5d5950c860fd200;
4949

50-
/// @dev Emitted when an operator is set or unset for a controller.
50+
/**
51+
* @dev Emitted when an operator is set or unset for a controller.
52+
* @param controller The controller address.
53+
* @param operator The operator address.
54+
* @param approved True if the operator is approved, false if revoked.
55+
*/
5156
event OperatorSet(address indexed controller, address indexed operator, bool approved);
5257

53-
/// @dev Emitted when a redeem request is made.
58+
/**
59+
* @dev Emitted when a redeem request is made.
60+
* @param controller The controller address for the redeem request.
61+
* @param owner The owner of the shares being redeemed.
62+
* @param requestId The unique identifier for the redeem request.
63+
* @param sender The address that initiated the redeem request.
64+
* @param shares The number of shares requested to redeem.
65+
* @param releaseTime The timestamp when the shares can be released.
66+
*/
5467
event RedeemRequest(
5568
address indexed controller,
5669
address indexed owner,
@@ -60,7 +73,11 @@ contract OperatorStaking is ERC1363Upgradeable, ReentrancyGuardTransient, UUPSUp
6073
uint48 releaseTime
6174
);
6275

63-
/// @dev Emitted when the rewarder contract is set.
76+
/**
77+
* @dev Emitted when the rewarder contract is set.
78+
* @param oldRewarder The previous rewarder contract address.
79+
* @param newRewarder The new rewarder contract address.
80+
*/
6481
event RewarderSet(address oldRewarder, address newRewarder);
6582

6683
/// @dev Thrown when the caller is not the ProtocolStaking's owner.

protocol-contracts/staking/contracts/ProtocolStaking.sol

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,53 @@ contract ProtocolStaking is AccessControlDefaultAdminRulesUpgradeable, ERC20Vote
5454
bytes32 private constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
5555
bytes32 private constant ELIGIBLE_ACCOUNT_ROLE = keccak256("ELIGIBLE_ACCOUNT_ROLE");
5656

57-
/// @dev Emitted when tokens are staked by an account.
57+
/**
58+
* @dev Emitted when tokens are staked by an account.
59+
* @param account The address of the account staking tokens.
60+
* @param amount The amount of tokens staked.
61+
*/
5862
event TokensStaked(address indexed account, uint256 amount);
59-
/// @dev Emitted when tokens are unstaked by an account.
63+
64+
/**
65+
* @dev Emitted when tokens are unstaked by an account.
66+
* @param account The address of the account unstaking tokens.
67+
* @param amount The amount of tokens unstaked.
68+
* @param releaseTime The timestamp when the tokens can be released.
69+
*/
6070
event TokensUnstaked(address indexed account, uint256 amount, uint48 releaseTime);
61-
/// @dev Emitted when tokens are released to a recipient after the unstaking cooldown period.
71+
72+
/**
73+
* @dev Emitted when tokens are released to a recipient after the unstaking cooldown period.
74+
* @param recipient The address receiving the released tokens.
75+
* @param amount The amount of tokens released.
76+
*/
6277
event TokensReleased(address indexed recipient, uint256 amount);
63-
/// @dev Emitted when rewards of an account are claimed.
78+
79+
/**
80+
* @dev Emitted when rewards of an account are claimed.
81+
* @param account The address of the account whose rewards are claimed.
82+
* @param recipient The address receiving the claimed rewards.
83+
* @param amount The amount of rewards claimed.
84+
*/
6485
event RewardsClaimed(address indexed account, address indexed recipient, uint256 amount);
65-
/// @dev Emitted when the reward rate is updated.
86+
87+
/**
88+
* @dev Emitted when the reward rate is updated.
89+
* @param rewardRate The new reward rate in tokens per second.
90+
*/
6691
event RewardRateSet(uint256 rewardRate);
67-
/// @dev Emitted when the unstake cooldown is updated.
92+
93+
/**
94+
* @dev Emitted when the unstake cooldown is updated.
95+
* @param unstakeCooldownPeriod The new unstake cooldown period in seconds.
96+
*/
6897
event UnstakeCooldownPeriodSet(uint256 unstakeCooldownPeriod);
69-
/// @dev Emitted when the reward recipient of an account is updated.
98+
99+
/**
100+
* @dev Emitted when the reward recipient of an account is updated.
101+
* @param account The address of the account whose reward recipient is updated.
102+
* @param recipient The new reward recipient address.
103+
*/
70104
event RewardsRecipientSet(address indexed account, address indexed recipient);
71105

72106
/// @dev The account cannot be made eligible.
@@ -81,7 +115,17 @@ contract ProtocolStaking is AccessControlDefaultAdminRulesUpgradeable, ERC20Vote
81115
_disableInitializers();
82116
}
83117

84-
/// @dev Initializes this upgradeable protocol staking contract.
118+
/**
119+
* @dev Initializes this upgradeable protocol staking contract.
120+
* @param name The name of the ERC20 token representing staked tokens.
121+
* @param symbol The symbol of the ERC20 token representing staked tokens.
122+
* @param version The version string for EIP712 domain separator.
123+
* @param stakingToken_ The address of the token used for staking and rewards.
124+
* @param governor The address granted the default admin role.
125+
* @param manager The address granted the manager role.
126+
* @param initialUnstakeCooldownPeriod The initial unstake cooldown period in seconds.
127+
* @param initialRewardRate The initial reward rate in tokens per second.
128+
*/
85129
function initialize(
86130
string memory name,
87131
string memory symbol,
@@ -230,7 +274,10 @@ contract ProtocolStaking is AccessControlDefaultAdminRulesUpgradeable, ERC20Vote
230274
return SafeCast.toUint256(SignedMath.max(0, SafeCast.toInt256(allocation) - $._paid[account]));
231275
}
232276

233-
/// @dev Returns the staking token which is used for staking and rewards.
277+
/**
278+
* @dev Returns the staking token which is used for staking and rewards.
279+
* @return The address of the staking token.
280+
*/
234281
function stakingToken() public view returns (address) {
235282
return _getProtocolStakingStorage()._stakingToken;
236283
}
@@ -244,12 +291,18 @@ contract ProtocolStaking is AccessControlDefaultAdminRulesUpgradeable, ERC20Vote
244291
return Math.sqrt(amount);
245292
}
246293

247-
/// @dev Returns the current total staked weight.
294+
/**
295+
* @dev Returns the current total staked weight.
296+
* @return The total staked weight of all eligible accounts.
297+
*/
248298
function totalStakedWeight() public view returns (uint256) {
249299
return _getProtocolStakingStorage()._totalEligibleStakedWeight;
250300
}
251301

252-
/// @dev Returns the current unstake cooldown period in seconds.
302+
/**
303+
* @dev Returns the current unstake cooldown period in seconds.
304+
* @return The unstake cooldown period in seconds.
305+
*/
253306
function unstakeCooldownPeriod() public view returns (uint256) {
254307
return _getProtocolStakingStorage()._unstakeCooldownPeriod;
255308
}

0 commit comments

Comments
 (0)