CSAccounting
CSAccounting.sol is the supplementary contract responsible for the management of bond, rewards, and penalties. It stores bond tokens in the form of stETH shares, provides information about the bond required, and provides interfaces for the penalties.
Upgradability
The contract uses OssifiableProxy for upgradability.
State Variables
PAUSE_ROLE
bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE");
RESUME_ROLE
bytes32 public constant RESUME_ROLE = keccak256("RESUME_ROLE");
ACCOUNTING_MANAGER_ROLE
bytes32 public constant ACCOUNTING_MANAGER_ROLE = keccak256("ACCOUNTING_MANAGER_ROLE");
MANAGE_BOND_CURVES_ROLE
bytes32 public constant MANAGE_BOND_CURVES_ROLE = keccak256("MANAGE_BOND_CURVES_ROLE");
SET_BOND_CURVE_ROLE
bytes32 public constant SET_BOND_CURVE_ROLE = keccak256("SET_BOND_CURVE_ROLE");
RESET_BOND_CURVE_ROLE
bytes32 public constant RESET_BOND_CURVE_ROLE = keccak256("RESET_BOND_CURVE_ROLE");
RECOVERER_ROLE
bytes32 public constant RECOVERER_ROLE = keccak256("RECOVERER_ROLE");
CSM
ICSModule public immutable CSM;
feeDistributor
ICSFeeDistributor public feeDistributor;
chargePenaltyRecipient
address public chargePenaltyRecipient;
LIDO_LOCATOR
ILidoLocator public immutable LIDO_LOCATOR;
LIDO
ILido public immutable LIDO;
WITHDRAWAL_QUEUE
IWithdrawalQueue public immutable WITHDRAWAL_QUEUE;
WSTETH
IWstETH public immutable WSTETH;
MIN_CURVE_LENGTH
uint256 public constant MIN_CURVE_LENGTH = 1;
DEFAULT_BOND_CURVE_ID
uint256 public constant DEFAULT_BOND_CURVE_ID = 0;
MAX_CURVE_LENGTH
uint256 public immutable MAX_CURVE_LENGTH;
MIN_BOND_LOCK_RETENTION_PERIOD
uint256 public immutable MIN_BOND_LOCK_RETENTION_PERIOD;
MAX_BOND_LOCK_RETENTION_PERIOD
uint256 public immutable MAX_BOND_LOCK_RETENTION_PERIOD;
Functions
resume
Resume reward claims and deposits
function resume() external onlyRole(RESUME_ROLE);
pauseFor
Pause reward claims and deposits for duration
seconds
Must be called together with CSModule.pauseFor
Passing MAX_UINT_256 as duration
pauses indefinitely
function pauseFor(uint256 duration) external onlyRole(PAUSE_ROLE);
Parameters
Name | Type | Description |
---|---|---|
duration | uint256 | Duration of the pause in seconds |
setChargePenaltyRecipient
Set charge recipient address
function setChargePenaltyRecipient(
address _chargePenaltyRecipient
) external onlyRole(ACCOUNTING_MANAGER_ROLE);
Parameters
Name | Type | Description |
---|---|---|
_chargePenaltyRecipient | address | Charge recipient address |
setLockedBondRetentionPeriod
Set bond lock retention period
function setLockedBondRetentionPeriod(uint256 retention) external onlyRole(ACCOUNTING_MANAGER_ROLE);
Parameters
Name | Type | Description |
---|---|---|
retention | uint256 | Period in seconds to retain bond lock |
addBondCurve
Add a new bond curve
function addBondCurve(
uint256[] calldata bondCurve
) external onlyRole(MANAGE_BOND_CURVES_ROLE) returns (uint256 id);
Parameters
Name | Type | Description |
---|---|---|
bondCurve | uint256[] | Bond curve definition to add |
Returns
Name | Type | Description |
---|---|---|
id | uint256 | Id of the added curve |
updateBondCurve
Update existing bond curve
If the curve is updated to a curve with higher values for any point, Extensive checks should be performed to avoid inconsistency in the keys accounting
function updateBondCurve(
uint256 curveId,
uint256[] calldata bondCurve
) external onlyRole(MANAGE_BOND_CURVES_ROLE);
Parameters
Name | Type | Description |
---|---|---|
curveId | uint256 | Bond curve ID to update |
bondCurve | uint256[] | Bond curve definition |
setBondCurve
Set the bond curve for the given Node Operator
If called externally, the normalizeQueue
method from CSModule.sol should be called after
to ensure key pointers consistency
function setBondCurve(
uint256 nodeOperatorId,
uint256 curveId
) external onlyRole(SET_BOND_CURVE_ROLE);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
curveId | uint256 | ID of the bond curve to set |
resetBondCurve
Reset bond curve to the default one for the given Node Operator
If called externally, the normalizeQueue
method from CSModule.sol should be called after
to ensure key pointers consistency
function resetBondCurve(uint256 nodeOperatorId) external onlyRole(RESET_BOND_CURVE_ROLE);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
depositETH
Stake user's ETH with Lido and deposit stETH to the bond
Called by CSM exclusively
function depositETH(address from, uint256 nodeOperatorId) external payable whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
from | address | Address to stake ETH and deposit stETH from |
nodeOperatorId | uint256 | ID of the Node Operator |
depositStETH
Deposit user's stETH to the bond for the given Node Operator
Called by CSM exclusively
function depositStETH(
address from,
uint256 nodeOperatorId,
uint256 stETHAmount,
PermitInput calldata permit
) external whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
from | address | Address to deposit stETH from |
nodeOperatorId | uint256 | ID of the Node Operator |
stETHAmount | uint256 | Amount of stETH to deposit |
permit | PermitInput | stETH permit for the contract |
depositWstETH
Unwrap the user's wstETH and deposit stETH to the bond for the given Node Operator
Called by CSM exclusively
function depositWstETH(
address from,
uint256 nodeOperatorId,
uint256 wstETHAmount,
PermitInput calldata permit
) external whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
from | address | Address to unwrap wstETH from |
nodeOperatorId | uint256 | ID of the Node Operator |
wstETHAmount | uint256 | Amount of wstETH to deposit |
permit | PermitInput | wstETH permit for the contract |
claimRewardsStETH
Claim full reward (fee + bond) in stETH for the given Node Operator with desirable value.
rewardsProof
and cumulativeFeeShares
might be empty in order to claim only excess bond
Called by CSM exclusively
It's impossible to use single-leaf proof via this method, so this case should be treated carefully by off-chain tooling, e.g. to make sure a tree has at least 2 leafs.
function claimRewardsStETH(
uint256 nodeOperatorId,
uint256 stETHAmount,
address rewardAddress,
uint256 cumulativeFeeShares,
bytes32[] calldata rewardsProof
) external whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
stETHAmount | uint256 | Amount of stETH to claim |
rewardAddress | address | Reward address of the node operator |
cumulativeFeeShares | uint256 | Cumulative fee stETH shares for the Node Operator |
rewardsProof | bytes32[] | Merkle proof of the rewards |
claimRewardsWstETH
Claim full reward (fee + bond) in wstETH for the given Node Operator available for this moment.
rewardsProof
and cumulativeFeeShares
might be empty in order to claim only excess bond
Called by CSM exclusively
It's impossible to use single-leaf proof via this method, so this case should be treated carefully by off-chain tooling, e.g. to make sure a tree has at least 2 leafs.
function claimRewardsWstETH(
uint256 nodeOperatorId,
uint256 wstETHAmount,
address rewardAddress,
uint256 cumulativeFeeShares,
bytes32[] calldata rewardsProof
) external whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
wstETHAmount | uint256 | Amount of wstETH to claim |
rewardAddress | address | Reward address of the node operator |
cumulativeFeeShares | uint256 | Cumulative fee stETH shares for the Node Operator |
rewardsProof | bytes32[] | Merkle proof of the rewards |
claimRewardsUnstETH
Request full reward (fee + bond) in Withdrawal NFT (unstETH) for the given Node Operator available for this moment.
rewardsProof
and cumulativeFeeShares
might be empty in order to claim only excess bond
Reverts if amount isn't between MIN_STETH_WITHDRAWAL_AMOUNT
and MAX_STETH_WITHDRAWAL_AMOUNT
Called by CSM exclusively
It's impossible to use single-leaf proof via this method, so this case should be treated carefully by off-chain tooling, e.g. to make sure a tree has at least 2 leafs.
function claimRewardsUnstETH(
uint256 nodeOperatorId,
uint256 stEthAmount,
address rewardAddress,
uint256 cumulativeFeeShares,
bytes32[] calldata rewardsProof
) external whenResumed onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
stEthAmount | uint256 | Amount of ETH to request |
rewardAddress | address | Reward address of the node operator |
cumulativeFeeShares | uint256 | Cumulative fee stETH shares for the Node Operator |
rewardsProof | bytes32[] | Merkle proof of the rewards |
lockBondETH
Lock bond in ETH for the given Node Operator
Called by CSM exclusively
function lockBondETH(uint256 nodeOperatorId, uint256 amount) external onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
amount | uint256 | Amount to lock in ETH (stETH) |
releaseLockedBondETH
Release locked bond in ETH for the given Node Operator
Called by CSM exclusively
function releaseLockedBondETH(uint256 nodeOperatorId, uint256 amount) external onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
amount | uint256 | Amount to release in ETH (stETH) |
compensateLockedBondETH
Compensate locked bond ETH for the given Node Operator
function compensateLockedBondETH(uint256 nodeOperatorId) external payable onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
settleLockedBondETH
Settle locked bond ETH for the given Node Operator
Called by CSM exclusively
function settleLockedBondETH(uint256 nodeOperatorId) external onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
penalize
Penalize bond by burning stETH shares of the given Node Operator
Called by CSM exclusively
function penalize(uint256 nodeOperatorId, uint256 amount) external onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
amount | uint256 | Amount to penalize in ETH (stETH) |
chargeFee
Charge fee from bond by transferring stETH shares of the given Node Operator to the charge recipient
Called by CSM exclusively
function chargeFee(uint256 nodeOperatorId, uint256 amount) external onlyCSM;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
amount | uint256 | Amount to charge in ETH (stETH) |
pullFeeRewards
Pull fees from CSFeeDistributor to the Node Operator's bond
Permissionless method. Can be called before penalty application to ensure that rewards are also penalized
function pullFeeRewards(
uint256 nodeOperatorId,
uint256 cumulativeFeeShares,
bytes32[] calldata rewardsProof
) external;
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
cumulativeFeeShares | uint256 | Cumulative fee stETH shares for the Node Operator |
rewardsProof | bytes32[] | Merkle proof of the rewards |
renewBurnerAllowance
Service method to update allowance to Burner in case it has changed
function renewBurnerAllowance() external;
getBondSummary
Get current and required bond amounts in ETH (stETH) for the given Node Operator
To calculate excess bond amount subtract required
from current
value.
To calculate missed bond amount subtract current
from required
value
function getBondSummary(
uint256 nodeOperatorId
) public view returns (uint256 current, uint256 required);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
current | uint256 | Current bond amount in ETH |
required | uint256 | Required bond amount in ETH |
getBondSummaryShares
Get current and required bond amounts in stETH shares for the given Node Operator
To calculate excess bond amount subtract required
from current
value.
To calculate missed bond amount subtract current
from required
value
function getBondSummaryShares(
uint256 nodeOperatorId
) public view returns (uint256 current, uint256 required);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
current | uint256 | Current bond amount in stETH shares |
required | uint256 | Required bond amount in stETH shares |
getUnbondedKeysCount
Get the number of the unbonded keys
function getUnbondedKeysCount(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Unbonded keys count |
getUnbondedKeysCountToEject
Get the number of the unbonded keys to be ejected using a forcedTargetLimit
function getUnbondedKeysCountToEject(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Unbonded keys count |
getRequiredBondForNextKeys
Get the required bond in ETH (inc. missed and excess) for the given Node Operator to upload new deposit data
function getRequiredBondForNextKeys(
uint256 nodeOperatorId,
uint256 additionalKeys
) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
additionalKeys | uint256 | Number of new keys to add |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Required bond amount in ETH |
getBondAmountByKeysCountWstETH
Get the bond amount in wstETH required for the keysCount
keys using the default bond curve
function getBondAmountByKeysCountWstETH(
uint256 keysCount,
uint256 curveId
) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
keysCount | uint256 | Keys count to calculate the required bond amount |
curveId | uint256 | Id of the curve to perform calculations against |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | wstETH amount required for the keysCount |
getBondAmountByKeysCountWstETH
Get the bond amount in wstETH required for the keysCount
keys using the custom bond curve
function getBondAmountByKeysCountWstETH(
uint256 keysCount,
BondCurve memory curve
) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
keysCount | uint256 | Keys count to calculate the required bond amount |
curve | BondCurve | Bond curve definition. Use CSBondCurve.getBondCurve(id) method to get the definition for the exiting curve |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | wstETH amount required for the keysCount |
getRequiredBondForNextKeysWstETH
Get the required bond in wstETH (inc. missed and excess) for the given Node Operator to upload new keys
function getRequiredBondForNextKeysWstETH(
uint256 nodeOperatorId,
uint256 additionalKeys
) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
additionalKeys | uint256 | Number of new keys to add |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Required bond in wstETH |
totalBondShares
Get total bond shares (stETH) stored on the contract
function totalBondShares() public view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Total bond shares (stETH) |
getBondShares
Get bond shares (stETH) for the given Node Operator
function getBondShares(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Bond in stETH shares |
getBond
Get bond amount in ETH (stETH) for the given Node Operator
function getBond(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Bond amount in ETH (stETH) |
getCurveInfo
Returns bond curve for the given curve id
Get default bond curve info if curveId
is 0
or invalid
function getCurveInfo(uint256 curveId) public view returns (BondCurve memory);
Parameters
Name | Type | Description |
---|---|---|
curveId | uint256 | Curve id to get bond curve for |
Returns
Name | Type | Description |
---|---|---|
<none> | BondCurve | Bond curve |
getBondCurve
Get bond curve for the given Node Operator
function getBondCurve(uint256 nodeOperatorId) public view returns (BondCurve memory);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | BondCurve | Bond curve |
getBondCurveId
Get bond curve ID for the given Node Operator
function getBondCurveId(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Bond curve ID |
getBondAmountByKeysCount
Get required bond in ETH for the given number of keys for default bond curve
To calculate the amount for the new keys 2 calls are required: getBondAmountByKeysCount(newTotal) - getBondAmountByKeysCount(currentTotal)
function getBondAmountByKeysCount(uint256 keys, uint256 curveId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
keys | uint256 | Number of keys to get required bond for |
curveId | uint256 | Id of the curve to perform calculations against |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Amount for particular keys count |
getKeysCountByBondAmount
Get keys count for the given bond amount with default bond curve
function getKeysCountByBondAmount(uint256 amount, uint256 curveId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
amount | uint256 | Bond amount in ETH (stETH)to get keys count for |
curveId | uint256 | Id of the curve to perform calculations against |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Keys count |
getBondAmountByKeysCount
Get required bond in ETH for the given number of keys for particular bond curve.
To calculate the amount for the new keys 2 calls are required: getBondAmountByKeysCount(newTotal, curve) - getBondAmountByKeysCount(currentTotal, curve)
function getBondAmountByKeysCount(
uint256 keys,
BondCurve memory curve
) public pure returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
keys | uint256 | Number of keys to get required bond for |
curve | BondCurve | Bond curve to perform calculations against |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Required bond amount in ETH (stETH) for particular keys count |
getKeysCountByBondAmount
Get keys count for the given bond amount for particular bond curve.
function getKeysCountByBondAmount(
uint256 amount,
BondCurve memory curve
) public pure returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
amount | uint256 | Bond amount to get keys count for |
curve | BondCurve | Bond curve to perform calculations against |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Keys count |
getBondLockRetentionPeriod
Get default bond lock retention period
function getBondLockRetentionPeriod() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Default bond lock retention period |
getLockedBondInfo
Get information about the locked bond for the given Node Operator
function getLockedBondInfo(uint256 nodeOperatorId) public view returns (BondLock memory);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | BondLock | Locked bond info |
getActualLockedBond
Get amount of the locked bond in ETH (stETH) by the given Node Operator
function getActualLockedBond(uint256 nodeOperatorId) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
nodeOperatorId | uint256 | ID of the Node Operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Amount of the actual locked bond |
Events
BondLockCompensated
event BondLockCompensated(uint256 indexed nodeOperatorId, uint256 amount);
ChargePenaltyRecipientSet
event ChargePenaltyRecipientSet(address chargePenaltyRecipient);
BondDepositedETH
event BondDepositedETH(uint256 indexed nodeOperatorId, address from, uint256 amount);
BondDepositedStETH
event BondDepositedStETH(uint256 indexed nodeOperatorId, address from, uint256 amount);
BondDepositedWstETH
event BondDepositedWstETH(uint256 indexed nodeOperatorId, address from, uint256 amount);
BondClaimedUnstETH
event BondClaimedUnstETH(
uint256 indexed nodeOperatorId,
address to,
uint256 amount,
uint256 requestId
);
BondClaimedStETH
event BondClaimedStETH(uint256 indexed nodeOperatorId, address to, uint256 amount);
BondClaimedWstETH
event BondClaimedWstETH(uint256 indexed nodeOperatorId, address to, uint256 amount);
BondBurned
event BondBurned(uint256 indexed nodeOperatorId, uint256 toBurnAmount, uint256 burnedAmount);
BondCharged
event BondCharged(uint256 indexed nodeOperatorId, uint256 toChargeAmount, uint256 chargedAmount);
BondCurveAdded
event BondCurveAdded(uint256[] bondCurve);
BondCurveUpdated
event BondCurveUpdated(uint256 indexed curveId, uint256[] bondCurve);
BondCurveSet
event BondCurveSet(uint256 indexed nodeOperatorId, uint256 curveId);
BondLockChanged
event BondLockChanged(uint256 indexed nodeOperatorId, uint256 newAmount, uint256 retentionUntil);
BondLockRemoved
event BondLockRemoved(uint256 indexed nodeOperatorId);
BondLockRetentionPeriodChanged
event BondLockRetentionPeriodChanged(uint256 retentionPeriod);