CSFeeDistributor
CSFeeDistributor.sol
is a supplementary contract that stores non-claimed and non-distributed Node Operator rewards on its balance. This contract stores the latest root of a rewards distribution Merkle tree. It accepts calls from CSAccounting.sol
with reward claim requests and stores data about already claimed rewards by the Node Operator. It receives non-distributed rewards from the CSModule.sol
each time the StakingRouter
mints the new portion of the module's rewards. This contract transfers excess rewards allocated by StakingRouter
due to variable Node Operator reward share back to Lido treasury.
Changes in v2:
- Added storage of the distribution history;
- Added support of the variable Node Operator reward share and rebate transfer to Lido treasury;
Upgradability
The contract uses OssifiableProxy for upgradability.
State Variables
RECOVERER_ROLE
bytes32 public constant RECOVERER_ROLE = keccak256("RECOVERER_ROLE");
STETH
IStETH public immutable STETH;
ACCOUNTING
address public immutable ACCOUNTING;
ORACLE
address public immutable ORACLE;
treeRoot
The latest Merkle Tree root
bytes32 public treeRoot;
treeCid
CID of the last published Merkle tree
string public treeCid;
logCid
CID of the file with log for the last frame reported
string public logCid;
distributedShares
Amount of stETH shares sent to the Accounting in favor of the NO
mapping(uint256 nodeOperatorId => uint256 distributed) public distributedShares;
totalClaimableShares
Total Amount of stETH shares available for claiming by NOs
uint256 public totalClaimableShares;
distributionDataHistoryCount
The number of _distributionDataHistory records
uint256 public distributionDataHistoryCount;
rebateRecipient
The address to transfer rebate to
address public rebateRecipient;
Functions
setRebateRecipient
Set address to send rebate to
function setRebateRecipient(address _rebateRecipient) external onlyRole(DEFAULT_ADMIN_ROLE);
Parameters
Name | Type | Description |
---|---|---|
_rebateRecipient | address | Address to send rebate to |
distributeFees
Distribute fees to the Accounting in favor of the Node Operator
function distributeFees(uint256 nodeOperatorId, uint256 cumulativeFeeShares, bytes32[] calldata proof)
external
onlyAccounting
returns (uint256 sharesToDistribute);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
cumulativeFeeShares | uint256 | Total Amount of stETH shares earned as fees |
proof | bytes32[] | Merkle proof of the leaf |
Returns
Name | Type | Description |
---|---|---|
sharesToDistribute | uint256 | Amount of stETH shares distributed |
processOracleReport
Receive the data of the Merkle tree from the Oracle contract and process it
function processOracleReport(
bytes32 _treeRoot,
string calldata _treeCid,
string calldata _logCid,
uint256 distributed,
uint256 rebate,
uint256 refSlot
) external onlyOracle;
Parameters
Name | Type | Description |
---|---|---|
_treeRoot | bytes32 | Root of the Merkle tree |
_treeCid | string | an IPFS CID of the tree |
_logCid | string | an IPFS CID of the log |
distributed | uint256 | an amount of the distributed shares |
rebate | uint256 | an amount of the rebate shares |
refSlot | uint256 | refSlot of the report |
recoverERC20
Allows sender to recover ERC20 tokens held by the contract
function recoverERC20(address token, uint256 amount) external override;
Parameters
Name | Type | Description |
---|---|---|
token | address | The address of the ERC20 token to recover |
amount | uint256 | The amount of the ERC20 token to recover Emits an ERC20Recovered event upon success Optionally, the inheriting contract can override this function to add additional restrictions |
getInitializedVersion
Get the initialized version of the contract
function getInitializedVersion() external view returns (uint64);
pendingSharesToDistribute
Get the Amount of stETH shares that are pending to be distributed
function pendingSharesToDistribute() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | pendingShares Amount shares that are pending to distribute |
getHistoricalDistributionData
Get the historical record of distribution data
function getHistoricalDistributionData(uint256 index) external view returns (DistributionData memory);
Parameters
Name | Type | Description |
---|---|---|
index | uint256 | Historical entry index |
Returns
Name | Type | Description |
---|---|---|
<none> | DistributionData | Historical distribution data |
getFeesToDistribute
Get the Amount of stETH shares that can be distributed in favor of the Node Operator
function getFeesToDistribute(uint256 nodeOperatorId, uint256 cumulativeFeeShares, bytes32[] calldata proof)
public
view
returns (uint256 sharesToDistribute);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
cumulativeFeeShares | uint256 | Total Amount of stETH shares earned as fees |
proof | bytes32[] | Merkle proof of the leaf |
Returns
Name | Type | Description |
---|---|---|
sharesToDistribute | uint256 | Amount of stETH shares that can be distributed |
hashLeaf
Get a hash of a leaf
Double hash the leaf to prevent second preimage attacks
function hashLeaf(uint256 nodeOperatorId, uint256 shares) public pure returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
shares | uint256 | Amount of stETH shares |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | Hash of the leaf |
Events
OperatorFeeDistributed
Emitted when fees are distributed
event OperatorFeeDistributed(uint256 indexed nodeOperatorId, uint256 shares);
DistributionDataUpdated
Emitted when distribution data is updated
event DistributionDataUpdated(uint256 totalClaimableShares, bytes32 treeRoot, string treeCid);
DistributionLogUpdated
Emitted when distribution log is updated
event DistributionLogUpdated(string logCid);
ModuleFeeDistributed
It logs how many shares were distributed in the latest report
event ModuleFeeDistributed(uint256 shares);
RebateTransferred
Emitted when rebate is transferred
event RebateTransferred(uint256 shares);
RebateRecipientSet
Emitted when rebate recipient is set
event RebateRecipientSet(address recipient);