Skip to main content

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

NameTypeDescription
durationuint256Duration of the pause in seconds

setChargePenaltyRecipient

Set charge recipient address

function setChargePenaltyRecipient(
address _chargePenaltyRecipient
) external onlyRole(ACCOUNTING_MANAGER_ROLE);

Parameters

NameTypeDescription
_chargePenaltyRecipientaddressCharge recipient address

setLockedBondRetentionPeriod

Set bond lock retention period

function setLockedBondRetentionPeriod(uint256 retention) external onlyRole(ACCOUNTING_MANAGER_ROLE);

Parameters

NameTypeDescription
retentionuint256Period 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

NameTypeDescription
bondCurveuint256[]Bond curve definition to add

Returns

NameTypeDescription
iduint256Id 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

NameTypeDescription
curveIduint256Bond curve ID to update
bondCurveuint256[]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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
curveIduint256ID 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

NameTypeDescription
nodeOperatorIduint256ID 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

NameTypeDescription
fromaddressAddress to stake ETH and deposit stETH from
nodeOperatorIduint256ID 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

NameTypeDescription
fromaddressAddress to deposit stETH from
nodeOperatorIduint256ID of the Node Operator
stETHAmountuint256Amount of stETH to deposit
permitPermitInputstETH 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

NameTypeDescription
fromaddressAddress to unwrap wstETH from
nodeOperatorIduint256ID of the Node Operator
wstETHAmountuint256Amount of wstETH to deposit
permitPermitInputwstETH 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
stETHAmountuint256Amount of stETH to claim
rewardAddressaddressReward address of the node operator
cumulativeFeeSharesuint256Cumulative fee stETH shares for the Node Operator
rewardsProofbytes32[]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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
wstETHAmountuint256Amount of wstETH to claim
rewardAddressaddressReward address of the node operator
cumulativeFeeSharesuint256Cumulative fee stETH shares for the Node Operator
rewardsProofbytes32[]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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
stEthAmountuint256Amount of ETH to request
rewardAddressaddressReward address of the node operator
cumulativeFeeSharesuint256Cumulative fee stETH shares for the Node Operator
rewardsProofbytes32[]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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
amountuint256Amount 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
amountuint256Amount to release in ETH (stETH)

compensateLockedBondETH

Compensate locked bond ETH for the given Node Operator

function compensateLockedBondETH(uint256 nodeOperatorId) external payable onlyCSM;

Parameters

NameTypeDescription
nodeOperatorIduint256ID 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

NameTypeDescription
nodeOperatorIduint256ID 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
amountuint256Amount 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
amountuint256Amount 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
cumulativeFeeSharesuint256Cumulative fee stETH shares for the Node Operator
rewardsProofbytes32[]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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
currentuint256Current bond amount in ETH
requireduint256Required 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
currentuint256Current bond amount in stETH shares
requireduint256Required bond amount in stETH shares

getUnbondedKeysCount

Get the number of the unbonded keys

function getUnbondedKeysCount(uint256 nodeOperatorId) public view returns (uint256);

Parameters

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Unbonded 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Unbonded 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
additionalKeysuint256Number of new keys to add

Returns

NameTypeDescription
<none>uint256Required 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

NameTypeDescription
keysCountuint256Keys count to calculate the required bond amount
curveIduint256Id of the curve to perform calculations against

Returns

NameTypeDescription
<none>uint256wstETH 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

NameTypeDescription
keysCountuint256Keys count to calculate the required bond amount
curveBondCurveBond curve definition. Use CSBondCurve.getBondCurve(id) method to get the definition for the exiting curve

Returns

NameTypeDescription
<none>uint256wstETH 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator
additionalKeysuint256Number of new keys to add

Returns

NameTypeDescription
<none>uint256Required bond in wstETH

totalBondShares

Get total bond shares (stETH) stored on the contract

function totalBondShares() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Total bond shares (stETH)

getBondShares

Get bond shares (stETH) for the given Node Operator

function getBondShares(uint256 nodeOperatorId) public view returns (uint256);

Parameters

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Bond in stETH shares

getBond

Get bond amount in ETH (stETH) for the given Node Operator

function getBond(uint256 nodeOperatorId) public view returns (uint256);

Parameters

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Bond amount in ETH (stETH)

getCurveInfo

Return 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

NameTypeDescription
curveIduint256Curve id to get bond curve for

Returns

NameTypeDescription
<none>BondCurveBond curve

getBondCurve

Get bond curve for the given Node Operator

function getBondCurve(uint256 nodeOperatorId) public view returns (BondCurve memory);

Parameters

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>BondCurveBond curve

getBondCurveId

Get bond curve ID for the given Node Operator

function getBondCurveId(uint256 nodeOperatorId) public view returns (uint256);

Parameters

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Bond 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

NameTypeDescription
keysuint256Number of keys to get required bond for
curveIduint256Id of the curve to perform calculations against

Returns

NameTypeDescription
<none>uint256Amount 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

NameTypeDescription
amountuint256Bond amount in ETH (stETH)to get keys count for
curveIduint256Id of the curve to perform calculations against

Returns

NameTypeDescription
<none>uint256Keys 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

NameTypeDescription
keysuint256Number of keys to get required bond for
curveBondCurveBond curve to perform calculations against

Returns

NameTypeDescription
<none>uint256Required 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

NameTypeDescription
amountuint256Bond amount to get keys count for
curveBondCurveBond curve to perform calculations against

Returns

NameTypeDescription
<none>uint256Keys count

getBondLockRetentionPeriod

Get default bond lock retention period

function getBondLockRetentionPeriod() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Default 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>BondLockLocked 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

NameTypeDescription
nodeOperatorIduint256ID of the Node Operator

Returns

NameTypeDescription
<none>uint256Amount 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);