diff --git a/src/CSAccounting.sol b/src/CSAccounting.sol index ff8ea5d8..6948403d 100644 --- a/src/CSAccounting.sol +++ b/src/CSAccounting.sol @@ -10,6 +10,7 @@ import { CSBondCore } from "./abstract/CSBondCore.sol"; import { CSBondCurve } from "./abstract/CSBondCurve.sol"; import { CSBondLock } from "./abstract/CSBondLock.sol"; +import { IStakingModule } from "./interfaces/IStakingModule.sol"; import { ICSModule } from "./interfaces/ICSModule.sol"; import { ICSAccounting } from "./interfaces/ICSAccounting.sol"; import { ICSFeeDistributor } from "./interfaces/ICSFeeDistributor.sol"; @@ -44,17 +45,6 @@ contract CSAccounting is ICSFeeDistributor public feeDistributor; address public chargePenaltyRecipient; - event BondLockCompensated(uint256 indexed nodeOperatorId, uint256 amount); - event ChargePenaltyRecipientSet(address chargePenaltyRecipient); - - error SenderIsNotCSM(); - error ZeroModuleAddress(); - error ZeroAdminAddress(); - error ZeroFeeDistributorAddress(); - error ZeroChargePenaltyRecipientAddress(); - error NodeOperatorDoesNotExist(); - error ElRewardsVaultReceiveFailed(); - modifier onlyCSM() { if (msg.sender != address(CSM)) revert SenderIsNotCSM(); _; @@ -120,21 +110,17 @@ contract CSAccounting is LIDO.approve(LIDO_LOCATOR.burner(), type(uint256).max); } - /// @notice Resume reward claims and deposits + /// @inheritdoc ICSAccounting function resume() external onlyRole(RESUME_ROLE) { _resume(); } - /// @notice Pause reward claims and deposits for `duration` seconds - /// @dev Must be called together with `CSModule.pauseFor` - /// @dev Passing MAX_UINT_256 as `duration` pauses indefinitely - /// @param duration Duration of the pause in seconds + /// @inheritdoc ICSAccounting function pauseFor(uint256 duration) external onlyRole(PAUSE_ROLE) { _pauseFor(duration); } - /// @notice Set charge recipient address - /// @param _chargePenaltyRecipient Charge recipient address + /// @inheritdoc ICSAccounting function setChargePenaltyRecipient( address _chargePenaltyRecipient ) external onlyRole(ACCOUNTING_MANAGER_ROLE) { @@ -142,36 +128,27 @@ contract CSAccounting is } /// @dev DEPRECATED. Use `setLockedBondPeriod` instead - /// @notice Set bond lock retention period - /// @param retention Period in seconds to retain bond lock function setLockedBondRetentionPeriod( uint256 retention ) external onlyRole(ACCOUNTING_MANAGER_ROLE) { CSBondLock._setBondLockPeriod(retention); } - /// @notice Set bond lock period - /// @param period Period in seconds to retain bond lock + /// @inheritdoc ICSAccounting function setLockedBondPeriod( uint256 period ) external onlyRole(ACCOUNTING_MANAGER_ROLE) { CSBondLock._setBondLockPeriod(period); } - /// @notice Add a new bond curve - /// @param bondCurve Bond curve definition to add - /// @return id Id of the added curve + /// @inheritdoc ICSAccounting function addBondCurve( uint256[] calldata bondCurve ) external onlyRole(MANAGE_BOND_CURVES_ROLE) returns (uint256 id) { id = CSBondCurve._addBondCurve(bondCurve); } - /// @notice Update existing bond curve - /// @dev 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 - /// @param curveId Bond curve ID to update - /// @param bondCurve Bond curve definition + /// @inheritdoc ICSAccounting function updateBondCurve( uint256 curveId, uint256[] calldata bondCurve @@ -179,11 +156,7 @@ contract CSAccounting is CSBondCurve._updateBondCurve(curveId, bondCurve); } - /// @notice Set the bond curve for the given Node Operator - /// @dev If called externally, the `normalizeQueue` method from CSModule.sol should be called after - /// to ensure key pointers consistency - /// @param nodeOperatorId ID of the Node Operator - /// @param curveId ID of the bond curve to set + /// @inheritdoc ICSAccounting function setBondCurve( uint256 nodeOperatorId, uint256 curveId @@ -192,10 +165,7 @@ contract CSAccounting is CSBondCurve._setBondCurve(nodeOperatorId, curveId); } - /// @notice Reset bond curve to the default one for the given Node Operator - /// @dev If called externally, the `normalizeQueue` method from CSModule.sol should be called after - /// to ensure key pointers consistency - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSAccounting function resetBondCurve( uint256 nodeOperatorId ) external onlyRole(RESET_BOND_CURVE_ROLE) { @@ -203,10 +173,7 @@ contract CSAccounting is CSBondCurve._resetBondCurve(nodeOperatorId); } - /// @notice Stake user's ETH with Lido and deposit stETH to the bond - /// @dev Called by CSM exclusively - /// @param from Address to stake ETH and deposit stETH from - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSAccounting function depositETH( address from, uint256 nodeOperatorId @@ -214,12 +181,7 @@ contract CSAccounting is CSBondCore._depositETH(from, nodeOperatorId); } - /// @notice Deposit user's stETH to the bond for the given Node Operator - /// @dev Called by CSM exclusively - /// @param from Address to deposit stETH from - /// @param nodeOperatorId ID of the Node Operator - /// @param stETHAmount Amount of stETH to deposit - /// @param permit stETH permit for the contract + /// @inheritdoc ICSAccounting function depositStETH( address from, uint256 nodeOperatorId, @@ -247,12 +209,7 @@ contract CSAccounting is CSBondCore._depositStETH(from, nodeOperatorId, stETHAmount); } - /// @notice Unwrap the user's wstETH and deposit stETH to the bond for the given Node Operator - /// @dev Called by CSM exclusively - /// @param from Address to unwrap wstETH from - /// @param nodeOperatorId ID of the Node Operator - /// @param wstETHAmount Amount of wstETH to deposit - /// @param permit wstETH permit for the contract + /// @inheritdoc ICSAccounting function depositWstETH( address from, uint256 nodeOperatorId, @@ -280,16 +237,7 @@ contract CSAccounting is CSBondCore._depositWstETH(from, nodeOperatorId, wstETHAmount); } - /// @notice 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 - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param stETHAmount Amount of stETH to claim - /// @param rewardAddress Reward address of the node operator - /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Merkle proof of the rewards - /// @dev 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. + /// @inheritdoc ICSAccounting function claimRewardsStETH( uint256 nodeOperatorId, uint256 stETHAmount, @@ -303,16 +251,7 @@ contract CSAccounting is CSBondCore._claimStETH(nodeOperatorId, stETHAmount, rewardAddress); } - /// @notice 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 - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param wstETHAmount Amount of wstETH to claim - /// @param rewardAddress Reward address of the node operator - /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Merkle proof of the rewards - /// @dev 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. + /// @inheritdoc ICSAccounting function claimRewardsWstETH( uint256 nodeOperatorId, uint256 wstETHAmount, @@ -326,17 +265,7 @@ contract CSAccounting is CSBondCore._claimWstETH(nodeOperatorId, wstETHAmount, rewardAddress); } - /// @notice 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 - /// @dev Reverts if amount isn't between `MIN_STETH_WITHDRAWAL_AMOUNT` and `MAX_STETH_WITHDRAWAL_AMOUNT` - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param stEthAmount Amount of ETH to request - /// @param rewardAddress Reward address of the node operator - /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Merkle proof of the rewards - /// @dev 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. + /// @inheritdoc ICSAccounting function claimRewardsUnstETH( uint256 nodeOperatorId, uint256 stEthAmount, @@ -350,10 +279,7 @@ contract CSAccounting is CSBondCore._claimUnstETH(nodeOperatorId, stEthAmount, rewardAddress); } - /// @notice Lock bond in ETH for the given Node Operator - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param amount Amount to lock in ETH (stETH) + /// @inheritdoc ICSAccounting function lockBondETH( uint256 nodeOperatorId, uint256 amount @@ -361,10 +287,7 @@ contract CSAccounting is CSBondLock._lock(nodeOperatorId, amount); } - /// @notice Release locked bond in ETH for the given Node Operator - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param amount Amount to release in ETH (stETH) + /// @inheritdoc ICSAccounting function releaseLockedBondETH( uint256 nodeOperatorId, uint256 amount @@ -372,9 +295,7 @@ contract CSAccounting is CSBondLock._reduceAmount(nodeOperatorId, amount); } - /// @notice Compensate locked bond ETH for the given Node Operator - //// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSAccounting function compensateLockedBondETH( uint256 nodeOperatorId ) external payable onlyCSM { @@ -386,9 +307,7 @@ contract CSAccounting is emit BondLockCompensated(nodeOperatorId, msg.value); } - /// @notice Settle locked bond ETH for the given Node Operator - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSAccounting function settleLockedBondETH(uint256 nodeOperatorId) external onlyCSM { uint256 lockedAmount = CSBondLock.getActualLockedBond(nodeOperatorId); if (lockedAmount > 0) { @@ -398,18 +317,12 @@ contract CSAccounting is } } - /// @notice Penalize bond by burning stETH shares of the given Node Operator - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param amount Amount to penalize in ETH (stETH) + /// @inheritdoc ICSAccounting function penalize(uint256 nodeOperatorId, uint256 amount) external onlyCSM { CSBondCore._burn(nodeOperatorId, amount); } - /// @notice Charge fee from bond by transferring stETH shares of the given Node Operator to the charge recipient - /// @dev Called by CSM exclusively - /// @param nodeOperatorId ID of the Node Operator - /// @param amount Amount to charge in ETH (stETH) + /// @inheritdoc ICSAccounting function chargeFee( uint256 nodeOperatorId, uint256 amount @@ -417,11 +330,7 @@ contract CSAccounting is CSBondCore._charge(nodeOperatorId, amount, chargePenaltyRecipient); } - /// @notice Pull fees from CSFeeDistributor to the Node Operator's bond - /// @dev Permissionless method. Can be called before penalty application to ensure that rewards are also penalized - /// @param nodeOperatorId ID of the Node Operator - /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Merkle proof of the rewards + /// @inheritdoc ICSAccounting function pullFeeRewards( uint256 nodeOperatorId, uint256 cumulativeFeeShares, @@ -431,9 +340,7 @@ contract CSAccounting is _pullFeeRewards(nodeOperatorId, cumulativeFeeShares, rewardsProof); } - /// @notice Recover ERC20 tokens from the contract - /// @param token Address of the ERC20 token to recover - /// @param amount Amount of the ERC20 token to recover + /// @inheritdoc AssetRecoverer function recoverERC20(address token, uint256 amount) external override { _onlyRecoverer(); if (token == address(LIDO)) { @@ -450,17 +357,12 @@ contract CSAccounting is AssetRecovererLib.recoverStETHShares(address(LIDO), shares); } - /// @notice Service method to update allowance to Burner in case it has changed + /// @inheritdoc ICSAccounting function renewBurnerAllowance() external { LIDO.approve(LIDO_LOCATOR.burner(), type(uint256).max); } - /// @notice Get current and required bond amounts in ETH (stETH) for the given Node Operator - /// @dev To calculate excess bond amount subtract `required` from `current` value. - /// To calculate missed bond amount subtract `current` from `required` value - /// @param nodeOperatorId ID of the Node Operator - /// @return current Current bond amount in ETH - /// @return required Required bond amount in ETH + /// @inheritdoc ICSAccounting function getBondSummary( uint256 nodeOperatorId ) public view returns (uint256 current, uint256 required) { @@ -476,12 +378,7 @@ contract CSAccounting is } } - /// @notice Get current and required bond amounts in stETH shares for the given Node Operator - /// @dev To calculate excess bond amount subtract `required` from `current` value. - /// To calculate missed bond amount subtract `current` from `required` value - /// @param nodeOperatorId ID of the Node Operator - /// @return current Current bond amount in stETH shares - /// @return required Required bond amount in stETH shares + /// @inheritdoc ICSAccounting function getBondSummaryShares( uint256 nodeOperatorId ) public view returns (uint256 current, uint256 required) { @@ -497,9 +394,7 @@ contract CSAccounting is } } - /// @notice Get the number of the unbonded keys - /// @param nodeOperatorId ID of the Node Operator - /// @return Unbonded keys count + /// @inheritdoc ICSAccounting function getUnbondedKeysCount( uint256 nodeOperatorId ) public view returns (uint256) { @@ -510,9 +405,7 @@ contract CSAccounting is }); } - /// @notice Get the number of the unbonded keys to be ejected using a forcedTargetLimit - /// @param nodeOperatorId ID of the Node Operator - /// @return Unbonded keys count + /// @inheritdoc ICSAccounting function getUnbondedKeysCountToEject( uint256 nodeOperatorId ) public view returns (uint256) { @@ -523,10 +416,7 @@ contract CSAccounting is }); } - /// @notice Get the required bond in ETH (inc. missed and excess) for the given Node Operator to upload new deposit data - /// @param nodeOperatorId ID of the Node Operator - /// @param additionalKeys Number of new keys to add - /// @return Required bond amount in ETH + /// @inheritdoc ICSAccounting function getRequiredBondForNextKeys( uint256 nodeOperatorId, uint256 additionalKeys @@ -545,10 +435,7 @@ contract CSAccounting is } } - /// @notice Get the bond amount in wstETH required for the `keysCount` keys using the default bond curve - /// @param keysCount Keys count to calculate the required bond amount - /// @param curveId Id of the curve to perform calculations against - /// @return wstETH amount required for the `keysCount` + /// @inheritdoc ICSAccounting function getBondAmountByKeysCountWstETH( uint256 keysCount, uint256 curveId @@ -559,11 +446,7 @@ contract CSAccounting is ); } - /// @notice Get the bond amount in wstETH required for the `keysCount` keys using the custom bond curve - /// @param keysCount Keys count to calculate the required bond amount - /// @param curve Bond curve definition. - /// Use CSBondCurve.getBondCurve(id) method to get the definition for the exiting curve - /// @return wstETH amount required for the `keysCount` + /// @inheritdoc ICSAccounting function getBondAmountByKeysCountWstETH( uint256 keysCount, BondCurve memory curve @@ -574,10 +457,7 @@ contract CSAccounting is ); } - /// @notice Get the required bond in wstETH (inc. missed and excess) for the given Node Operator to upload new keys - /// @param nodeOperatorId ID of the Node Operator - /// @param additionalKeys Number of new keys to add - /// @return Required bond in wstETH + /// @inheritdoc ICSAccounting function getRequiredBondForNextKeysWstETH( uint256 nodeOperatorId, uint256 additionalKeys @@ -655,7 +535,10 @@ contract CSAccounting is } function _onlyExistingNodeOperator(uint256 nodeOperatorId) internal view { - if (nodeOperatorId < CSM.getNodeOperatorsCount()) return; + if ( + nodeOperatorId < + IStakingModule(address(CSM)).getNodeOperatorsCount() + ) return; revert NodeOperatorDoesNotExist(); } diff --git a/src/CSEarlyAdoption.sol b/src/CSEarlyAdoption.sol index 355dc58b..360a163d 100644 --- a/src/CSEarlyAdoption.sol +++ b/src/CSEarlyAdoption.sol @@ -16,15 +16,6 @@ contract CSEarlyAdoption is ICSEarlyAdoption { mapping(address => bool) internal _consumedAddresses; - event Consumed(address indexed member); - - error InvalidProof(); - error AlreadyConsumed(); - error InvalidTreeRoot(); - error InvalidCurveId(); - error ZeroModuleAddress(); - error SenderIsNotModule(); - constructor(bytes32 treeRoot, uint256 curveId, address module) { if (treeRoot == bytes32(0)) revert InvalidTreeRoot(); if (curveId == 0) revert InvalidCurveId(); @@ -35,10 +26,7 @@ contract CSEarlyAdoption is ICSEarlyAdoption { MODULE = module; } - /// @notice Validate EA eligibility proof and mark it as consumed - /// @dev Called only by the module - /// @param member Address to be verified alongside the proof - /// @param proof Merkle proof of EA eligibility + /// @inheritdoc ICSEarlyAdoption function consume(address member, bytes32[] calldata proof) external { if (msg.sender != MODULE) revert SenderIsNotModule(); if (_consumedAddresses[member]) revert AlreadyConsumed(); @@ -47,17 +35,12 @@ contract CSEarlyAdoption is ICSEarlyAdoption { emit Consumed(member); } - /// @notice Check if the address has already consumed EA access - /// @param member Address to check - /// @return Consumed flag + /// @inheritdoc ICSEarlyAdoption function isConsumed(address member) external view returns (bool) { return _consumedAddresses[member]; } - /// @notice Check is the address is eligible to consume EA access - /// @param member Address to check - /// @param proof Merkle proof of EA eligibility - /// @return Boolean flag if the proof is valid or not + /// @inheritdoc ICSEarlyAdoption function verifyProof( address member, bytes32[] calldata proof @@ -65,10 +48,7 @@ contract CSEarlyAdoption is ICSEarlyAdoption { return MerkleProof.verifyCalldata(proof, TREE_ROOT, hashLeaf(member)); } - /// @notice Get a hash of a leaf in EA Merkle tree - /// @param member EA member address - /// @return Hash of the leaf - /// @dev Double hash the leaf to prevent second preimage attacks + /// @inheritdoc ICSEarlyAdoption function hashLeaf(address member) public pure returns (bytes32) { return keccak256(bytes.concat(keccak256(abi.encode(member)))); } diff --git a/src/CSFeeDistributor.sol b/src/CSFeeDistributor.sol index 41de20c5..c9a1b28f 100644 --- a/src/CSFeeDistributor.sol +++ b/src/CSFeeDistributor.sol @@ -40,34 +40,6 @@ contract CSFeeDistributor is /// @notice Total Amount of stETH shares available for claiming by NOs uint256 public totalClaimableShares; - /// @dev Emitted when fees are distributed - event FeeDistributed(uint256 indexed nodeOperatorId, uint256 shares); - - /// @dev Emitted when distribution data is updated - event DistributionDataUpdated( - uint256 totalClaimableShares, - bytes32 treeRoot, - string treeCid - ); - - /// @dev Emitted when distribution log is updated - event DistributionLogUpdated(string logCid); - - error ZeroAccountingAddress(); - error ZeroStEthAddress(); - error ZeroAdminAddress(); - error ZeroOracleAddress(); - error NotAccounting(); - error NotOracle(); - - error InvalidTreeRoot(); - error InvalidTreeCID(); - error InvalidLogCID(); - error InvalidShares(); - error InvalidProof(); - error FeeSharesDecrease(); - error NotEnoughShares(); - constructor(address stETH, address accounting, address oracle) { if (accounting == address(0)) revert ZeroAccountingAddress(); if (oracle == address(0)) revert ZeroOracleAddress(); @@ -87,11 +59,7 @@ contract CSFeeDistributor is _grantRole(DEFAULT_ADMIN_ROLE, admin); } - /// @notice Distribute fees to the Accounting in favor of the Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param shares Total Amount of stETH shares earned as fees - /// @param proof Merkle proof of the leaf - /// @return sharesToDistribute Amount of stETH shares distributed + /// @inheritdoc ICSFeeDistributor function distributeFees( uint256 nodeOperatorId, uint256 shares, @@ -117,7 +85,7 @@ contract CSFeeDistributor is emit FeeDistributed(nodeOperatorId, sharesToDistribute); } - /// @notice Receive the data of the Merkle tree from the Oracle contract and process it + /// @inheritdoc ICSFeeDistributor function processOracleReport( bytes32 _treeRoot, string calldata _treeCid, @@ -163,10 +131,7 @@ contract CSFeeDistributor is emit DistributionLogUpdated(_logCid); } - /// @notice Recover ERC20 tokens (except for stETH) from the contract - /// @dev Any stETH transferred to feeDistributor is treated as a donation and can not be recovered - /// @param token Address of the ERC20 token to recover - /// @param amount Amount of the ERC20 token to recover + /// @inheritdoc AssetRecoverer function recoverERC20(address token, uint256 amount) external override { _onlyRecoverer(); if (token == address(STETH)) { @@ -175,17 +140,12 @@ contract CSFeeDistributor is AssetRecovererLib.recoverERC20(token, amount); } - /// @notice Get the Amount of stETH shares that are pending to be distributed - /// @return pendingShares Amount shares that are pending to distribute + /// @inheritdoc ICSFeeDistributor function pendingSharesToDistribute() external view returns (uint256) { return STETH.sharesOf(address(this)) - totalClaimableShares; } - /// @notice Get the Amount of stETH shares that can be distributed in favor of the Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param shares Total Amount of stETH shares earned as fees - /// @param proof Merkle proof of the leaf - /// @return sharesToDistribute Amount of stETH shares that can be distributed + /// @inheritdoc ICSFeeDistributor function getFeesToDistribute( uint256 nodeOperatorId, uint256 shares, @@ -210,11 +170,7 @@ contract CSFeeDistributor is } } - /// @notice Get a hash of a leaf - /// @param nodeOperatorId ID of the Node Operator - /// @param shares Amount of stETH shares - /// @return Hash of the leaf - /// @dev Double hash the leaf to prevent second preimage attacks + /// @inheritdoc ICSFeeDistributor function hashLeaf( uint256 nodeOperatorId, uint256 shares diff --git a/src/CSFeeOracle.sol b/src/CSFeeOracle.sol index 1aee5379..8581a45c 100644 --- a/src/CSFeeOracle.sol +++ b/src/CSFeeOracle.sol @@ -8,35 +8,16 @@ import { BaseOracle } from "./lib/base-oracle/BaseOracle.sol"; import { ICSFeeDistributor } from "./interfaces/ICSFeeDistributor.sol"; import { AssetRecoverer } from "./abstract/AssetRecoverer.sol"; -import { IAssetRecovererLib } from "./lib/AssetRecovererLib.sol"; +import { ICSFeeOracle } from "./interfaces/ICSFeeOracle.sol"; contract CSFeeOracle is + ICSFeeOracle, BaseOracle, PausableUntil, - AssetRecoverer, - IAssetRecovererLib + AssetRecoverer { /// @notice No assets are stored in the contract - struct ReportData { - /// @dev Version of the oracle consensus rules. Current version expected - /// by the oracle can be obtained by calling getConsensusVersion(). - uint256 consensusVersion; - /// @dev Reference slot for which the report was calculated. If the slot - /// contains a block, the state being reported should include all state - /// changes resulting from that block. The epoch containing the slot - /// should be finalized prior to calculating the report. - uint256 refSlot; - /// @notice Merkle Tree root. - bytes32 treeRoot; - /// @notice CID of the published Merkle tree. - string treeCid; - /// @notice CID of the file with log of the last frame reported. - string logCid; - /// @notice Total amount of fees distributed in the report. - uint256 distributed; - } - /// @notice An ACL role granting the permission to manage the contract (update variables). bytes32 public constant CONTRACT_MANAGER_ROLE = keccak256("CONTRACT_MANAGER_ROLE"); @@ -62,16 +43,6 @@ contract CSFeeOracle is /// performance over the network computed by the off-chain oracle. uint256 public avgPerfLeewayBP; - /// @dev Emitted when a new fee distributor contract is set - event FeeDistributorContractSet(address feeDistributorContract); - - event PerfLeewaySet(uint256 valueBP); - - error ZeroAdminAddress(); - error ZeroFeeDistributorAddress(); - error InvalidPerfLeeway(); - error SenderNotAllowed(); - constructor( uint256 secondsPerSlot, uint256 genesisTime @@ -94,25 +65,21 @@ contract CSFeeOracle is _setPerformanceLeeway(_avgPerfLeewayBP); } - /// @notice Set a new fee distributor contract - /// @param feeDistributorContract Address of the new fee distributor contract + /// @inheritdoc ICSFeeOracle function setFeeDistributorContract( address feeDistributorContract ) external onlyRole(CONTRACT_MANAGER_ROLE) { _setFeeDistributorContract(feeDistributorContract); } - /// @notice Set a new performance threshold value in basis points - /// @param valueBP performance threshold in basis points + /// @inheritdoc ICSFeeOracle function setPerformanceLeeway( uint256 valueBP ) external onlyRole(CONTRACT_MANAGER_ROLE) { _setPerformanceLeeway(valueBP); } - /// @notice Submit the data for a committee report - /// @param data Data for a committee report - /// @param contractVersion Version of the oracle consensus rules + /// @inheritdoc ICSFeeOracle function submitReportData( ReportData calldata data, uint256 contractVersion @@ -129,19 +96,17 @@ contract CSFeeOracle is _handleConsensusReportData(data); } - /// @notice Resume accepting oracle reports + /// @inheritdoc ICSFeeOracle function resume() external onlyRole(RESUME_ROLE) { _resume(); } - /// @notice Pause accepting oracle reports for a `duration` seconds - /// @param duration Duration of the pause in seconds + /// @inheritdoc ICSFeeOracle function pauseFor(uint256 duration) external onlyRole(PAUSE_ROLE) { _pauseFor(duration); } - /// @notice Pause accepting oracle reports until a timestamp - /// @param pauseUntilInclusive Timestamp until which the oracle reports are paused + /// @inheritdoc ICSFeeOracle function pauseUntil( uint256 pauseUntilInclusive ) external onlyRole(PAUSE_ROLE) { diff --git a/src/CSModule.sol b/src/CSModule.sol index 79e1feb9..2901cca4 100644 --- a/src/CSModule.sol +++ b/src/CSModule.sol @@ -8,6 +8,7 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { AccessControlEnumerableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { IStakingModule } from "./interfaces/IStakingModule.sol"; import { ILidoLocator } from "./interfaces/ILidoLocator.sol"; import { IStETH } from "./interfaces/IStETH.sol"; import { ICSAccounting } from "./interfaces/ICSAccounting.sol"; @@ -23,6 +24,7 @@ import { AssetRecoverer } from "./abstract/AssetRecoverer.sol"; contract CSModule is ICSModule, + IStakingModule, Initializable, AccessControlEnumerableUpgradeable, PausableUntil, @@ -79,96 +81,6 @@ contract CSModule is uint64 private _depositableValidatorsCount; uint64 private _nodeOperatorsCount; - event NodeOperatorAdded( - uint256 indexed nodeOperatorId, - address indexed managerAddress, - address indexed rewardAddress - ); - event ReferrerSet(uint256 indexed nodeOperatorId, address indexed referrer); - event DepositableSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 depositableKeysCount - ); - event VettedSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 vettedKeysCount - ); - event VettedSigningKeysCountDecreased(uint256 indexed nodeOperatorId); - event DepositedSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 depositedKeysCount - ); - event ExitedSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 exitedKeysCount - ); - event StuckSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 stuckKeysCount - ); - event TotalSigningKeysCountChanged( - uint256 indexed nodeOperatorId, - uint256 totalKeysCount - ); - event TargetValidatorsCountChanged( - uint256 indexed nodeOperatorId, - uint256 targetLimitMode, - uint256 targetValidatorsCount - ); - event WithdrawalSubmitted( - uint256 indexed nodeOperatorId, - uint256 keyIndex, - uint256 amount, - bytes pubkey - ); - event InitialSlashingSubmitted( - uint256 indexed nodeOperatorId, - uint256 keyIndex, - bytes pubkey - ); - - event PublicRelease(); - event KeyRemovalChargeSet(uint256 amount); - - event KeyRemovalChargeApplied(uint256 indexed nodeOperatorId); - event ELRewardsStealingPenaltyReported( - uint256 indexed nodeOperatorId, - bytes32 proposedBlockHash, - uint256 stolenAmount - ); - event ELRewardsStealingPenaltyCancelled( - uint256 indexed nodeOperatorId, - uint256 amount - ); - event ELRewardsStealingPenaltyCompensated( - uint256 indexed nodeOperatorId, - uint256 amount - ); - event ELRewardsStealingPenaltySettled(uint256 indexed nodeOperatorId); - - error SenderIsNotEligible(); - error InvalidVetKeysPointer(); - error StuckKeysHigherThanNonExited(); - error ExitedKeysHigherThanTotalDeposited(); - error ExitedKeysDecrease(); - - error InvalidInput(); - error NotEnoughKeys(); - - error SigningKeysInvalidOffset(); - - error AlreadySubmitted(); - - error AlreadyActivated(); - error InvalidAmount(); - error NotAllowedToJoinYet(); - error MaxSigningKeysCountExceeded(); - - error NotSupported(); - error ZeroLocatorAddress(); - error ZeroAccountingAddress(); - error ZeroAdminAddress(); - constructor( bytes32 moduleType, uint256 minSlashingPenaltyQuotient, @@ -190,6 +102,7 @@ contract CSModule is _disableInitializers(); } + /// @notice initialize the module function initialize( address _accounting, address _earlyAdoption, @@ -213,51 +126,31 @@ contract CSModule is _pauseFor(PausableUntil.PAUSE_INFINITELY); } - /// @notice Resume creation of the Node Operators and keys upload + /// @inheritdoc ICSModule function resume() external onlyRole(RESUME_ROLE) { _resume(); } - /// @notice Pause creation of the Node Operators and keys upload for `duration` seconds. - /// Existing NO management and reward claims are still available. - /// To pause reward claims use pause method on CSAccounting - /// @param duration Duration of the pause in seconds + /// @inheritdoc ICSModule function pauseFor(uint256 duration) external onlyRole(PAUSE_ROLE) { _pauseFor(duration); } - /// @notice Activate public release mode - /// Enable permissionless creation of the Node Operators - /// Remove the keys limit for the Node Operators + /// @inheritdoc ICSModule function activatePublicRelease() external onlyRole(MODULE_MANAGER_ROLE) { if (publicRelease) revert AlreadyActivated(); publicRelease = true; emit PublicRelease(); } - /// @notice Set the key removal charge amount. - /// A charge is taken from the bond for each removed key - /// @param amount Amount of stETH in wei to be charged for removing a single key + /// @inheritdoc ICSModule function setKeyRemovalCharge( uint256 amount ) external onlyRole(MODULE_MANAGER_ROLE) { _setKeyRemovalCharge(amount); } - /// @notice Add a new Node Operator using ETH as a bond. - /// At least one deposit data and corresponding bond should be provided - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata - /// @param managementProperties Optional. Management properties to be used for the Node Operator. - /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. - /// If set to true `resetNodeOperatorManagerAddress` method will be disabled - /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption - /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration - + /// @inheritdoc ICSModule function addNodeOperatorETH( uint256 keysCount, bytes calldata publicKeys, @@ -288,21 +181,7 @@ contract CSModule is ); } - /// @notice Add a new Node Operator using stETH as a bond. - /// At least one deposit data and corresponding bond should be provided - /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata - /// @param managementProperties Optional. Management properties to be used for the Node Operator. - /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. - /// If set to true `resetNodeOperatorManagerAddress` method will be disabled - /// @param permit Optional. Permit to use stETH as bond - /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption - /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration + /// @inheritdoc ICSModule function addNodeOperatorStETH( uint256 keysCount, bytes calldata publicKeys, @@ -332,21 +211,7 @@ contract CSModule is ); } - /// @notice Add a new Node Operator using wstETH as a bond. - /// At least one deposit data and corresponding bond should be provided - /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata - /// @param managementProperties Optional. Management properties to be used for the Node Operator. - /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. - /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. - /// If set to true `resetNodeOperatorManagerAddress` method will be disabled - /// @param permit Optional. Permit to use wstETH as bond - /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption - /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration + /// @inheritdoc ICSModule function addNodeOperatorWstETH( uint256 keysCount, bytes calldata publicKeys, @@ -376,12 +241,7 @@ contract CSModule is ); } - /// @notice Add new keys to the existing Node Operator using ETH as a bond - /// @param nodeOperatorId ID of the Node Operator - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @inheritdoc ICSModule function addValidatorKeysETH( uint256 nodeOperatorId, uint256 keysCount, @@ -407,14 +267,7 @@ contract CSModule is ); } - /// @notice Add new keys to the existing Node Operator using stETH as a bond - /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert - /// @param nodeOperatorId ID of the Node Operator - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata - /// @param permit Optional. Permit to use stETH as bond + /// @inheritdoc ICSModule function addValidatorKeysStETH( uint256 nodeOperatorId, uint256 keysCount, @@ -439,14 +292,7 @@ contract CSModule is ); } - /// @notice Add new keys to the existing Node Operator using wstETH as a bond - /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert - /// @param nodeOperatorId ID of the Node Operator - /// @param keysCount Signing keys count - /// @param publicKeys Public keys to submit - /// @param signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata - /// @param permit Optional. Permit to use wstETH as bond + /// @inheritdoc ICSModule function addValidatorKeysWstETH( uint256 nodeOperatorId, uint256 keysCount, @@ -471,8 +317,7 @@ contract CSModule is ); } - /// @notice Stake user's ETH with Lido and make a deposit in stETH to the bond of the existing Node Operator - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function depositETH(uint256 nodeOperatorId) external payable { _onlyExistingNodeOperator(nodeOperatorId); accounting.depositETH{ value: msg.value }(msg.sender, nodeOperatorId); @@ -484,10 +329,7 @@ contract CSModule is }); } - /// @notice Deposit user's stETH to the bond of the existing Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param stETHAmount Amount of stETH to deposit - /// @param permit Optional. Permit to use stETH as bond + /// @inheritdoc ICSModule function depositStETH( uint256 nodeOperatorId, uint256 stETHAmount, @@ -508,10 +350,7 @@ contract CSModule is }); } - /// @notice Unwrap the user's wstETH and make a deposit in stETH to the bond of the existing Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param wstETHAmount Amount of wstETH to deposit - /// @param permit Optional. Permit to use wstETH as bond + /// @inheritdoc ICSModule function depositWstETH( uint256 nodeOperatorId, uint256 wstETHAmount, @@ -532,13 +371,7 @@ contract CSModule is }); } - /// @notice Claim full reward (fees + bond rewards) in stETH for the given Node Operator - /// @notice If `stETHAmount` exceeds the current claimable amount, the claimable amount will be used instead - /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim - /// @param nodeOperatorId ID of the Node Operator - /// @param stETHAmount Amount of stETH to claim - /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Optional. Merkle proof of the rewards + /// @inheritdoc ICSModule function claimRewardsStETH( uint256 nodeOperatorId, uint256 stETHAmount, @@ -562,13 +395,7 @@ contract CSModule is }); } - /// @notice Claim full reward (fees + bond rewards) in wstETH for the given Node Operator - /// @notice If `wstETHAmount` exceeds the current claimable amount, the claimable amount will be used instead - /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim - /// @param nodeOperatorId ID of the Node Operator - /// @param wstETHAmount Amount of wstETH to claim - /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Optional. Merkle proof of the rewards + /// @inheritdoc ICSModule function claimRewardsWstETH( uint256 nodeOperatorId, uint256 wstETHAmount, @@ -592,16 +419,7 @@ contract CSModule is }); } - /// @notice Request full reward (fees + bond rewards) in Withdrawal NFT (unstETH) for the given Node Operator - /// @notice Amounts less than `MIN_STETH_WITHDRAWAL_AMOUNT` (see LidoWithdrawalQueue contract) are not allowed - /// @notice Amounts above `MAX_STETH_WITHDRAWAL_AMOUNT` should be requested in several transactions - /// @notice If `ethAmount` exceeds the current claimable amount, the claimable amount will be used instead - /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim - /// @dev Reverts if amount isn't between `MIN_STETH_WITHDRAWAL_AMOUNT` and `MAX_STETH_WITHDRAWAL_AMOUNT` - /// @param nodeOperatorId ID of the Node Operator - /// @param stEthAmount Amount of ETH to request - /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator - /// @param rewardsProof Optional. Merkle proof of the rewards + /// @inheritdoc ICSModule function claimRewardsUnstETH( uint256 nodeOperatorId, uint256 stEthAmount, @@ -625,9 +443,7 @@ contract CSModule is }); } - /// @notice Propose a new manager address for the Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param proposedAddress Proposed manager address + /// @inheritdoc ICSModule function proposeNodeOperatorManagerAddressChange( uint256 nodeOperatorId, address proposedAddress @@ -639,9 +455,7 @@ contract CSModule is ); } - /// @notice Confirm a new manager address for the Node Operator. - /// Should be called from the currently proposed address - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function confirmNodeOperatorManagerAddressChange( uint256 nodeOperatorId ) external { @@ -651,9 +465,7 @@ contract CSModule is ); } - /// @notice Propose a new reward address for the Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param proposedAddress Proposed reward address + /// @inheritdoc ICSModule function proposeNodeOperatorRewardAddressChange( uint256 nodeOperatorId, address proposedAddress @@ -665,9 +477,7 @@ contract CSModule is ); } - /// @notice Confirm a new reward address for the Node Operator. - /// Should be called from the currently proposed address - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function confirmNodeOperatorRewardAddressChange( uint256 nodeOperatorId ) external { @@ -677,9 +487,7 @@ contract CSModule is ); } - /// @notice Reset the manager address to the reward address. - /// Should be called from the reward address - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function resetNodeOperatorManagerAddress(uint256 nodeOperatorId) external { NOAddresses.resetNodeOperatorManagerAddress( _nodeOperators, @@ -687,9 +495,7 @@ contract CSModule is ); } - /// @notice Change rewardAddress if extendedManagerPermissions is enabled for the Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @param newAddress Proposed reward address + /// @inheritdoc ICSModule function changeNodeOperatorRewardAddress( uint256 nodeOperatorId, address newAddress @@ -705,8 +511,7 @@ contract CSModule is ); } - /// @notice Called when rewards are minted for the module - /// @dev Called by StakingRouter + /// @inheritdoc IStakingModule /// @dev Passes through the minted stETH shares to the fee distributor function onRewardsMinted( uint256 totalShares @@ -714,12 +519,9 @@ contract CSModule is STETH.transferShares(address(accounting.feeDistributor()), totalShares); } - /// @notice Update stuck validators count for Node Operators - /// @dev Called by StakingRouter + /// @inheritdoc IStakingModule /// @dev If the stuck keys count is above zero for the Node Operator, /// the depositable validators count is set to 0 for this Node Operator - /// @param nodeOperatorIds bytes packed array of Node Operator IDs - /// @param stuckValidatorsCounts bytes packed array of stuck validators counts function updateStuckValidatorsCount( bytes calldata nodeOperatorIds, bytes calldata stuckValidatorsCounts @@ -743,10 +545,7 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Update exited validators count for Node Operators - /// @dev Called by StakingRouter - /// @param nodeOperatorIds bytes packed array of Node Operator IDs - /// @param exitedValidatorsCounts bytes packed array of exited validators counts + /// @inheritdoc IStakingModule function updateExitedValidatorsCount( bytes calldata nodeOperatorIds, bytes calldata exitedValidatorsCounts @@ -774,10 +573,8 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Update refunded validators count for the Node Operator. - /// Non supported in CSM - /// @dev Called by StakingRouter - /// @dev Always reverts + /// @inheritdoc IStakingModule + /// @dev Always reverts. Non supported in CSM /// @dev `refundedValidatorsCount` is not used in the module function updateRefundedValidatorsCount( uint256 /* nodeOperatorId */, @@ -786,14 +583,7 @@ contract CSModule is revert NotSupported(); } - /// @notice Update target validators limits for Node Operator - /// @dev Called by StakingRouter - /// @param nodeOperatorId ID of the Node Operator - /// @param targetLimitMode Target limit mode for the Node Operator (see https://hackmd.io/@lido/BJXRTxMRp) - /// 0 - disabled - /// 1 - soft mode - /// 2 - forced mode - /// @param targetLimit Target limit of validators + /// @inheritdoc IStakingModule function updateTargetValidatorsLimits( uint256 nodeOperatorId, uint256 targetLimitMode, @@ -841,10 +631,8 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Called when exited and stuck validators counts updated. - /// This method is not used in CSM, hence it is empty - /// @dev Called by StakingRouter - // @dev for some reason foundry coverage consider this function as not fully covered. Check tests to see it is covered indeed + /// @inheritdoc IStakingModule + /// @dev This method is not used in CSM, hence it is do nothing function onExitedAndStuckValidatorsCountsUpdated() external onlyRole(STAKING_ROUTER_ROLE) @@ -853,11 +641,7 @@ contract CSModule is // Nothing to do, rewards are distributed by a performance oracle. } - /// @notice Unsafe update of validators count for Node Operator by the DAO - /// @dev Called by StakingRouter - /// @param nodeOperatorId ID of the Node Operator - /// @param exitedValidatorsKeysCount Exited validators counts - /// @param stuckValidatorsKeysCount Stuck validators counts + /// @inheritdoc IStakingModule function unsafeUpdateValidatorsCount( uint256 nodeOperatorId, uint256 exitedValidatorsKeysCount, @@ -872,10 +656,7 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Called to decrease the number of vetted keys for Node Operators with given ids - /// @dev Called by StakingRouter - /// @param nodeOperatorIds Bytes packed array of the Node Operator ids - /// @param vettedSigningKeysCounts Bytes packed array of the new numbers of vetted keys for the Node Operators + /// @inheritdoc IStakingModule function decreaseVettedSigningKeysCount( bytes calldata nodeOperatorIds, bytes calldata vettedSigningKeysCounts @@ -927,10 +708,7 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Remove keys for the Node Operator and confiscate removal charge for each deleted key - /// @param nodeOperatorId ID of the Node Operator - /// @param startIndex Index of the first key - /// @param keysCount Keys count to delete + /// @inheritdoc ICSModule function removeKeys( uint256 nodeOperatorId, uint256 startIndex, @@ -990,9 +768,7 @@ contract CSModule is // // Confiscate ejection fee from the bond // } - /// @notice Perform queue normalization for the given Node Operator - /// @notice Normalization stands for adding vetted but not enqueued keys to the queue - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function normalizeQueue(uint256 nodeOperatorId) external { _updateDepositableValidatorsCount({ nodeOperatorId: nodeOperatorId, @@ -1002,11 +778,7 @@ contract CSModule is depositQueue.normalize(_nodeOperators, nodeOperatorId); } - /// @notice Report EL rewards stealing for the given Node Operator - /// @notice The final locked amount will be equal to the stolen funds plus EL stealing additional fine - /// @param nodeOperatorId ID of the Node Operator - /// @param blockHash Execution layer block hash of the proposed block with EL rewards stealing - /// @param amount Amount of stolen EL rewards in ETH + /// @inheritdoc ICSModule function reportELRewardsStealingPenalty( uint256 nodeOperatorId, bytes32 blockHash, @@ -1031,10 +803,7 @@ contract CSModule is }); } - /// @notice Cancel previously reported and not settled EL rewards stealing penalty for the given Node Operator - /// @notice The funds will be unlocked - /// @param nodeOperatorId ID of the Node Operator - /// @param amount Amount of penalty to cancel + /// @inheritdoc ICSModule function cancelELRewardsStealingPenalty( uint256 nodeOperatorId, uint256 amount @@ -1051,9 +820,7 @@ contract CSModule is }); } - /// @notice Settle locked bond for the given Node Operators - /// @dev SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE role is expected to be assigned to Easy Track - /// @param nodeOperatorIds IDs of the Node Operators + /// @inheritdoc ICSModule function settleELRewardsStealingPenalty( uint256[] calldata nodeOperatorIds ) external onlyRole(SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE) { @@ -1082,9 +849,7 @@ contract CSModule is } } - /// @notice Compensate EL rewards stealing penalty for the given Node Operator to prevent further validator exits - /// @dev Can only be called by the Node Operator manager - /// @param nodeOperatorId ID of the Node Operator + /// @inheritdoc ICSModule function compensateELRewardsStealingPenalty( uint256 nodeOperatorId ) external payable { @@ -1098,13 +863,7 @@ contract CSModule is emit ELRewardsStealingPenaltyCompensated(nodeOperatorId, msg.value); } - /// @notice Report Node Operator's key as withdrawn and settle withdrawn amount - /// @notice Called by the Verifier contract. - /// See `CSVerifier.processWithdrawalProof` to use this method permissionless - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the withdrawn key in the Node Operator's keys storage - /// @param amount Amount of withdrawn ETH in wei - /// @param isSlashed Validator is slashed or not + /// @inheritdoc ICSModule function submitWithdrawal( uint256 nodeOperatorId, uint256 keyIndex, @@ -1156,11 +915,7 @@ contract CSModule is }); } - /// @notice Report Node Operator's key as slashed and apply the initial slashing penalty - /// @notice Called by the Verifier contract. - /// See `CSVerifier.processSlashingProof` to use this method permissionless - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the slashed key in the Node Operator's keys storage + /// @inheritdoc ICSModule function submitInitialSlashing( uint256 nodeOperatorId, uint256 keyIndex @@ -1191,8 +946,7 @@ contract CSModule is }); } - /// @notice Called by the Staking Router when withdrawal credentials changed by DAO - /// @dev Called by StakingRouter + /// @inheritdoc IStakingModule /// @dev Resets the key removal charge /// @dev Changing the WC means that the current deposit data in the queue is not valid anymore and can't be deposited /// So, the key removal charge should be reset to 0 to allow Node Operators to remove the keys without any charge. @@ -1204,13 +958,9 @@ contract CSModule is _setKeyRemovalCharge(0); } + /// @inheritdoc IStakingModule /// @notice Get the next `depositsCount` of depositable keys with signatures from the queue - /// @dev Called by StakingRouter /// @dev Second param `depositCalldata` is not used - /// @param depositsCount Count of deposits to get - /// @param /* depositCalldata */ (unused) Deposit calldata - /// @return publicKeys Public keys - /// @return signatures Signatures function obtainDepositData( uint256 depositsCount, bytes calldata /* depositCalldata */ @@ -1310,11 +1060,7 @@ contract CSModule is _incrementModuleNonce(); } - /// @notice Clean the deposit queue from batches with no depositable keys - /// @dev Use **eth_call** to check how many items will be removed - /// @param maxItems How many queue items to review - /// @return removed Count of batches to be removed by visiting `maxItems` batches - /// @return lastRemovedAtDepth The value to use as `maxItems` to remove `removed` batches if the static call of the method was used + /// @inheritdoc ICSModule function cleanDepositQueue( uint256 maxItems ) external returns (uint256 removed, uint256 lastRemovedAtDepth) { @@ -1324,17 +1070,12 @@ contract CSModule is ); } - /// @notice Get the deposit queue item by an index - /// @param index Index of a queue item - /// @return Deposit queue item + /// @inheritdoc ICSModule function depositQueueItem(uint128 index) external view returns (Batch) { return depositQueue.at(index); } - /// @notice Check if the given Node Operator's key is reported as slashed - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the key to check - /// @return Validator reported as slashed flag + /// @inheritdoc ICSModule function isValidatorSlashed( uint256 nodeOperatorId, uint256 keyIndex @@ -1342,10 +1083,7 @@ contract CSModule is return _isValidatorSlashed[_keyPointer(nodeOperatorId, keyIndex)]; } - /// @notice Check if the given Node Operator's key is reported as withdrawn - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex index of the key to check - /// @return Validator reported as withdrawn flag + /// @inheritdoc ICSModule function isValidatorWithdrawn( uint256 nodeOperatorId, uint256 keyIndex @@ -1353,8 +1091,7 @@ contract CSModule is return _isValidatorWithdrawn[_keyPointer(nodeOperatorId, keyIndex)]; } - /// @notice Get the module type - /// @return Module type + /// @inheritdoc IStakingModule function getType() external view returns (bytes32) { return MODULE_TYPE; } @@ -1365,7 +1102,7 @@ contract CSModule is return EL_REWARDS_STEALING_ADDITIONAL_FINE; } - /// @notice Get staking module summary + /// @inheritdoc IStakingModule function getStakingModuleSummary() external view @@ -1380,18 +1117,14 @@ contract CSModule is depositableValidatorsCount = _depositableValidatorsCount; } - /// @notice Get Node Operator info - /// @param nodeOperatorId ID of the Node Operator - /// @return Node Operator info + /// @inheritdoc ICSModule function getNodeOperator( uint256 nodeOperatorId ) external view returns (NodeOperator memory) { return _nodeOperators[nodeOperatorId]; } - /// @notice Get Node Operator non-withdrawn keys - /// @param nodeOperatorId ID of the Node Operator - /// @return Non-withdrawn keys count + /// @inheritdoc ICSModule function getNodeOperatorNonWithdrawnKeys( uint256 nodeOperatorId ) external view returns (uint256) { @@ -1401,7 +1134,7 @@ contract CSModule is } } - /// @notice Get Node Operator summary + /// @inheritdoc IStakingModule /// @notice depositableValidatorsCount depends on: /// - totalVettedKeys /// - totalDepositedKeys @@ -1410,15 +1143,6 @@ contract CSModule is /// - targetValidatorsCount /// - totalUnbondedKeys /// - totalStuckKeys - /// @param nodeOperatorId ID of the Node Operator - /// @return targetLimitMode Target limit mode - /// @return targetValidatorsCount Target validators count - /// @return stuckValidatorsCount Stuck validators count - /// @return refundedValidatorsCount Refunded validators count - /// @return stuckPenaltyEndTimestamp Stuck penalty end timestamp (unused) - /// @return totalExitedValidators Total exited validators - /// @return totalDepositedValidators Total deposited validators - /// @return depositableValidatorsCount Depositable validators count function getNodeOperatorSummary( uint256 nodeOperatorId ) @@ -1478,11 +1202,7 @@ contract CSModule is depositableValidatorsCount = no.depositableValidatorsCount; } - /// @notice Get Node Operator signing keys - /// @param nodeOperatorId ID of the Node Operator - /// @param startIndex Index of the first key - /// @param keysCount Count of keys to get - /// @return Signing keys + /// @inheritdoc ICSModule function getSigningKeys( uint256 nodeOperatorId, uint256 startIndex, @@ -1493,13 +1213,7 @@ contract CSModule is return SigningKeys.loadKeys(nodeOperatorId, startIndex, keysCount); } - /// @notice Get Node Operator signing keys with signatures - /// @param nodeOperatorId ID of the Node Operator - /// @param startIndex Index of the first key - /// @param keysCount Count of keys to get - /// @return keys Signing keys - /// @return signatures Signatures of `(deposit_message_root, domain)` tuples - /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @inheritdoc ICSModule function getSigningKeysWithSignatures( uint256 nodeOperatorId, uint256 startIndex, @@ -1524,29 +1238,24 @@ contract CSModule is return _nonce; } - /// @notice Get total number of Node Operators + /// @inheritdoc IStakingModule function getNodeOperatorsCount() external view returns (uint256) { return _nodeOperatorsCount; } - /// @notice Get total number of active Node Operators + /// @inheritdoc IStakingModule function getActiveNodeOperatorsCount() external view returns (uint256) { return _nodeOperatorsCount; } - /// @notice Get Node Operator active status - /// @param nodeOperatorId ID of the Node Operator - /// @return active Operator is active flag + /// @inheritdoc IStakingModule function getNodeOperatorIsActive( uint256 nodeOperatorId ) external view returns (bool) { return nodeOperatorId < _nodeOperatorsCount; } - /// @notice Get IDs of Node Operators - /// @param offset Offset of the first Node Operator ID to get - /// @param limit Count of Node Operator IDs to get - /// @return nodeOperatorIds IDs of the Node Operators + /// @inheritdoc IStakingModule function getNodeOperatorIds( uint256 offset, uint256 limit diff --git a/src/CSVerifier.sol b/src/CSVerifier.sol index acf86741..925bdd1a 100644 --- a/src/CSVerifier.sol +++ b/src/CSVerifier.sol @@ -65,18 +65,6 @@ contract CSVerifier is ICSVerifier { /// @dev Staking module contract ICSModule public immutable MODULE; - error RootNotFound(); - error InvalidGIndex(); - error InvalidBlockHeader(); - error InvalidChainConfig(); - error PartialWithdrawal(); - error ValidatorNotWithdrawn(); - error InvalidWithdrawalAddress(); - error UnsupportedSlot(Slot slot); - error ZeroModuleAddress(); - error ZeroWithdrawalAddress(); - error InvalidPivotSlot(); - /// @dev The previous and current forks can be essentially the same. constructor( address withdrawalAddress, @@ -115,11 +103,7 @@ contract CSVerifier is ICSVerifier { PIVOT_SLOT = pivotSlot; } - /// @notice Verify slashing proof and report slashing to the module for valid proofs - /// @param beaconBlock Beacon block header - /// @param witness Slashing witness - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the validator key in the Node Operator's key storage + /// @inheritdoc ICSVerifier function processSlashingProof( ProvableBeaconBlockHeader calldata beaconBlock, SlashingWitness calldata witness, @@ -166,11 +150,7 @@ contract CSVerifier is ICSVerifier { MODULE.submitInitialSlashing(nodeOperatorId, keyIndex); } - /// @notice Verify withdrawal proof and report withdrawal to the module for valid proofs - /// @param beaconBlock Beacon block header - /// @param witness Withdrawal witness - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the validator key in the Node Operator's key storage + /// @inheritdoc ICSVerifier function processWithdrawalProof( ProvableBeaconBlockHeader calldata beaconBlock, WithdrawalWitness calldata witness, @@ -211,12 +191,7 @@ contract CSVerifier is ICSVerifier { ); } - /// @notice Verify withdrawal proof against historical summaries data and report withdrawal to the module for valid proofs - /// @param beaconBlock Beacon block header - /// @param oldBlock Historical block header witness - /// @param witness Withdrawal witness - /// @param nodeOperatorId ID of the Node Operator - /// @param keyIndex Index of the validator key in the Node Operator's key storage + /// @inheritdoc ICSVerifier function processHistoricalWithdrawalProof( ProvableBeaconBlockHeader calldata beaconBlock, HistoricalHeaderWitness calldata oldBlock, diff --git a/src/abstract/AssetRecoverer.sol b/src/abstract/AssetRecoverer.sol index 8be7ff8c..8a6fae5d 100644 --- a/src/abstract/AssetRecoverer.sol +++ b/src/abstract/AssetRecoverer.sol @@ -19,6 +19,7 @@ abstract contract AssetRecoverer { /// @dev Allows sender to recover ERC20 tokens held by the contract /// @param token The address of the ERC20 token to recover + /// @param amount 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 function recoverERC20(address token, uint256 amount) external virtual { diff --git a/src/abstract/CSBondCore.sol b/src/abstract/CSBondCore.sol index e0700dd7..cda15733 100644 --- a/src/abstract/CSBondCore.sol +++ b/src/abstract/CSBondCore.sol @@ -41,51 +41,6 @@ abstract contract CSBondCore is ICSBondCore { bytes32 private constant CS_BOND_CORE_STORAGE_LOCATION = 0x23f334b9eb5378c2a1573857b8f9d9ca79959360a69e73d3f16848e56ec92100; - event BondDepositedETH( - uint256 indexed nodeOperatorId, - address from, - uint256 amount - ); - event BondDepositedStETH( - uint256 indexed nodeOperatorId, - address from, - uint256 amount - ); - event BondDepositedWstETH( - uint256 indexed nodeOperatorId, - address from, - uint256 amount - ); - event BondClaimedUnstETH( - uint256 indexed nodeOperatorId, - address to, - uint256 amount, - uint256 requestId - ); - event BondClaimedStETH( - uint256 indexed nodeOperatorId, - address to, - uint256 amount - ); - event BondClaimedWstETH( - uint256 indexed nodeOperatorId, - address to, - uint256 amount - ); - event BondBurned( - uint256 indexed nodeOperatorId, - uint256 toBurnAmount, - uint256 burnedAmount - ); - event BondCharged( - uint256 indexed nodeOperatorId, - uint256 toChargeAmount, - uint256 chargedAmount - ); - - error ZeroLocatorAddress(); - error NothingToClaim(); - constructor(address lidoLocator) { if (lidoLocator == address(0)) { revert ZeroLocatorAddress(); @@ -96,24 +51,19 @@ abstract contract CSBondCore is ICSBondCore { WSTETH = IWstETH(WITHDRAWAL_QUEUE.WSTETH()); } - /// @notice Get total bond shares (stETH) stored on the contract - /// @return Total bond shares (stETH) + /// @inheritdoc ICSBondCore function totalBondShares() public view returns (uint256) { return _getCSBondCoreStorage().totalBondShares; } - /// @notice Get bond shares (stETH) for the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Bond in stETH shares + /// @inheritdoc ICSBondCore function getBondShares( uint256 nodeOperatorId ) public view returns (uint256) { return _getCSBondCoreStorage().bondShares[nodeOperatorId]; } - /// @notice Get bond amount in ETH (stETH) for the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Bond amount in ETH (stETH) + /// @inheritdoc ICSBondCore function getBond(uint256 nodeOperatorId) public view returns (uint256) { return _ethByShares(getBondShares(nodeOperatorId)); } diff --git a/src/abstract/CSBondCurve.sol b/src/abstract/CSBondCurve.sol index cdf298e8..896df394 100644 --- a/src/abstract/CSBondCurve.sol +++ b/src/abstract/CSBondCurve.sol @@ -43,26 +43,13 @@ abstract contract CSBondCurve is ICSBondCurve, Initializable { uint256 public constant DEFAULT_BOND_CURVE_ID = 0; uint256 public immutable MAX_CURVE_LENGTH; - event BondCurveAdded(uint256[] bondCurve); - event BondCurveUpdated(uint256 indexed curveId, uint256[] bondCurve); - event BondCurveSet(uint256 indexed nodeOperatorId, uint256 curveId); - - error InvalidBondCurveLength(); - error InvalidBondCurveMaxLength(); - error InvalidBondCurveValues(); - error InvalidBondCurveId(); - error InvalidInitialisationCurveId(); - constructor(uint256 maxCurveLength) { if (maxCurveLength < MIN_CURVE_LENGTH) revert InvalidBondCurveMaxLength(); MAX_CURVE_LENGTH = maxCurveLength; } - /// @dev Get default bond curve info if `curveId` is `0` or invalid - /// @notice Return bond curve for the given curve id - /// @param curveId Curve id to get bond curve for - /// @return Bond curve + /// @inheritdoc ICSBondCurve function getCurveInfo( uint256 curveId ) public view returns (BondCurve memory) { @@ -71,30 +58,21 @@ abstract contract CSBondCurve is ICSBondCurve, Initializable { return $.bondCurves[curveId]; } - /// @notice Get bond curve for the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Bond curve + /// @inheritdoc ICSBondCurve function getBondCurve( uint256 nodeOperatorId ) public view returns (BondCurve memory) { return getCurveInfo(getBondCurveId(nodeOperatorId)); } - /// @notice Get bond curve ID for the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Bond curve ID + /// @inheritdoc ICSBondCurve function getBondCurveId( uint256 nodeOperatorId ) public view returns (uint256) { return _getCSBondCurveStorage().operatorBondCurveId[nodeOperatorId]; } - /// @notice Get required bond in ETH for the given number of keys for default bond curve - /// @dev To calculate the amount for the new keys 2 calls are required: - /// getBondAmountByKeysCount(newTotal) - getBondAmountByKeysCount(currentTotal) - /// @param keys Number of keys to get required bond for - /// @param curveId Id of the curve to perform calculations against - /// @return Amount for particular keys count + /// @inheritdoc ICSBondCurve function getBondAmountByKeysCount( uint256 keys, uint256 curveId @@ -102,10 +80,7 @@ abstract contract CSBondCurve is ICSBondCurve, Initializable { return getBondAmountByKeysCount(keys, getCurveInfo(curveId)); } - /// @notice Get keys count for the given bond amount with default bond curve - /// @param amount Bond amount in ETH (stETH)to get keys count for - /// @param curveId Id of the curve to perform calculations against - /// @return Keys count + /// @inheritdoc ICSBondCurve function getKeysCountByBondAmount( uint256 amount, uint256 curveId @@ -113,12 +88,7 @@ abstract contract CSBondCurve is ICSBondCurve, Initializable { return getKeysCountByBondAmount(amount, getCurveInfo(curveId)); } - /// @notice Get required bond in ETH for the given number of keys for particular bond curve. - /// @dev To calculate the amount for the new keys 2 calls are required: - /// getBondAmountByKeysCount(newTotal, curve) - getBondAmountByKeysCount(currentTotal, curve) - /// @param keys Number of keys to get required bond for - /// @param curve Bond curve to perform calculations against - /// @return Required bond amount in ETH (stETH) for particular keys count + /// @inheritdoc ICSBondCurve function getBondAmountByKeysCount( uint256 keys, BondCurve memory curve @@ -133,10 +103,7 @@ abstract contract CSBondCurve is ICSBondCurve, Initializable { : curve.points.unsafeMemoryAccess(keys - 1); } - /// @notice Get keys count for the given bond amount for particular bond curve. - /// @param amount Bond amount to get keys count for - /// @param curve Bond curve to perform calculations against - /// @return Keys count + /// @inheritdoc ICSBondCurve function getKeysCountByBondAmount( uint256 amount, BondCurve memory curve diff --git a/src/abstract/CSBondLock.sol b/src/abstract/CSBondLock.sol index 3ab751f3..c8b94227 100644 --- a/src/abstract/CSBondLock.sol +++ b/src/abstract/CSBondLock.sol @@ -45,18 +45,6 @@ abstract contract CSBondLock is ICSBondLock, Initializable { uint256 public immutable MIN_BOND_LOCK_PERIOD; uint256 public immutable MAX_BOND_LOCK_PERIOD; - event BondLockChanged( - uint256 indexed nodeOperatorId, - uint256 newAmount, - uint256 lockUntil - ); - event BondLockRemoved(uint256 indexed nodeOperatorId); - - event BondLockPeriodChanged(uint256 lockPeriod); - - error InvalidBondLockPeriod(); - error InvalidBondLockAmount(); - constructor(uint256 minBondLockPeriod, uint256 maxBondLockPeriod) { if (minBondLockPeriod > maxBondLockPeriod) { revert InvalidBondLockPeriod(); @@ -82,30 +70,23 @@ abstract contract CSBondLock is ICSBondLock, Initializable { } /// @dev DEPRECATED. Use `getBondLockPeriod` instead - /// @notice Get default bond lock retention period - /// @return Default bond lock retention period function getBondLockRetentionPeriod() external view returns (uint256) { return _getCSBondLockStorage().bondLockPeriod; } - /// @notice Get default bond lock period - /// @return Default bond lock period + /// @inheritdoc ICSBondLock function getBondLockPeriod() external view returns (uint256) { return _getCSBondLockStorage().bondLockPeriod; } - /// @notice Get information about the locked bond for the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Locked bond info + /// @inheritdoc ICSBondLock function getLockedBondInfo( uint256 nodeOperatorId ) public view returns (BondLock memory) { return _getCSBondLockStorage().bondLock[nodeOperatorId]; } - /// @notice Get amount of the locked bond in ETH (stETH) by the given Node Operator - /// @param nodeOperatorId ID of the Node Operator - /// @return Amount of the actual locked bond + /// @inheritdoc ICSBondLock function getActualLockedBond( uint256 nodeOperatorId ) public view returns (uint256) { diff --git a/src/interfaces/ICSAccounting.sol b/src/interfaces/ICSAccounting.sol index f78a36e8..f9e11392 100644 --- a/src/interfaces/ICSAccounting.sol +++ b/src/interfaces/ICSAccounting.sol @@ -8,6 +8,7 @@ import { ICSBondCurve } from "./ICSBondCurve.sol"; import { ICSBondLock } from "./ICSBondLock.sol"; import { ICSFeeDistributor } from "./ICSFeeDistributor.sol"; import { IAssetRecovererLib } from "../lib/AssetRecovererLib.sol"; +import { ICSModule } from "./ICSModule.sol"; interface ICSAccounting is ICSBondCore, @@ -23,38 +24,150 @@ interface ICSAccounting is bytes32 s; } + event BondLockCompensated(uint256 indexed nodeOperatorId, uint256 amount); + event ChargePenaltyRecipientSet(address chargePenaltyRecipient); + + error SenderIsNotCSM(); + error ZeroModuleAddress(); + error ZeroAdminAddress(); + error ZeroFeeDistributorAddress(); + error ZeroChargePenaltyRecipientAddress(); + error NodeOperatorDoesNotExist(); + error ElRewardsVaultReceiveFailed(); + + function PAUSE_ROLE() external view returns (bytes32); + + function RESUME_ROLE() external view returns (bytes32); + + function ACCOUNTING_MANAGER_ROLE() external view returns (bytes32); + + function MANAGE_BOND_CURVES_ROLE() external view returns (bytes32); + + function SET_BOND_CURVE_ROLE() external view returns (bytes32); + + function RESET_BOND_CURVE_ROLE() external view returns (bytes32); + + function RECOVERER_ROLE() external view returns (bytes32); + + function CSM() external view returns (ICSModule); + function feeDistributor() external view returns (ICSFeeDistributor); function chargePenaltyRecipient() external view returns (address); + /// @notice Resume reward claims and deposits + function resume() external; + + /// @notice Pause reward claims and deposits for `duration` seconds + /// @dev Must be called together with `CSModule.pauseFor` + /// @dev Passing MAX_UINT_256 as `duration` pauses indefinitely + /// @param duration Duration of the pause in seconds + function pauseFor(uint256 duration) external; + + /// @notice Set charge recipient address + /// @param _chargePenaltyRecipient Charge recipient address + function setChargePenaltyRecipient( + address _chargePenaltyRecipient + ) external; + + /// @notice Set bond lock period + /// @param period Period in seconds to retain bond lock + function setLockedBondPeriod(uint256 period) external; + + /// @notice Add a new bond curve + /// @param bondCurve Bond curve definition to add + /// @return id Id of the added curve + function addBondCurve( + uint256[] calldata bondCurve + ) external returns (uint256 id); + + /// @notice Update existing bond curve + /// @dev 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 + /// @param curveId Bond curve ID to update + /// @param bondCurve Bond curve definition + function updateBondCurve( + uint256 curveId, + uint256[] calldata bondCurve + ) external; + + /// @notice Get the required bond in ETH (inc. missed and excess) for the given Node Operator to upload new deposit data + /// @param nodeOperatorId ID of the Node Operator + /// @param additionalKeys Number of new keys to add + /// @return Required bond amount in ETH function getRequiredBondForNextKeys( uint256 nodeOperatorId, uint256 additionalKeys ) external view returns (uint256); + /// @notice Get the bond amount in wstETH required for the `keysCount` keys using the default bond curve + /// @param keysCount Keys count to calculate the required bond amount + /// @param curveId Id of the curve to perform calculations against + /// @return wstETH amount required for the `keysCount` function getBondAmountByKeysCountWstETH( uint256 keysCount, uint256 curveId ) external view returns (uint256); + /// @notice Get the bond amount in wstETH required for the `keysCount` keys using the custom bond curve + /// @param keysCount Keys count to calculate the required bond amount + /// @param curve Bond curve definition. + /// Use CSBondCurve.getBondCurve(id) method to get the definition for the exiting curve + /// @return wstETH amount required for the `keysCount` function getBondAmountByKeysCountWstETH( uint256 keysCount, BondCurve memory curve ) external view returns (uint256); + /// @notice Get the required bond in wstETH (inc. missed and excess) for the given Node Operator to upload new keys + /// @param nodeOperatorId ID of the Node Operator + /// @param additionalKeys Number of new keys to add + /// @return Required bond in wstETH function getRequiredBondForNextKeysWstETH( uint256 nodeOperatorId, uint256 additionalKeys ) external view returns (uint256); + /// @notice Get the number of the unbonded keys + /// @param nodeOperatorId ID of the Node Operator + /// @return Unbonded keys count function getUnbondedKeysCount( uint256 nodeOperatorId ) external view returns (uint256); + /// @notice Get the number of the unbonded keys to be ejected using a forcedTargetLimit + /// @param nodeOperatorId ID of the Node Operator + /// @return Unbonded keys count function getUnbondedKeysCountToEject( uint256 nodeOperatorId ) external view returns (uint256); + /// @notice Get current and required bond amounts in ETH (stETH) for the given Node Operator + /// @dev To calculate excess bond amount subtract `required` from `current` value. + /// To calculate missed bond amount subtract `current` from `required` value + /// @param nodeOperatorId ID of the Node Operator + /// @return current Current bond amount in ETH + /// @return required Required bond amount in ETH + function getBondSummary( + uint256 nodeOperatorId + ) external view returns (uint256 current, uint256 required); + + /// @notice Get current and required bond amounts in stETH shares for the given Node Operator + /// @dev To calculate excess bond amount subtract `required` from `current` value. + /// To calculate missed bond amount subtract `current` from `required` value + /// @param nodeOperatorId ID of the Node Operator + /// @return current Current bond amount in stETH shares + /// @return required Required bond amount in stETH shares + function getBondSummaryShares( + uint256 nodeOperatorId + ) external view returns (uint256 current, uint256 required); + + /// @notice Unwrap the user's wstETH and deposit stETH to the bond for the given Node Operator + /// @dev Called by CSM exclusively + /// @param from Address to unwrap wstETH from + /// @param nodeOperatorId ID of the Node Operator + /// @param wstETHAmount Amount of wstETH to deposit + /// @param permit wstETH permit for the contract function depositWstETH( address from, uint256 nodeOperatorId, @@ -62,6 +175,12 @@ interface ICSAccounting is PermitInput calldata permit ) external; + /// @notice Deposit user's stETH to the bond for the given Node Operator + /// @dev Called by CSM exclusively + /// @param from Address to deposit stETH from + /// @param nodeOperatorId ID of the Node Operator + /// @param stETHAmount Amount of stETH to deposit + /// @param permit stETH permit for the contract function depositStETH( address from, uint256 nodeOperatorId, @@ -69,8 +188,22 @@ interface ICSAccounting is PermitInput calldata permit ) external; + /// @notice Stake user's ETH with Lido and deposit stETH to the bond + /// @dev Called by CSM exclusively + /// @param from Address to stake ETH and deposit stETH from + /// @param nodeOperatorId ID of the Node Operator function depositETH(address from, uint256 nodeOperatorId) external payable; + /// @notice 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 + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param stETHAmount Amount of stETH to claim + /// @param rewardAddress Reward address of the node operator + /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Merkle proof of the rewards + /// @dev 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, @@ -79,6 +212,16 @@ interface ICSAccounting is bytes32[] calldata rewardsProof ) external; + /// @notice 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 + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param wstETHAmount Amount of wstETH to claim + /// @param rewardAddress Reward address of the node operator + /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Merkle proof of the rewards + /// @dev 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, @@ -87,6 +230,17 @@ interface ICSAccounting is bytes32[] calldata rewardsProof ) external; + /// @notice 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 + /// @dev Reverts if amount isn't between `MIN_STETH_WITHDRAWAL_AMOUNT` and `MAX_STETH_WITHDRAWAL_AMOUNT` + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param stEthAmount Amount of ETH to request + /// @param rewardAddress Reward address of the node operator + /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Merkle proof of the rewards + /// @dev 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, @@ -95,22 +249,67 @@ interface ICSAccounting is bytes32[] calldata rewardsProof ) external; + /// @notice Lock bond in ETH for the given Node Operator + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param amount Amount to lock in ETH (stETH) function lockBondETH(uint256 nodeOperatorId, uint256 amount) external; + /// @notice Release locked bond in ETH for the given Node Operator + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param amount Amount to release in ETH (stETH) function releaseLockedBondETH( uint256 nodeOperatorId, uint256 amount ) external; + /// @notice Settle locked bond ETH for the given Node Operator + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator function settleLockedBondETH(uint256 nodeOperatorId) external; + /// @notice Compensate locked bond ETH for the given Node Operator + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator function compensateLockedBondETH(uint256 nodeOperatorId) external payable; + /// @notice Set the bond curve for the given Node Operator + /// @dev If called externally, the `normalizeQueue` method from CSModule.sol should be called after + /// to ensure key pointers consistency + /// @param nodeOperatorId ID of the Node Operator + /// @param curveId ID of the bond curve to set function setBondCurve(uint256 nodeOperatorId, uint256 curveId) external; + /// @notice Reset bond curve to the default one for the given Node Operator + /// @dev If called externally, the `normalizeQueue` method from CSModule.sol should be called after + /// to ensure key pointers consistency + /// @param nodeOperatorId ID of the Node Operator function resetBondCurve(uint256 nodeOperatorId) external; + /// @notice Penalize bond by burning stETH shares of the given Node Operator + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param amount Amount to penalize in ETH (stETH) function penalize(uint256 nodeOperatorId, uint256 amount) external; + /// @notice Charge fee from bond by transferring stETH shares of the given Node Operator to the charge recipient + /// @dev Called by CSM exclusively + /// @param nodeOperatorId ID of the Node Operator + /// @param amount Amount to charge in ETH (stETH) function chargeFee(uint256 nodeOperatorId, uint256 amount) external; + + /// @notice Pull fees from CSFeeDistributor to the Node Operator's bond + /// @dev Permissionless method. Can be called before penalty application to ensure that rewards are also penalized + /// @param nodeOperatorId ID of the Node Operator + /// @param cumulativeFeeShares Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Merkle proof of the rewards + function pullFeeRewards( + uint256 nodeOperatorId, + uint256 cumulativeFeeShares, + bytes32[] calldata rewardsProof + ) external; + + /// @notice Service method to update allowance to Burner in case it has changed + function renewBurnerAllowance() external; } diff --git a/src/interfaces/ICSBondCore.sol b/src/interfaces/ICSBondCore.sol index 5b7cd9bf..93b96137 100644 --- a/src/interfaces/ICSBondCore.sol +++ b/src/interfaces/ICSBondCore.sol @@ -3,12 +3,78 @@ pragma solidity 0.8.24; +import { ILidoLocator } from "./ILidoLocator.sol"; +import { ILido } from "./ILido.sol"; +import { IWithdrawalQueue } from "./IWithdrawalQueue.sol"; +import { IWstETH } from "./IWstETH.sol"; + interface ICSBondCore { + event BondDepositedETH( + uint256 indexed nodeOperatorId, + address from, + uint256 amount + ); + event BondDepositedStETH( + uint256 indexed nodeOperatorId, + address from, + uint256 amount + ); + event BondDepositedWstETH( + uint256 indexed nodeOperatorId, + address from, + uint256 amount + ); + event BondClaimedUnstETH( + uint256 indexed nodeOperatorId, + address to, + uint256 amount, + uint256 requestId + ); + event BondClaimedStETH( + uint256 indexed nodeOperatorId, + address to, + uint256 amount + ); + event BondClaimedWstETH( + uint256 indexed nodeOperatorId, + address to, + uint256 amount + ); + event BondBurned( + uint256 indexed nodeOperatorId, + uint256 toBurnAmount, + uint256 burnedAmount + ); + event BondCharged( + uint256 indexed nodeOperatorId, + uint256 toChargeAmount, + uint256 chargedAmount + ); + + error ZeroLocatorAddress(); + error NothingToClaim(); + + function LIDO_LOCATOR() external view returns (ILidoLocator); + + function LIDO() external view returns (ILido); + + function WITHDRAWAL_QUEUE() external view returns (IWithdrawalQueue); + + function WSTETH() external view returns (IWstETH); + + /// @notice Get total bond shares (stETH) stored on the contract + /// @return Total bond shares (stETH) function totalBondShares() external view returns (uint256); + /// @notice Get bond shares (stETH) for the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Bond in stETH shares function getBondShares( uint256 nodeOperatorId ) external view returns (uint256); + /// @notice Get bond amount in ETH (stETH) for the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Bond amount in ETH (stETH) function getBond(uint256 nodeOperatorId) external view returns (uint256); } diff --git a/src/interfaces/ICSBondCurve.sol b/src/interfaces/ICSBondCurve.sol index a4bfe59d..d51b9255 100644 --- a/src/interfaces/ICSBondCurve.sol +++ b/src/interfaces/ICSBondCurve.sol @@ -43,36 +43,79 @@ interface ICSBondCurve { uint256 trend; } - // solhint-disable-next-line + event BondCurveAdded(uint256[] bondCurve); + event BondCurveUpdated(uint256 indexed curveId, uint256[] bondCurve); + event BondCurveSet(uint256 indexed nodeOperatorId, uint256 curveId); + + error InvalidBondCurveLength(); + error InvalidBondCurveMaxLength(); + error InvalidBondCurveValues(); + error InvalidBondCurveId(); + error InvalidInitialisationCurveId(); + + function MIN_CURVE_LENGTH() external view returns (uint256); + + function MAX_CURVE_LENGTH() external view returns (uint256); + function DEFAULT_BOND_CURVE_ID() external view returns (uint256); + /// @dev Get default bond curve info if `curveId` is `0` or invalid + /// @notice Return bond curve for the given curve id + /// @param curveId Curve id to get bond curve for + /// @return Bond curve function getCurveInfo( uint256 curveId ) external view returns (BondCurve memory); + /// @notice Get bond curve for the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Bond curve function getBondCurve( uint256 nodeOperatorId ) external view returns (BondCurve memory); + /// @notice Get bond curve ID for the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Bond curve ID function getBondCurveId( uint256 nodeOperatorId ) external view returns (uint256); + /// @notice Get required bond in ETH for the given number of keys for default bond curve + /// @dev To calculate the amount for the new keys 2 calls are required: + /// getBondAmountByKeysCount(newTotal) - getBondAmountByKeysCount(currentTotal) + /// @param keys Number of keys to get required bond for + /// @param curveId Id of the curve to perform calculations against + /// @return Amount for particular keys count function getBondAmountByKeysCount( uint256 keys, uint256 curveId ) external view returns (uint256); + /// @notice Get required bond in ETH for the given number of keys for particular bond curve. + /// @dev To calculate the amount for the new keys 2 calls are required: + /// getBondAmountByKeysCount(newTotal, curve) - getBondAmountByKeysCount(currentTotal, curve) + /// @param keys Number of keys to get required bond for + /// @param curve Bond curve to perform calculations against + /// @return Required bond amount in ETH (stETH) for particular keys count function getBondAmountByKeysCount( uint256 keys, BondCurve memory curve ) external view returns (uint256); + /// @notice Get keys count for the given bond amount with default bond curve + /// @param amount Bond amount in ETH (stETH)to get keys count for + /// @param curveId Id of the curve to perform calculations against + /// @return Keys count function getKeysCountByBondAmount( uint256 amount, uint256 curveId ) external view returns (uint256); + /// @notice Get keys count for the given bond amount for particular bond curve. + /// @param amount Bond amount to get keys count for + /// @param curve Bond curve to perform calculations against + /// @return Keys count function getKeysCountByBondAmount( uint256 amount, BondCurve memory curve diff --git a/src/interfaces/ICSBondLock.sol b/src/interfaces/ICSBondLock.sol index 2b99e21f..9624a3b2 100644 --- a/src/interfaces/ICSBondLock.sol +++ b/src/interfaces/ICSBondLock.sol @@ -13,18 +13,36 @@ interface ICSBondLock { uint128 lockUntil; } - /// @dev DEPRECATED: Use `getBondLockPeriod` instead - function getBondLockRetentionPeriod() - external - view - returns (uint256 retention); + event BondLockChanged( + uint256 indexed nodeOperatorId, + uint256 newAmount, + uint256 lockUntil + ); + event BondLockRemoved(uint256 indexed nodeOperatorId); + event BondLockPeriodChanged(uint256 lockPeriod); + + error InvalidBondLockPeriod(); + error InvalidBondLockAmount(); + + function MIN_BOND_LOCK_PERIOD() external view returns (uint256); + + function MAX_BOND_LOCK_PERIOD() external view returns (uint256); + + /// @notice Get default bond lock period + /// @return period Default bond lock period function getBondLockPeriod() external view returns (uint256 period); + /// @notice Get information about the locked bond for the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Locked bond info function getLockedBondInfo( uint256 nodeOperatorId ) external view returns (BondLock memory); + /// @notice Get amount of the locked bond in ETH (stETH) by the given Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @return Amount of the actual locked bond function getActualLockedBond( uint256 nodeOperatorId ) external view returns (uint256); diff --git a/src/interfaces/ICSEarlyAdoption.sol b/src/interfaces/ICSEarlyAdoption.sol index b95c0d61..5e6509da 100644 --- a/src/interfaces/ICSEarlyAdoption.sol +++ b/src/interfaces/ICSEarlyAdoption.sol @@ -4,16 +4,44 @@ pragma solidity 0.8.24; interface ICSEarlyAdoption { + event Consumed(address indexed member); + + error InvalidProof(); + error AlreadyConsumed(); + error InvalidTreeRoot(); + error InvalidCurveId(); + error ZeroModuleAddress(); + error SenderIsNotModule(); + function CURVE_ID() external view returns (uint256); function TREE_ROOT() external view returns (bytes32); + function MODULE() external view returns (address); + + /// @notice Check is the address is eligible to consume EA access + /// @param member Address to check + /// @param proof Merkle proof of EA eligibility + /// @return Boolean flag if the proof is valid or not function verifyProof( - address addr, + address member, bytes32[] calldata proof ) external view returns (bool); - function consume(address sender, bytes32[] calldata proof) external; + /// @notice Validate EA eligibility proof and mark it as consumed + /// @dev Called only by the module + /// @param member Address to be verified alongside the proof + /// @param proof Merkle proof of EA eligibility + function consume(address member, bytes32[] calldata proof) external; + + /// @notice Check if the address has already consumed EA access + /// @param member Address to check + /// @return Consumed flag + function isConsumed(address member) external view returns (bool); - function isConsumed(address sender) external view returns (bool); + /// @notice Get a hash of a leaf in EA Merkle tree + /// @param member EA member address + /// @return Hash of the leaf + /// @dev Double hash the leaf to prevent second preimage attacks + function hashLeaf(address member) external pure returns (bytes32); } diff --git a/src/interfaces/ICSFeeDistributor.sol b/src/interfaces/ICSFeeDistributor.sol index 329bd789..438db952 100644 --- a/src/interfaces/ICSFeeDistributor.sol +++ b/src/interfaces/ICSFeeDistributor.sol @@ -2,22 +2,83 @@ // SPDX-License-Identifier: GPL-3.0 import { IAssetRecovererLib } from "../lib/AssetRecovererLib.sol"; +import { IStETH } from "./IStETH.sol"; pragma solidity 0.8.24; interface ICSFeeDistributor is IAssetRecovererLib { + /// @dev Emitted when fees are distributed + event FeeDistributed(uint256 indexed nodeOperatorId, uint256 shares); + + /// @dev Emitted when distribution data is updated + event DistributionDataUpdated( + uint256 totalClaimableShares, + bytes32 treeRoot, + string treeCid + ); + + /// @dev Emitted when distribution log is updated + event DistributionLogUpdated(string logCid); + + error ZeroAccountingAddress(); + error ZeroStEthAddress(); + error ZeroAdminAddress(); + error ZeroOracleAddress(); + error NotAccounting(); + error NotOracle(); + + error InvalidTreeRoot(); + error InvalidTreeCID(); + error InvalidLogCID(); + error InvalidShares(); + error InvalidProof(); + error FeeSharesDecrease(); + error NotEnoughShares(); + + function RECOVERER_ROLE() external view returns (bytes32); + + function STETH() external view returns (IStETH); + + function ACCOUNTING() external view returns (address); + + function ORACLE() external view returns (address); + + function treeRoot() external view returns (bytes32); + + function treeCid() external view returns (string calldata); + + function logCid() external view returns (string calldata); + + function distributedShares(uint256) external view returns (uint256); + + function totalClaimableShares() external view returns (uint256); + + /// @notice Get the Amount of stETH shares that can be distributed in favor of the Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param shares Total Amount of stETH shares earned as fees + /// @param proof Merkle proof of the leaf + /// @return sharesToDistribute Amount of stETH shares that can be distributed function getFeesToDistribute( uint256 nodeOperatorId, uint256 shares, bytes32[] calldata proof ) external view returns (uint256); + /// @notice Distribute fees to the Accounting in favor of the Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param shares Total Amount of stETH shares earned as fees + /// @param proof Merkle proof of the leaf + /// @return sharesToDistribute Amount of stETH shares distributed function distributeFees( uint256 nodeOperatorId, uint256 shares, bytes32[] calldata proof ) external returns (uint256); + /// @notice Receive the data of the Merkle tree from the Oracle contract and process it + /// @param _treeRoot Root of the Merkle tree + /// @param _treeCid an IPFS CID of the tree + /// @param _logCid an IPFS CID of the log function processOracleReport( bytes32 _treeRoot, string calldata _treeCid, @@ -25,6 +86,17 @@ interface ICSFeeDistributor is IAssetRecovererLib { uint256 _distributedShares ) external; - /// @notice Returns the amount of shares that are pending to be distributed + /// @notice Get the Amount of stETH shares that are pending to be distributed + /// @return pendingShares Amount shares that are pending to distribute function pendingSharesToDistribute() external view returns (uint256); + + /// @notice Get a hash of a leaf + /// @param nodeOperatorId ID of the Node Operator + /// @param shares Amount of stETH shares + /// @return Hash of the leaf + /// @dev Double hash the leaf to prevent second preimage attacks + function hashLeaf( + uint256 nodeOperatorId, + uint256 shares + ) external pure returns (bytes32); } diff --git a/src/interfaces/ICSFeeOracle.sol b/src/interfaces/ICSFeeOracle.sol new file mode 100644 index 00000000..e41c17be --- /dev/null +++ b/src/interfaces/ICSFeeOracle.sol @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2024 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.24; + +import { IAssetRecovererLib } from "../lib/AssetRecovererLib.sol"; +import { ICSFeeDistributor } from "./ICSFeeDistributor.sol"; + +interface ICSFeeOracle is IAssetRecovererLib { + struct ReportData { + /// @dev Version of the oracle consensus rules. Current version expected + /// by the oracle can be obtained by calling getConsensusVersion(). + uint256 consensusVersion; + /// @dev Reference slot for which the report was calculated. If the slot + /// contains a block, the state being reported should include all state + /// changes resulting from that block. The epoch containing the slot + /// should be finalized prior to calculating the report. + uint256 refSlot; + /// @notice Merkle Tree root. + bytes32 treeRoot; + /// @notice CID of the published Merkle tree. + string treeCid; + /// @notice CID of the file with log of the last frame reported. + string logCid; + /// @notice Total amount of fees distributed in the report. + uint256 distributed; + } + + /// @dev Emitted when a new fee distributor contract is set + event FeeDistributorContractSet(address feeDistributorContract); + + event PerfLeewaySet(uint256 valueBP); + + error ZeroAdminAddress(); + error ZeroFeeDistributorAddress(); + error InvalidPerfLeeway(); + error SenderNotAllowed(); + + function CONTRACT_MANAGER_ROLE() external view returns (bytes32); + + function SUBMIT_DATA_ROLE() external view returns (bytes32); + + function PAUSE_ROLE() external view returns (bytes32); + + function RESUME_ROLE() external view returns (bytes32); + + function RECOVERER_ROLE() external view returns (bytes32); + + function feeDistributor() external view returns (ICSFeeDistributor); + + function avgPerfLeewayBP() external view returns (uint256); + + /// @notice Set a new fee distributor contract + /// @param feeDistributorContract Address of the new fee distributor contract + function setFeeDistributorContract(address feeDistributorContract) external; + + /// @notice Set a new performance threshold value in basis points + /// @param valueBP performance threshold in basis points + function setPerformanceLeeway(uint256 valueBP) external; + + /// @notice Submit the data for a committee report + /// @param data Data for a committee report + /// @param contractVersion Version of the oracle consensus rules + function submitReportData( + ReportData calldata data, + uint256 contractVersion + ) external; + + /// @notice Resume accepting oracle reports + function resume() external; + + /// @notice Pause accepting oracle reports for a `duration` seconds + /// @param duration Duration of the pause in seconds + function pauseFor(uint256 duration) external; + + /// @notice Pause accepting oracle reports until a timestamp + /// @param pauseUntilInclusive Timestamp until which the oracle reports are paused + function pauseUntil(uint256 pauseUntilInclusive) external; +} diff --git a/src/interfaces/ICSModule.sol b/src/interfaces/ICSModule.sol index a9bd6427..fad4b8be 100644 --- a/src/interfaces/ICSModule.sol +++ b/src/interfaces/ICSModule.sol @@ -8,6 +8,10 @@ import { ICSAccounting } from "./ICSAccounting.sol"; import { IQueueLib } from "../lib/QueueLib.sol"; import { INOAddresses } from "../lib/NOAddresses.sol"; import { IAssetRecovererLib } from "../lib/AssetRecovererLib.sol"; +import { Batch } from "../lib/QueueLib.sol"; +import { ILidoLocator } from "./ILidoLocator.sol"; +import { ICSEarlyAdoption } from "./ICSEarlyAdoption.sol"; +import { IStETH } from "./IStETH.sol"; struct NodeOperator { // All the counters below are used together e.g. in the _updateDepositableValidatorsCount @@ -35,30 +39,463 @@ struct NodeOperatorManagementProperties { } /// @title Lido's Community Staking Module interface -interface ICSModule is - IStakingModule, - IQueueLib, - INOAddresses, - IAssetRecovererLib -{ +interface ICSModule is IQueueLib, INOAddresses, IAssetRecovererLib { error NodeOperatorDoesNotExist(); + error SenderIsNotEligible(); + error InvalidVetKeysPointer(); + error StuckKeysHigherThanNonExited(); + error ExitedKeysHigherThanTotalDeposited(); + error ExitedKeysDecrease(); + + error InvalidInput(); + error NotEnoughKeys(); + + error SigningKeysInvalidOffset(); + + error AlreadySubmitted(); + + error AlreadyActivated(); + error InvalidAmount(); + error NotAllowedToJoinYet(); + error MaxSigningKeysCountExceeded(); + + error NotSupported(); + error ZeroLocatorAddress(); + error ZeroAccountingAddress(); + error ZeroAdminAddress(); error ZeroRewardAddress(); - /// @notice Gets node operator non-withdrawn keys - /// @param nodeOperatorId ID of the node operator - /// @return Non-withdrawn keys count - function getNodeOperatorNonWithdrawnKeys( + event NodeOperatorAdded( + uint256 indexed nodeOperatorId, + address indexed managerAddress, + address indexed rewardAddress + ); + event ReferrerSet(uint256 indexed nodeOperatorId, address indexed referrer); + event DepositableSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 depositableKeysCount + ); + event VettedSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 vettedKeysCount + ); + event VettedSigningKeysCountDecreased(uint256 indexed nodeOperatorId); + event DepositedSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 depositedKeysCount + ); + event ExitedSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 exitedKeysCount + ); + event StuckSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 stuckKeysCount + ); + event TotalSigningKeysCountChanged( + uint256 indexed nodeOperatorId, + uint256 totalKeysCount + ); + event TargetValidatorsCountChanged( + uint256 indexed nodeOperatorId, + uint256 targetLimitMode, + uint256 targetValidatorsCount + ); + event WithdrawalSubmitted( + uint256 indexed nodeOperatorId, + uint256 keyIndex, + uint256 amount, + bytes pubkey + ); + event InitialSlashingSubmitted( + uint256 indexed nodeOperatorId, + uint256 keyIndex, + bytes pubkey + ); + + event PublicRelease(); + event KeyRemovalChargeSet(uint256 amount); + + event KeyRemovalChargeApplied(uint256 indexed nodeOperatorId); + event ELRewardsStealingPenaltyReported( + uint256 indexed nodeOperatorId, + bytes32 proposedBlockHash, + uint256 stolenAmount + ); + event ELRewardsStealingPenaltyCancelled( + uint256 indexed nodeOperatorId, + uint256 amount + ); + event ELRewardsStealingPenaltyCompensated( + uint256 indexed nodeOperatorId, + uint256 amount + ); + event ELRewardsStealingPenaltySettled(uint256 indexed nodeOperatorId); + + function EL_REWARDS_STEALING_ADDITIONAL_FINE() + external + view + returns (uint256); + + function INITIAL_SLASHING_PENALTY() external view returns (uint256); + + function LIDO_LOCATOR() external view returns (ILidoLocator); + + function MAX_KEY_REMOVAL_CHARGE() external view returns (uint256); + + function MAX_SIGNING_KEYS_PER_OPERATOR_BEFORE_PUBLIC_RELEASE() + external + view + returns (uint256); + + function MODULE_MANAGER_ROLE() external view returns (bytes32); + + function PAUSE_ROLE() external view returns (bytes32); + + function RECOVERER_ROLE() external view returns (bytes32); + + function REPORT_EL_REWARDS_STEALING_PENALTY_ROLE() + external + view + returns (bytes32); + + function RESUME_ROLE() external view returns (bytes32); + + function SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE() + external + view + returns (bytes32); + + function STAKING_ROUTER_ROLE() external view returns (bytes32); + + function STETH() external view returns (IStETH); + + function VERIFIER_ROLE() external view returns (bytes32); + + /// @notice Returns the address of the accounting contract + function accounting() external view returns (ICSAccounting); + + /// @notice Returns the early adoption contract address + function earlyAdoption() external view returns (ICSEarlyAdoption); + + /// @notice Pause creation of the Node Operators and keys upload for `duration` seconds. + /// Existing NO management and reward claims are still available. + /// To pause reward claims use pause method on CSAccounting + /// @param duration Duration of the pause in seconds + function pauseFor(uint256 duration) external; + + /// @notice Resume creation of the Node Operators and keys upload + function resume() external; + + /// @notice Public release mode status + function publicRelease() external view returns (bool); + + /// @notice Activate public release mode + /// Enable permissionless creation of the Node Operators + /// Remove the keys limit for the Node Operators + function activatePublicRelease() external; + + /// @notice Add a new Node Operator using ETH as a bond. + /// At least one deposit data and corresponding bond should be provided + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @param managementProperties Optional. Management properties to be used for the Node Operator. + /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. + /// If set to true `resetNodeOperatorManagerAddress` method will be disabled + /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption + /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration + function addNodeOperatorETH( + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures, + NodeOperatorManagementProperties memory managementProperties, + bytes32[] memory eaProof, + address referrer + ) external payable; + + /// @notice Add a new Node Operator using stETH as a bond. + /// At least one deposit data and corresponding bond should be provided + /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @param managementProperties Optional. Management properties to be used for the Node Operator. + /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. + /// If set to true `resetNodeOperatorManagerAddress` method will be disabled + /// @param permit Optional. Permit to use stETH as bond + /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption + /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration + function addNodeOperatorStETH( + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures, + NodeOperatorManagementProperties memory managementProperties, + ICSAccounting.PermitInput memory permit, + bytes32[] memory eaProof, + address referrer + ) external; + + /// @notice Add a new Node Operator using wstETH as a bond. + /// At least one deposit data and corresponding bond should be provided + /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @param managementProperties Optional. Management properties to be used for the Node Operator. + /// managerAddress: Used as `managerAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// rewardAddress: Used as `rewardAddress` for the Node Operator. If not passed `msg.sender` will be used. + /// extendedManagerPermissions: Flag indicating that managerAddress will be able to change rewardAddress. + /// If set to true `resetNodeOperatorManagerAddress` method will be disabled + /// @param permit Optional. Permit to use wstETH as bond + /// @param eaProof Optional. Merkle proof of the sender being eligible for the Early Adoption + /// @param referrer Optional. Referrer address. Should be passed when Node Operator is created using partners integration + function addNodeOperatorWstETH( + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures, + NodeOperatorManagementProperties memory managementProperties, + ICSAccounting.PermitInput memory permit, + bytes32[] memory eaProof, + address referrer + ) external; + + /// @notice Add new keys to the existing Node Operator using ETH as a bond + /// @param nodeOperatorId ID of the Node Operator + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + function addValidatorKeysETH( + uint256 nodeOperatorId, + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures + ) external payable; + + /// @notice Add new keys to the existing Node Operator using stETH as a bond + /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert + /// @param nodeOperatorId ID of the Node Operator + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @param permit Optional. Permit to use stETH as bond + function addValidatorKeysStETH( + uint256 nodeOperatorId, + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures, + ICSAccounting.PermitInput memory permit + ) external; + + /// @notice Add new keys to the existing Node Operator using wstETH as a bond + /// @notice Due to the stETH rounding issue make sure to make approval or sign permit with extra 10 wei to avoid revert + /// @param nodeOperatorId ID of the Node Operator + /// @param keysCount Signing keys count + /// @param publicKeys Public keys to submit + /// @param signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata + /// @param permit Optional. Permit to use wstETH as bond + function addValidatorKeysWstETH( + uint256 nodeOperatorId, + uint256 keysCount, + bytes memory publicKeys, + bytes memory signatures, + ICSAccounting.PermitInput memory permit + ) external; + + /// @notice Stake user's ETH with Lido and make a deposit in stETH to the bond of the existing Node Operator + /// @param nodeOperatorId ID of the Node Operator + function depositETH(uint256 nodeOperatorId) external payable; + + /// @notice Deposit user's stETH to the bond of the existing Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param stETHAmount Amount of stETH to deposit + /// @param permit Optional. Permit to use stETH as bond + function depositStETH( + uint256 nodeOperatorId, + uint256 stETHAmount, + ICSAccounting.PermitInput memory permit + ) external; + + /// @notice Unwrap the user's wstETH and make a deposit in stETH to the bond of the existing Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param wstETHAmount Amount of wstETH to deposit + /// @param permit Optional. Permit to use wstETH as bond + function depositWstETH( + uint256 nodeOperatorId, + uint256 wstETHAmount, + ICSAccounting.PermitInput memory permit + ) external; + + /// @notice Claim full reward (fees + bond rewards) in stETH for the given Node Operator + /// @notice If `stETHAmount` exceeds the current claimable amount, the claimable amount will be used instead + /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim + /// @param nodeOperatorId ID of the Node Operator + /// @param stETHAmount Amount of stETH to claim + /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Optional. Merkle proof of the rewards + function claimRewardsStETH( + uint256 nodeOperatorId, + uint256 stETHAmount, + uint256 cumulativeFeeShares, + bytes32[] memory rewardsProof + ) external; + + /// @notice Request full reward (fees + bond rewards) in Withdrawal NFT (unstETH) for the given Node Operator + /// @notice Amounts less than `MIN_STETH_WITHDRAWAL_AMOUNT` (see LidoWithdrawalQueue contract) are not allowed + /// @notice Amounts above `MAX_STETH_WITHDRAWAL_AMOUNT` should be requested in several transactions + /// @notice If `ethAmount` exceeds the current claimable amount, the claimable amount will be used instead + /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim + /// @dev Reverts if amount isn't between `MIN_STETH_WITHDRAWAL_AMOUNT` and `MAX_STETH_WITHDRAWAL_AMOUNT` + /// @param nodeOperatorId ID of the Node Operator + /// @param stEthAmount Amount of ETH to request + /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Optional. Merkle proof of the rewards + function claimRewardsUnstETH( + uint256 nodeOperatorId, + uint256 stEthAmount, + uint256 cumulativeFeeShares, + bytes32[] memory rewardsProof + ) external; + + /// @notice Claim full reward (fees + bond rewards) in wstETH for the given Node Operator + /// @notice If `wstETHAmount` exceeds the current claimable amount, the claimable amount will be used instead + /// @notice If `rewardsProof` is not provided, only excess bond (bond rewards) will be available for claim + /// @param nodeOperatorId ID of the Node Operator + /// @param wstETHAmount Amount of wstETH to claim + /// @param cumulativeFeeShares Optional. Cumulative fee stETH shares for the Node Operator + /// @param rewardsProof Optional. Merkle proof of the rewards + function claimRewardsWstETH( + uint256 nodeOperatorId, + uint256 wstETHAmount, + uint256 cumulativeFeeShares, + bytes32[] memory rewardsProof + ) external; + + /// @notice Report EL rewards stealing for the given Node Operator + /// @notice The final locked amount will be equal to the stolen funds plus EL stealing additional fine + /// @param nodeOperatorId ID of the Node Operator + /// @param blockHash Execution layer block hash of the proposed block with EL rewards stealing + /// @param amount Amount of stolen EL rewards in ETH + function reportELRewardsStealingPenalty( + uint256 nodeOperatorId, + bytes32 blockHash, + uint256 amount + ) external; + + /// @notice Compensate EL rewards stealing penalty for the given Node Operator to prevent further validator exits + /// @dev Can only be called by the Node Operator manager + /// @param nodeOperatorId ID of the Node Operator + function compensateELRewardsStealingPenalty( uint256 nodeOperatorId - ) external view returns (uint256); + ) external payable; + + /// @notice Cancel previously reported and not settled EL rewards stealing penalty for the given Node Operator + /// @notice The funds will be unlocked + /// @param nodeOperatorId ID of the Node Operator + /// @param amount Amount of penalty to cancel + function cancelELRewardsStealingPenalty( + uint256 nodeOperatorId, + uint256 amount + ) external; + + /// @notice Settle locked bond for the given Node Operators + /// @dev SETTLE_EL_REWARDS_STEALING_PENALTY_ROLE role is expected to be assigned to Easy Track + /// @param nodeOperatorIds IDs of the Node Operators + function settleELRewardsStealingPenalty( + uint256[] memory nodeOperatorIds + ) external; + + /// @notice Propose a new manager address for the Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param proposedAddress Proposed manager address + function proposeNodeOperatorManagerAddressChange( + uint256 nodeOperatorId, + address proposedAddress + ) external; + + /// @notice Confirm a new manager address for the Node Operator. + /// Should be called from the currently proposed address + /// @param nodeOperatorId ID of the Node Operator + function confirmNodeOperatorManagerAddressChange( + uint256 nodeOperatorId + ) external; + + /// @notice Reset the manager address to the reward address. + /// Should be called from the reward address + /// @param nodeOperatorId ID of the Node Operator + function resetNodeOperatorManagerAddress(uint256 nodeOperatorId) external; + + /// @notice Propose a new reward address for the Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param proposedAddress Proposed reward address + function proposeNodeOperatorRewardAddressChange( + uint256 nodeOperatorId, + address proposedAddress + ) external; - /// @notice Returns the node operator by id - /// @param nodeOperatorId Node Operator id + /// @notice Confirm a new reward address for the Node Operator. + /// Should be called from the currently proposed address + /// @param nodeOperatorId ID of the Node Operator + function confirmNodeOperatorRewardAddressChange( + uint256 nodeOperatorId + ) external; + + /// @notice Change rewardAddress if extendedManagerPermissions is enabled for the Node Operator + /// @param nodeOperatorId ID of the Node Operator + /// @param newAddress Proposed reward address + function changeNodeOperatorRewardAddress( + uint256 nodeOperatorId, + address newAddress + ) external; + + /// @notice Returns the deposit queue head and tail + function depositQueue() external view returns (uint128 head, uint128 tail); + + /// @notice Get the deposit queue item by an index + /// @param index Index of a queue item + /// @return Deposit queue item + function depositQueueItem(uint128 index) external view returns (Batch); + + /// @notice Clean the deposit queue from batches with no depositable keys + /// @dev Use **eth_call** to check how many items will be removed + /// @param maxItems How many queue items to review + /// @return removed Count of batches to be removed by visiting `maxItems` batches + /// @return lastRemovedAtDepth The value to use as `maxItems` to remove `removed` batches if the static call of the method was used + function cleanDepositQueue( + uint256 maxItems + ) external returns (uint256 removed, uint256 lastRemovedAtDepth); + + /// @notice Perform queue normalization for the given Node Operator + /// @notice Normalization stands for adding vetted but not enqueued keys to the queue + /// @param nodeOperatorId ID of the Node Operator + function normalizeQueue(uint256 nodeOperatorId) external; + + /// @notice Get Node Operator info + /// @param nodeOperatorId ID of the Node Operator + /// @return Node Operator info function getNodeOperator( uint256 nodeOperatorId ) external view returns (NodeOperator memory); - /// @notice Gets node operator signing keys - /// @param nodeOperatorId ID of the node operator + /// @notice Get Node Operator non-withdrawn keys + /// @param nodeOperatorId ID of the Node Operator + /// @return Non-withdrawn keys count + function getNodeOperatorNonWithdrawnKeys( + uint256 nodeOperatorId + ) external view returns (uint256); + + /// @notice Get Node Operator signing keys + /// @param nodeOperatorId ID of the Node Operator /// @param startIndex Index of the first key /// @param keysCount Count of keys to get /// @return Signing keys @@ -68,30 +505,35 @@ interface ICSModule is uint256 keysCount ) external view returns (bytes memory); - /// @notice Gets node operator signing keys with signatures - /// @param nodeOperatorId ID of the node operator + /// @notice Get Node Operator signing keys with signatures + /// @param nodeOperatorId ID of the Node Operator /// @param startIndex Index of the first key /// @param keysCount Count of keys to get /// @return keys Signing keys - /// @return signatures Signatures of (deposit_message, domain) tuples + /// @return signatures Signatures of `(deposit_message_root, domain)` tuples + /// https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#signingdata function getSigningKeysWithSignatures( uint256 nodeOperatorId, uint256 startIndex, uint256 keysCount ) external view returns (bytes memory keys, bytes memory signatures); - /// @notice Report node operator's key as slashed and apply initial slashing penalty. - /// @param nodeOperatorId Operator ID in the module. - /// @param keyIndex Index of the slashed key in the node operator's keys. + /// @notice Report Node Operator's key as slashed and apply the initial slashing penalty + /// @notice Called by the Verifier contract. + /// See `CSVerifier.processSlashingProof` to use this method permissionless + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the slashed key in the Node Operator's keys storage function submitInitialSlashing( uint256 nodeOperatorId, uint256 keyIndex ) external; - /// @notice Report node operator's key as withdrawn and settle withdrawn amount. - /// @param nodeOperatorId Operator ID in the module. - /// @param keyIndex Index of the withdrawn key in the node operator's keys. - /// @param amount Amount of withdrawn ETH in wei. + /// @notice Report Node Operator's key as withdrawn and settle withdrawn amount + /// @notice Called by the Verifier contract. + /// See `CSVerifier.processWithdrawalProof` to use this method permissionless + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the withdrawn key in the Node Operator's keys storage + /// @param amount Amount of withdrawn ETH in wei /// @param isSlashed Validator is slashed or not function submitWithdrawal( uint256 nodeOperatorId, @@ -100,17 +542,39 @@ interface ICSModule is bool isSlashed ) external; - function depositWstETH( + /// @notice Check if the given Node Operator's key is reported as slashed + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the key to check + /// @return Validator reported as slashed flag + function isValidatorSlashed( uint256 nodeOperatorId, - uint256 wstETHAmount, - ICSAccounting.PermitInput calldata permit - ) external; + uint256 keyIndex + ) external view returns (bool); - function depositStETH( + /// @notice Check if the given Node Operator's key is reported as withdrawn + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex index of the key to check + /// @return Validator reported as withdrawn flag + function isValidatorWithdrawn( uint256 nodeOperatorId, - uint256 stETHAmount, - ICSAccounting.PermitInput calldata permit + uint256 keyIndex + ) external view returns (bool); + + /// @notice Remove keys for the Node Operator and confiscate removal charge for each deleted key + /// @param nodeOperatorId ID of the Node Operator + /// @param startIndex Index of the first key + /// @param keysCount Keys count to delete + function removeKeys( + uint256 nodeOperatorId, + uint256 startIndex, + uint256 keysCount ) external; - function depositETH(uint256 nodeOperatorId) external payable; + /// @notice Returns the key removal charge amount + function keyRemovalCharge() external view returns (uint256); + + /// @notice Set the key removal charge amount. + /// A charge is taken from the bond for each removed key + /// @param amount Amount of stETH in wei to be charged for removing a single key + function setKeyRemovalCharge(uint256 amount) external; } diff --git a/src/interfaces/ICSVerifier.sol b/src/interfaces/ICSVerifier.sol index 6ea0ec3e..02f52647 100644 --- a/src/interfaces/ICSVerifier.sol +++ b/src/interfaces/ICSVerifier.sol @@ -3,8 +3,9 @@ pragma solidity 0.8.24; -import { BeaconBlockHeader } from "../lib/Types.sol"; +import { BeaconBlockHeader, Slot } from "../lib/Types.sol"; import { GIndex } from "../lib/GIndex.sol"; +import { ICSModule } from "./ICSModule.sol"; interface ICSVerifier { struct ProvableBeaconBlockHeader { @@ -50,7 +51,47 @@ interface ICSVerifier { bytes32[] proof; } - /// @notice `witness` is a slashing witness against the `beaconBlock`'s state root. + error RootNotFound(); + error InvalidGIndex(); + error InvalidBlockHeader(); + error InvalidChainConfig(); + error PartialWithdrawal(); + error ValidatorNotWithdrawn(); + error InvalidWithdrawalAddress(); + error UnsupportedSlot(Slot slot); + error ZeroModuleAddress(); + error ZeroWithdrawalAddress(); + error InvalidPivotSlot(); + + function BEACON_ROOTS() external view returns (address); + + function SLOTS_PER_EPOCH() external view returns (uint64); + + function GI_FIRST_WITHDRAWAL_PREV() external view returns (GIndex); + + function GI_FIRST_WITHDRAWAL_CURR() external view returns (GIndex); + + function GI_FIRST_VALIDATOR_PREV() external view returns (GIndex); + + function GI_FIRST_VALIDATOR_CURR() external view returns (GIndex); + + function GI_HISTORICAL_SUMMARIES_PREV() external view returns (GIndex); + + function GI_HISTORICAL_SUMMARIES_CURR() external view returns (GIndex); + + function FIRST_SUPPORTED_SLOT() external view returns (Slot); + + function PIVOT_SLOT() external view returns (Slot); + + function WITHDRAWAL_ADDRESS() external view returns (address); + + function MODULE() external view returns (ICSModule); + + /// @notice Verify slashing proof and report slashing to the module for valid proofs + /// @param beaconBlock Beacon block header + /// @param witness Slashing witness against the `beaconBlock`'s state root. + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the validator key in the Node Operator's key storage function processSlashingProof( ProvableBeaconBlockHeader calldata beaconBlock, SlashingWitness calldata witness, @@ -58,7 +99,11 @@ interface ICSVerifier { uint256 keyIndex ) external; - /// @notice `witness` is a withdrawal witness against the `beaconBlock`'s state root. + /// @notice Verify withdrawal proof and report withdrawal to the module for valid proofs + /// @param beaconBlock Beacon block header + /// @param witness Withdrawal witness against the `beaconBlock`'s state root. + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the validator key in the Node Operator's key storage function processWithdrawalProof( ProvableBeaconBlockHeader calldata beaconBlock, WithdrawalWitness calldata witness, @@ -66,8 +111,12 @@ interface ICSVerifier { uint256 keyIndex ) external; - /// @notice `oldHeader` is a beacon block header witness against the `beaconBlock`'s state root. - /// @notice `witness` is a withdrawal witness against the `oldHeader`'s state root. + /// @notice Verify withdrawal proof against historical summaries data and report withdrawal to the module for valid proofs + /// @param beaconBlock Beacon block header + /// @param oldBlock Historical block header witness + /// @param witness Withdrawal witness + /// @param nodeOperatorId ID of the Node Operator + /// @param keyIndex Index of the validator key in the Node Operator's key storage function processHistoricalWithdrawalProof( ProvableBeaconBlockHeader calldata beaconBlock, HistoricalHeaderWitness calldata oldBlock, diff --git a/src/interfaces/IStakingModule.sol b/src/interfaces/IStakingModule.sol index 80e0ff4e..717765a6 100644 --- a/src/interfaces/IStakingModule.sol +++ b/src/interfaces/IStakingModule.sol @@ -6,6 +6,7 @@ pragma solidity 0.8.24; /// @title Lido's Staking Module interface interface IStakingModule { /// @notice Returns the type of the staking module + /// @return Module type function getType() external view returns (bytes32); /// @notice Returns all-validators summary in the staking module @@ -25,7 +26,7 @@ interface IStakingModule { ); /// @notice Returns all-validators summary belonging to the node operator with the given id - /// @param _nodeOperatorId id of the operator to return report for + /// @param nodeOperatorId id of the operator to return report for /// @return targetLimitMode shows whether the current target limit applied to the node operator (1 = soft mode, 2 = forced mode) /// @return targetValidatorsCount relative target active validators limit for operator /// @return stuckValidatorsCount number of validators with an expired request to exit time @@ -40,7 +41,7 @@ interface IStakingModule { /// EXITED state this counter is not decreasing /// @return depositableValidatorsCount number of validators in the set available for deposit function getNodeOperatorSummary( - uint256 _nodeOperatorId + uint256 nodeOperatorId ) external view @@ -75,91 +76,94 @@ interface IStakingModule { function getActiveNodeOperatorsCount() external view returns (uint256); /// @notice Returns if the node operator with given id is active - /// @param _nodeOperatorId Id of the node operator + /// @param nodeOperatorId Id of the node operator function getNodeOperatorIsActive( - uint256 _nodeOperatorId + uint256 nodeOperatorId ) external view returns (bool); - /// @notice Returns up to `_limit` node operator ids starting from the `_offset`. The order of + /// @notice Returns up to `limit` node operator ids starting from the `offset`. The order of /// the returned ids is not defined and might change between calls. - /// @dev This view must not revert in case of invalid data passed. When `_offset` exceeds the - /// total node operators count or when `_limit` is equal to 0 MUST be returned empty array. + /// @dev This view must not revert in case of invalid data passed. When `offset` exceeds the + /// total node operators count or when `limit` is equal to 0 MUST be returned empty array. function getNodeOperatorIds( - uint256 _offset, - uint256 _limit + uint256 offset, + uint256 limit ) external view returns (uint256[] memory nodeOperatorIds); /// @notice Called by StakingRouter to signal that stETH rewards were minted for this module. - /// @param _totalShares Amount of stETH shares that were minted to reward all node operators. + /// @param totalShares Amount of stETH shares that were minted to reward all node operators. /// @dev IMPORTANT: this method SHOULD revert with empty error data ONLY because of "out of gas". /// Details about error data: https://docs.soliditylang.org/en/v0.8.9/control-structures.html#error-handling-assert-require-revert-and-exceptions - function onRewardsMinted(uint256 _totalShares) external; + function onRewardsMinted(uint256 totalShares) external; - /// @notice Called by StakingRouter to decrease the number of vetted keys for node operator with given id - /// @param _nodeOperatorIds bytes packed array of the node operators id - /// @param _vettedSigningKeysCounts bytes packed array of the new number of vetted keys for the node operators + /// @notice Called by StakingRouter to decrease the number of vetted keys for Node Operators with given ids + /// @param nodeOperatorIds Bytes packed array of the Node Operator ids + /// @param vettedSigningKeysCounts Bytes packed array of the new numbers of vetted keys for the Node Operators function decreaseVettedSigningKeysCount( - bytes calldata _nodeOperatorIds, - bytes calldata _vettedSigningKeysCounts + bytes calldata nodeOperatorIds, + bytes calldata vettedSigningKeysCounts ) external; /// @notice Updates the number of the validators of the given node operator that were requested /// to exit but failed to do so in the max allowed time - /// @param _nodeOperatorIds bytes packed array of the node operators id - /// @param _stuckValidatorsCounts bytes packed array of the new number of STUCK validators for the node operators + /// @param nodeOperatorIds bytes packed array of the node operators id + /// @param stuckValidatorsCounts bytes packed array of the new number of STUCK validators for the node operators function updateStuckValidatorsCount( - bytes calldata _nodeOperatorIds, - bytes calldata _stuckValidatorsCounts + bytes calldata nodeOperatorIds, + bytes calldata stuckValidatorsCounts ) external; /// @notice Updates the number of the validators in the EXITED state for node operator with given id - /// @param _nodeOperatorIds bytes packed array of the node operators id - /// @param _exitedValidatorsCounts bytes packed array of the new number of EXITED validators for the node operators + /// @param nodeOperatorIds bytes packed array of the node operators id + /// @param exitedValidatorsCounts bytes packed array of the new number of EXITED validators for the node operators function updateExitedValidatorsCount( - bytes calldata _nodeOperatorIds, - bytes calldata _exitedValidatorsCounts + bytes calldata nodeOperatorIds, + bytes calldata exitedValidatorsCounts ) external; /// @notice Updates the number of the refunded validators for node operator with the given id - /// @param _nodeOperatorId Id of the node operator - /// @param _refundedValidatorsCount New number of refunded validators of the node operator + /// @param nodeOperatorId Id of the node operator + /// @param refundedValidatorsCount New number of refunded validators of the node operator function updateRefundedValidatorsCount( - uint256 _nodeOperatorId, - uint256 _refundedValidatorsCount + uint256 nodeOperatorId, + uint256 refundedValidatorsCount ) external; /// @notice Updates the limit of the validators that can be used for deposit - /// @param _nodeOperatorId Id of the node operator - /// @param _targetLimitMode target limit mode - /// @param _targetLimit Target limit of the node operator + /// @param nodeOperatorId ID of the Node Operator + /// @param targetLimitMode Target limit mode for the Node Operator (see https://hackmd.io/@lido/BJXRTxMRp) + /// 0 - disabled + /// 1 - soft mode + /// 2 - forced mode + /// @param targetLimit Target limit of validators function updateTargetValidatorsLimits( - uint256 _nodeOperatorId, - uint256 _targetLimitMode, - uint256 _targetLimit + uint256 nodeOperatorId, + uint256 targetLimitMode, + uint256 targetLimit ) external; /// @notice Unsafely updates the number of validators in the EXITED/STUCK states for node operator with given id /// 'unsafely' means that this method can both increase and decrease exited and stuck counters - /// @param _nodeOperatorId Id of the node operator - /// @param _exitedValidatorsCount New number of EXITED validators for the node operator - /// @param _stuckValidatorsCount New number of STUCK validator for the node operator + /// @param nodeOperatorId Id of the node operator + /// @param exitedValidatorsCount New number of EXITED validators for the node operator + /// @param stuckValidatorsCount New number of STUCK validator for the node operator function unsafeUpdateValidatorsCount( - uint256 _nodeOperatorId, - uint256 _exitedValidatorsCount, - uint256 _stuckValidatorsCount + uint256 nodeOperatorId, + uint256 exitedValidatorsCount, + uint256 stuckValidatorsCount ) external; /// @notice Obtains deposit data to be used by StakingRouter to deposit to the Ethereum Deposit /// contract /// @dev The method MUST revert when the staking module has not enough deposit data items - /// @param _depositsCount Number of deposits to be done - /// @param _depositCalldata Staking module defined data encoded as bytes. - /// IMPORTANT: _depositCalldata MUST NOT modify the deposit data set of the staking module + /// @param depositsCount Number of deposits to be done + /// @param depositCalldata Staking module defined data encoded as bytes. + /// IMPORTANT: depositCalldata MUST NOT modify the deposit data set of the staking module /// @return publicKeys Batch of the concatenated public validators keys /// @return signatures Batch of the concatenated deposit signatures for returned public keys function obtainDepositData( - uint256 _depositsCount, - bytes calldata _depositCalldata + uint256 depositsCount, + bytes calldata depositCalldata ) external returns (bytes memory publicKeys, bytes memory signatures); /// @notice Called by StakingRouter after it finishes updating exited and stuck validators diff --git a/test/CSAccounting.t.sol b/test/CSAccounting.t.sol index 4be77749..8bf7bf7b 100644 --- a/test/CSAccounting.t.sol +++ b/test/CSAccounting.t.sol @@ -14,6 +14,8 @@ import { ICSFeeDistributor } from "../src/interfaces/ICSFeeDistributor.sol"; import { IWithdrawalQueue } from "../src/interfaces/IWithdrawalQueue.sol"; import { ICSAccounting } from "../src/interfaces/ICSAccounting.sol"; import { ICSBondCurve } from "../src/interfaces/ICSBondCurve.sol"; +import { ICSBondCore } from "../src/interfaces/ICSBondCore.sol"; +import { ICSBondLock } from "../src/interfaces/ICSBondLock.sol"; import { CSAccounting } from "../src/CSAccounting.sol"; import { CSBondCore } from "../src/abstract/CSBondCore.sol"; @@ -157,7 +159,7 @@ contract CSAccountingConstructorTest is CSAccountingBaseConstructorTest { } function test_constructor_RevertWhen_ZeroModuleAddress() public { - vm.expectRevert(CSAccounting.ZeroModuleAddress.selector); + vm.expectRevert(ICSAccounting.ZeroModuleAddress.selector); accounting = new CSAccounting( address(locator), address(0), @@ -170,7 +172,7 @@ contract CSAccountingConstructorTest is CSAccountingBaseConstructorTest { function test_constructor_RevertWhen_InvalidBondLockPeriod_MinMoreThanMax() public { - vm.expectRevert(CSBondLock.InvalidBondLockPeriod.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockPeriod.selector); accounting = new CSAccounting( address(locator), address(0), @@ -183,7 +185,7 @@ contract CSAccountingConstructorTest is CSAccountingBaseConstructorTest { function test_constructor_RevertWhen_InvalidBondLockPeriod_MaxTooBig() public { - vm.expectRevert(CSBondLock.InvalidBondLockPeriod.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockPeriod.selector); accounting = new CSAccounting( address(locator), address(0), @@ -194,7 +196,7 @@ contract CSAccountingConstructorTest is CSAccountingBaseConstructorTest { } function test_constructor_RevertWhen_InvalidMaxBondCurveLength() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveMaxLength.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveMaxLength.selector); accounting = new CSAccounting( address(locator), address(0), @@ -239,11 +241,13 @@ contract CSAccountingInitTest is CSAccountingBaseInitTest { _enableInitializers(address(accounting)); vm.expectEmit(true, false, false, true, address(accounting)); - emit CSBondCurve.BondCurveAdded(curve); + emit ICSBondCurve.BondCurveAdded(curve); vm.expectEmit(true, false, false, true, address(accounting)); - emit CSBondLock.BondLockPeriodChanged(8 weeks); + emit ICSBondLock.BondLockPeriodChanged(8 weeks); vm.expectEmit(true, false, false, true, address(accounting)); - emit CSAccounting.ChargePenaltyRecipientSet(testChargePenaltyRecipient); + emit ICSAccounting.ChargePenaltyRecipientSet( + testChargePenaltyRecipient + ); accounting.initialize( curve, admin, @@ -261,7 +265,7 @@ contract CSAccountingInitTest is CSAccountingBaseInitTest { _enableInitializers(address(accounting)); - vm.expectRevert(CSAccounting.ZeroAdminAddress.selector); + vm.expectRevert(ICSAccounting.ZeroAdminAddress.selector); accounting.initialize( curve, address(0), @@ -277,7 +281,7 @@ contract CSAccountingInitTest is CSAccountingBaseInitTest { _enableInitializers(address(accounting)); - vm.expectRevert(CSAccounting.ZeroFeeDistributorAddress.selector); + vm.expectRevert(ICSAccounting.ZeroFeeDistributorAddress.selector); accounting.initialize( curve, admin, @@ -294,7 +298,7 @@ contract CSAccountingInitTest is CSAccountingBaseInitTest { _enableInitializers(address(accounting)); vm.expectRevert( - CSAccounting.ZeroChargePenaltyRecipientAddress.selector + ICSAccounting.ZeroChargePenaltyRecipientAddress.selector ); accounting.initialize( curve, @@ -1521,7 +1525,7 @@ contract CSAccountingClaimStETHRewardsTest is CSAccountingClaimRewardsBaseTest { _rewards({ fee: 0.1 ether }); _lock({ id: 0, amount: 1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsStETH( leaf.nodeOperatorId, @@ -1787,7 +1791,7 @@ contract CSAccountingClaimStETHRewardsTest is CSAccountingClaimRewardsBaseTest { _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsStETH( leaf.nodeOperatorId, @@ -1807,7 +1811,7 @@ contract CSAccountingClaimStETHRewardsTest is CSAccountingClaimRewardsBaseTest { _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsStETH( leaf.nodeOperatorId, @@ -1860,7 +1864,7 @@ contract CSAccountingClaimStETHRewardsTest is CSAccountingClaimRewardsBaseTest { _deposit({ bond: 32 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsStETH( leaf.nodeOperatorId, @@ -1904,7 +1908,7 @@ contract CSAccountingClaimStETHRewardsTest is CSAccountingClaimRewardsBaseTest { _operator({ ongoing: 16, withdrawn: 0 }); vm.expectRevert( - abi.encodeWithSelector(CSAccounting.SenderIsNotCSM.selector) + abi.encodeWithSelector(ICSAccounting.SenderIsNotCSM.selector) ); vm.prank(stranger); accounting.claimRewardsStETH( @@ -2017,7 +2021,7 @@ contract CSAccountingClaimWstETHRewardsTest is _rewards({ fee: 0.1 ether }); _lock({ id: 0, amount: 1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsWstETH( leaf.nodeOperatorId, @@ -2313,7 +2317,7 @@ contract CSAccountingClaimWstETHRewardsTest is _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsWstETH( leaf.nodeOperatorId, @@ -2333,7 +2337,7 @@ contract CSAccountingClaimWstETHRewardsTest is _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsWstETH( leaf.nodeOperatorId, @@ -2399,7 +2403,7 @@ contract CSAccountingClaimWstETHRewardsTest is _deposit({ bond: 32 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsWstETH( leaf.nodeOperatorId, @@ -2443,7 +2447,7 @@ contract CSAccountingClaimWstETHRewardsTest is _operator({ ongoing: 16, withdrawn: 0 }); vm.expectRevert( - abi.encodeWithSelector(CSAccounting.SenderIsNotCSM.selector) + abi.encodeWithSelector(ICSAccounting.SenderIsNotCSM.selector) ); vm.prank(stranger); accounting.claimRewardsWstETH( @@ -2526,7 +2530,7 @@ contract CSAccountingclaimRewardsUnstETHTest is _rewards({ fee: 0.1 ether }); _lock({ id: 0, amount: 1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsUnstETH( leaf.nodeOperatorId, @@ -2742,7 +2746,7 @@ contract CSAccountingclaimRewardsUnstETHTest is _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsUnstETH( leaf.nodeOperatorId, @@ -2762,7 +2766,7 @@ contract CSAccountingclaimRewardsUnstETHTest is _deposit({ bond: 16 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsUnstETH( leaf.nodeOperatorId, @@ -2810,7 +2814,7 @@ contract CSAccountingclaimRewardsUnstETHTest is _deposit({ bond: 32 ether }); _rewards({ fee: 0.1 ether }); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); vm.prank(address(stakingModule)); accounting.claimRewardsUnstETH( leaf.nodeOperatorId, @@ -2854,7 +2858,7 @@ contract CSAccountingclaimRewardsUnstETHTest is _operator({ ongoing: 16, withdrawn: 0 }); vm.expectRevert( - abi.encodeWithSelector(CSAccounting.SenderIsNotCSM.selector) + abi.encodeWithSelector(ICSAccounting.SenderIsNotCSM.selector) ); vm.prank(stranger); accounting.claimRewardsUnstETH( @@ -2925,7 +2929,7 @@ contract CSAccountingDepositEthTest is CSAccountingBaseTest { vm.deal(stranger, 32 ether); vm.prank(stranger); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); accounting.depositETH{ value: 32 ether }(stranger, 0); } } @@ -3205,7 +3209,7 @@ contract CSAccountingDepositStEthTest is CSAccountingBaseTest { function test_depositStETH_revertWhen_SenderIsNotCSM() public { vm.prank(stranger); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); accounting.depositStETH( stranger, 0, @@ -3510,7 +3514,7 @@ contract CSAccountingDepositWstEthTest is CSAccountingBaseTest { function test_depositWstETH_revertWhen_SenderIsNotCSM() public { vm.prank(stranger); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); accounting.depositWstETH( stranger, 0, @@ -3562,7 +3566,7 @@ contract CSAccountingPenalizeTest is CSAccountingBaseTest { } function test_penalize_RevertWhen_SenderIsNotCSM() public { - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); vm.prank(stranger); accounting.penalize(0, 20); } @@ -3595,7 +3599,7 @@ contract CSAccountingChargeFeeTest is CSAccountingBaseTest { } function test_chargeFee_RevertWhen_SenderIsNotCSM() public { - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); vm.prank(stranger); accounting.chargeFee(0, 20); } @@ -3625,7 +3629,7 @@ contract CSAccountingLockBondETHTest is CSAccountingBaseTest { function test_lockBondETH_RevertWhen_SenderIsNotCSM() public { mock_getNodeOperatorsCount(1); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); vm.prank(stranger); accounting.lockBondETH(0, 1 ether); } @@ -3657,7 +3661,7 @@ contract CSAccountingLockBondETHTest is CSAccountingBaseTest { function test_releaseLockedBondETH_RevertWhen_SenderIsNotCSM() public { mock_getNodeOperatorsCount(1); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); vm.prank(stranger); accounting.releaseLockedBondETH(0, 1 ether); } @@ -3669,7 +3673,7 @@ contract CSAccountingLockBondETHTest is CSAccountingBaseTest { accounting.lockBondETH(0, 1 ether); vm.expectEmit(true, true, true, true, address(accounting)); - emit CSAccounting.BondLockCompensated(0, 0.4 ether); + emit ICSAccounting.BondLockCompensated(0, 0.4 ether); vm.deal(address(stakingModule), 0.4 ether); vm.prank(address(stakingModule)); @@ -3695,7 +3699,7 @@ contract CSAccountingLockBondETHTest is CSAccountingBaseTest { vm.deal(address(stakingModule), 0.4 ether); vm.prank(address(stakingModule)); - vm.expectRevert(CSAccounting.ElRewardsVaultReceiveFailed.selector); + vm.expectRevert(ICSAccounting.ElRewardsVaultReceiveFailed.selector); accounting.compensateLockedBondETH{ value: 0.4 ether }(0); } @@ -3706,7 +3710,7 @@ contract CSAccountingLockBondETHTest is CSAccountingBaseTest { vm.prank(address(stakingModule)); accounting.lockBondETH(0, 1 ether); - vm.expectRevert(CSAccounting.SenderIsNotCSM.selector); + vm.expectRevert(ICSAccounting.SenderIsNotCSM.selector); vm.prank(stranger); accounting.compensateLockedBondETH{ value: 1 ether }(0); } @@ -3808,7 +3812,7 @@ contract CSAccountingBondCurveTest is CSAccountingBaseTest { } function test_updateBondCurve_RevertWhen_InvalidBondCurveId() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveId.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveId.selector); vm.prank(admin); accounting.updateBondCurve(1, new uint256[](0)); } @@ -3833,7 +3837,7 @@ contract CSAccountingBondCurveTest is CSAccountingBaseTest { function test_setBondCurve_RevertWhen_OperatorDoesNotExist() public { mock_getNodeOperatorsCount(0); - vm.expectRevert(CSAccounting.NodeOperatorDoesNotExist.selector); + vm.expectRevert(ICSAccounting.NodeOperatorDoesNotExist.selector); vm.prank(admin); accounting.setBondCurve({ nodeOperatorId: 0, curveId: 2 }); } @@ -3867,7 +3871,7 @@ contract CSAccountingBondCurveTest is CSAccountingBaseTest { function test_resetBondCurve_RevertWhen_OperatorDoesNotExist() public { mock_getNodeOperatorsCount(0); - vm.expectRevert(CSAccounting.NodeOperatorDoesNotExist.selector); + vm.expectRevert(ICSAccounting.NodeOperatorDoesNotExist.selector); vm.prank(address(stakingModule)); accounting.resetBondCurve({ nodeOperatorId: 0 }); } @@ -3895,7 +3899,7 @@ contract CSAccountingMiscTest is CSAccountingBaseTest { function test_setChargePenaltyRecipient() public { vm.prank(admin); vm.expectEmit(true, false, false, true, address(accounting)); - emit CSAccounting.ChargePenaltyRecipientSet(address(1337)); + emit ICSAccounting.ChargePenaltyRecipientSet(address(1337)); accounting.setChargePenaltyRecipient(address(1337)); assertEq(accounting.chargePenaltyRecipient(), address(1337)); } @@ -4086,7 +4090,7 @@ contract CSAccountingPullFeeRewardsTest is CSAccountingBaseTest { function test_pullFeeRewards_revertWhen_operatorDoesNotExits() public { mock_getNodeOperatorsCount(0); - vm.expectRevert(CSAccounting.NodeOperatorDoesNotExist.selector); + vm.expectRevert(ICSAccounting.NodeOperatorDoesNotExist.selector); accounting.pullFeeRewards(0, 0, new bytes32[](0)); } } diff --git a/test/CSBondCore.t.sol b/test/CSBondCore.t.sol index caa8e49b..b9b0243a 100644 --- a/test/CSBondCore.t.sol +++ b/test/CSBondCore.t.sol @@ -17,6 +17,7 @@ import { WithdrawalQueueMock } from "./helpers/mocks/WithdrawalQueueMock.sol"; import { IStETH } from "../src/interfaces/IStETH.sol"; import { IBurner } from "../src/interfaces/IBurner.sol"; import { IWithdrawalQueue } from "../src/interfaces/IWithdrawalQueue.sol"; +import { ICSBondCore } from "../src/interfaces/ICSBondCore.sol"; import { Utilities } from "./helpers/Utilities.sol"; import { Fixtures } from "./helpers/Fixtures.sol"; @@ -140,7 +141,7 @@ contract CSBondCoreConstructorTest is CSBondCoreTestBase { } function test_constructor_RevertIf_ZeroLocator() public { - vm.expectRevert(CSBondCore.ZeroLocatorAddress.selector); + vm.expectRevert(ICSBondCore.ZeroLocatorAddress.selector); new CSBondCoreTestable(address(0)); } } @@ -163,7 +164,7 @@ contract CSBondCoreBondGettersTest is CSBondCoreTestBase { contract CSBondCoreETHTest is CSBondCoreTestBase { function test_depositETH() public { vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondDepositedETH(0, user, 1 ether); + emit ICSBondCore.BondDepositedETH(0, user, 1 ether); bondCore.depositETH{ value: 1 ether }(user, 0); uint256 shares = stETH.getSharesByPooledEth(1 ether); @@ -180,7 +181,7 @@ contract CSBondCoreETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimableShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); + emit ICSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimUnstETH(0, claimedETH + 1, user); @@ -198,14 +199,14 @@ contract CSBondCoreETHTest is CSBondCoreTestBase { function test_claimUnstETH_WhenClaimableIsZero() public { assertEq(bondCore.getBondShares(0), 0); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimUnstETH(0, 100, user); } function test_claimUnstETH_WhenToClaimIsZero() public { _deposit(2 ether); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimUnstETH(0, 0, user); } @@ -216,7 +217,7 @@ contract CSBondCoreETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimableShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); + emit ICSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimUnstETH(0, 2 ether, user); @@ -238,7 +239,7 @@ contract CSBondCoreETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimedShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); + emit ICSBondCore.BondClaimedUnstETH(0, user, claimedETH, 0); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimUnstETH(0, 0.25 ether, user); @@ -263,7 +264,7 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { vm.stopPrank(); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondDepositedStETH(0, user, 1 ether); + emit ICSBondCore.BondDepositedStETH(0, user, 1 ether); bondCore.depositStETH(user, 0, 1 ether); uint256 shares = stETH.getSharesByPooledEth(1 ether); @@ -280,7 +281,7 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimableShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedStETH(0, user, claimedETH); + emit ICSBondCore.BondClaimedStETH(0, user, claimedETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimStETH(0, claimedETH, user); @@ -296,14 +297,14 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { function test_claimStETH_WhenClaimableIsZero() public { assertEq(bondCore.getBondShares(0), 0); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimStETH(0, 100, user); } function test_claimStETH_WhenToClaimIsZero() public { _deposit(2 ether); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimStETH(0, 0, user); } @@ -314,7 +315,7 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimableShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedStETH(0, user, claimedETH); + emit ICSBondCore.BondClaimedStETH(0, user, claimedETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimStETH(0, 2 ether, user); @@ -334,7 +335,7 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimableShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedStETH(0, user, claimedETH); + emit ICSBondCore.BondClaimedStETH(0, user, claimedETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimStETH(0, 1 ether, user); @@ -354,7 +355,7 @@ contract CSBondCoreStETHTest is CSBondCoreTestBase { uint256 claimedETH = stETH.getPooledEthByShares(claimedShares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedStETH(0, user, claimedETH); + emit ICSBondCore.BondClaimedStETH(0, user, claimedETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimStETH(0, 0.25 ether, user); @@ -375,7 +376,7 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { vm.stopPrank(); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondDepositedWstETH(0, user, wstETHAmount); + emit ICSBondCore.BondDepositedWstETH(0, user, wstETHAmount); bondCore.depositWstETH(user, 0, wstETHAmount); @@ -396,7 +397,7 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { ); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedWstETH(0, user, claimedWstETH); + emit ICSBondCore.BondClaimedWstETH(0, user, claimedWstETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimWstETH(0, claimableShares, user); @@ -409,14 +410,14 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { function test_claimWstETH_WhenClaimableIsZero() public { assertEq(bondCore.getBondShares(0), 0); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimWstETH(0, 100, user); } function test_claimWstETH_WhenToClaimIsZero() public { _deposit(2 ether); - vm.expectRevert(CSBondCore.NothingToClaim.selector); + vm.expectRevert(ICSBondCore.NothingToClaim.selector); bondCore.claimWstETH(0, 0, user); } @@ -429,7 +430,7 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { ); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedWstETH(0, user, claimedWstETH); + emit ICSBondCore.BondClaimedWstETH(0, user, claimedWstETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimWstETH(0, claimableShares + 1, user); @@ -448,7 +449,7 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { ); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedWstETH(0, user, claimedWstETH); + emit ICSBondCore.BondClaimedWstETH(0, user, claimedWstETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimWstETH(0, claimableShares, user); @@ -467,7 +468,7 @@ contract CSBondCoreWstETHTest is CSBondCoreTestBase { ); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondClaimedWstETH(0, user, claimedWstETH); + emit ICSBondCore.BondClaimedWstETH(0, user, claimedWstETH); uint256 bondSharesBefore = bondCore.getBondShares(0); bondCore.claimWstETH(0, claimedShares, user); @@ -485,7 +486,7 @@ contract CSBondCoreBurnTest is CSBondCoreTestBase { uint256 shares = stETH.getSharesByPooledEth(1 ether); uint256 burned = stETH.getPooledEthByShares(shares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondBurned(0, burned, burned); + emit ICSBondCore.BondBurned(0, burned, burned); uint256 bondSharesBefore = bondCore.getBondShares(0); vm.expectCall( @@ -513,7 +514,7 @@ contract CSBondCoreBurnTest is CSBondCoreTestBase { uint256 bondSharesBefore = bondCore.getBondShares(0); uint256 burnShares = stETH.getSharesByPooledEth(33 ether); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondBurned( + emit ICSBondCore.BondBurned( 0, stETH.getPooledEthByShares(burnShares), stETH.getPooledEthByShares(bondSharesBefore) @@ -544,7 +545,7 @@ contract CSBondCoreBurnTest is CSBondCoreTestBase { uint256 shares = stETH.getSharesByPooledEth(32 ether); uint256 burned = stETH.getPooledEthByShares(shares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondBurned(0, burned, burned); + emit ICSBondCore.BondBurned(0, burned, burned); vm.expectCall( locator.burner(), @@ -573,7 +574,7 @@ contract CSBondCoreChargeTest is CSBondCoreTestBase { uint256 shares = stETH.getSharesByPooledEth(1 ether); uint256 charged = stETH.getPooledEthByShares(shares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondCharged(0, charged, charged); + emit ICSBondCore.BondCharged(0, charged, charged); uint256 bondSharesBefore = bondCore.getBondShares(0); vm.expectCall( @@ -601,7 +602,7 @@ contract CSBondCoreChargeTest is CSBondCoreTestBase { uint256 bondSharesBefore = bondCore.getBondShares(0); uint256 chargeShares = stETH.getSharesByPooledEth(33 ether); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondCharged( + emit ICSBondCore.BondCharged( 0, stETH.getPooledEthByShares(chargeShares), stETH.getPooledEthByShares(bondSharesBefore) @@ -631,7 +632,7 @@ contract CSBondCoreChargeTest is CSBondCoreTestBase { uint256 shares = stETH.getSharesByPooledEth(32 ether); uint256 charged = stETH.getPooledEthByShares(shares); vm.expectEmit(true, true, true, true, address(bondCore)); - emit CSBondCore.BondCharged(0, charged, charged); + emit ICSBondCore.BondCharged(0, charged, charged); vm.expectCall( locator.lido(), diff --git a/test/CSBondCurve.t.sol b/test/CSBondCurve.t.sol index 88478b21..f6ad6300 100644 --- a/test/CSBondCurve.t.sol +++ b/test/CSBondCurve.t.sol @@ -49,7 +49,7 @@ contract CSBondCurveInitTest is Test { bondCurve.addBondCurve(_bondCurve); - vm.expectRevert(CSBondCurve.InvalidInitialisationCurveId.selector); + vm.expectRevert(ICSBondCurve.InvalidInitialisationCurveId.selector); bondCurve.initialize(_bondCurve); } } @@ -77,7 +77,7 @@ contract CSBondCurveTest is Test { } function test_getCurveInfo_RevertWhen_InvalidBondCurveId() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveId.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveId.selector); bondCurve.getCurveInfo(1337); } @@ -87,7 +87,7 @@ contract CSBondCurveTest is Test { _bondCurve[1] = 32 ether; vm.expectEmit(true, true, true, true, address(bondCurve)); - emit CSBondCurve.BondCurveAdded(_bondCurve); + emit ICSBondCurve.BondCurveAdded(_bondCurve); uint256 addedId = bondCurve.addBondCurve(_bondCurve); @@ -101,12 +101,12 @@ contract CSBondCurveTest is Test { } function test_addBondCurve_RevertWhen_LessThanMinBondCurveLength() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveLength.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveLength.selector); bondCurve.addBondCurve(new uint256[](0)); } function test_addBondCurve_RevertWhen_MoreThanMaxBondCurveLength() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveLength.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveLength.selector); bondCurve.addBondCurve(new uint256[](21)); } @@ -114,7 +114,7 @@ contract CSBondCurveTest is Test { uint256[] memory curvePoints = new uint256[](1); curvePoints[0] = 0 ether; - vm.expectRevert(CSBondCurve.InvalidBondCurveValues.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveValues.selector); bondCurve.addBondCurve(curvePoints); } @@ -123,7 +123,7 @@ contract CSBondCurveTest is Test { curvePoints[0] = 16 ether; curvePoints[1] = 8 ether; - vm.expectRevert(CSBondCurve.InvalidBondCurveValues.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveValues.selector); bondCurve.addBondCurve(curvePoints); } @@ -135,7 +135,7 @@ contract CSBondCurveTest is Test { uint256 toUpdateId = 0; vm.expectEmit(true, true, true, true, address(bondCurve)); - emit CSBondCurve.BondCurveUpdated(toUpdateId, _bondCurve); + emit ICSBondCurve.BondCurveUpdated(toUpdateId, _bondCurve); bondCurve.updateBondCurve(toUpdateId, _bondCurve); @@ -152,14 +152,14 @@ contract CSBondCurveTest is Test { function test_updateBondCurve_RevertWhen_LessThanMinBondCurveLength() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveLength.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveLength.selector); bondCurve.updateBondCurve(0, new uint256[](0)); } function test_updateBondCurve_RevertWhen_MoreThanMaxBondCurveLength() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveLength.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveLength.selector); bondCurve.updateBondCurve(0, new uint256[](21)); } @@ -167,7 +167,7 @@ contract CSBondCurveTest is Test { uint256[] memory curvePoints = new uint256[](1); curvePoints[0] = 0 ether; - vm.expectRevert(CSBondCurve.InvalidBondCurveValues.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveValues.selector); bondCurve.updateBondCurve(0, curvePoints); } @@ -178,7 +178,7 @@ contract CSBondCurveTest is Test { curvePoints[0] = 16 ether; curvePoints[1] = 8 ether; - vm.expectRevert(CSBondCurve.InvalidBondCurveValues.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveValues.selector); bondCurve.updateBondCurve(0, curvePoints); } @@ -186,7 +186,7 @@ contract CSBondCurveTest is Test { uint256[] memory _bondCurve = new uint256[](2); _bondCurve[0] = 16 ether; _bondCurve[1] = 32 ether; - vm.expectRevert(CSBondCurve.InvalidBondCurveId.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveId.selector); bondCurve.updateBondCurve(1, _bondCurve); } @@ -197,14 +197,14 @@ contract CSBondCurveTest is Test { uint256 addedId = bondCurve.addBondCurve(curvePoints); vm.expectEmit(true, true, true, true, address(bondCurve)); - emit CSBondCurve.BondCurveSet(noId, addedId); + emit ICSBondCurve.BondCurveSet(noId, addedId); bondCurve.setBondCurve(noId, addedId); assertEq(bondCurve.getBondCurveId(noId), addedId); } function test_setBondCurve_RevertWhen_NoExistingCurveId() public { - vm.expectRevert(CSBondCurve.InvalidBondCurveId.selector); + vm.expectRevert(ICSBondCurve.InvalidBondCurveId.selector); bondCurve.setBondCurve(0, 100500); } @@ -216,7 +216,7 @@ contract CSBondCurveTest is Test { bondCurve.setBondCurve(noId, addedId); vm.expectEmit(true, true, true, true, address(bondCurve)); - emit CSBondCurve.BondCurveSet(noId, 0); + emit ICSBondCurve.BondCurveSet(noId, 0); bondCurve.resetBondCurve(noId); assertEq(bondCurve.getBondCurveId(noId), 0); diff --git a/test/CSBondLock.t.sol b/test/CSBondLock.t.sol index 8c6914cf..269eb86f 100644 --- a/test/CSBondLock.t.sol +++ b/test/CSBondLock.t.sol @@ -8,6 +8,7 @@ import "forge-std/Test.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { CSBondLock } from "../src/abstract/CSBondLock.sol"; +import { ICSBondLock } from "../src/interfaces/ICSBondLock.sol"; import { Stub } from "./helpers/mocks/Stub.sol"; import { LidoMock } from "./helpers/mocks/LidoMock.sol"; import { WstETHMock } from "./helpers/mocks/WstETHMock.sol"; @@ -50,7 +51,7 @@ contract CSBondLockTest is Test { uint256 period = 4 weeks; vm.expectEmit(true, true, true, true, address(bondLock)); - emit CSBondLock.BondLockPeriodChanged(period); + emit ICSBondLock.BondLockPeriodChanged(period); bondLock.setBondLockPeriod(period); @@ -60,13 +61,13 @@ contract CSBondLockTest is Test { function test_setBondLockPeriod_RevertWhen_LessThanMin() public { uint256 min = bondLock.MIN_BOND_LOCK_PERIOD(); - vm.expectRevert(CSBondLock.InvalidBondLockPeriod.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockPeriod.selector); bondLock.setBondLockPeriod(min - 1 seconds); } function test_setBondLockPeriod_RevertWhen_GreaterThanMax() public { uint256 max = bondLock.MAX_BOND_LOCK_PERIOD(); - vm.expectRevert(CSBondLock.InvalidBondLockPeriod.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockPeriod.selector); bondLock.setBondLockPeriod(max + 1 seconds); } @@ -110,7 +111,7 @@ contract CSBondLockTest is Test { uint256 until = block.timestamp + period; vm.expectEmit(true, true, true, true, address(bondLock)); - emit CSBondLock.BondLockChanged(noId, amount, until); + emit ICSBondLock.BondLockChanged(noId, amount, until); bondLock.lock(noId, amount); @@ -167,7 +168,7 @@ contract CSBondLockTest is Test { } function test_lock_RevertWhen_ZeroAmount() public { - vm.expectRevert(CSBondLock.InvalidBondLockAmount.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockAmount.selector); bondLock.lock(0, 0); } @@ -190,7 +191,7 @@ contract CSBondLockTest is Test { bondLock.lock(noId, amount); vm.expectEmit(true, true, true, true, address(bondLock)); - emit CSBondLock.BondLockRemoved(noId); + emit ICSBondLock.BondLockRemoved(noId); bondLock.reduceAmount(noId, amount); @@ -213,7 +214,7 @@ contract CSBondLockTest is Test { vm.warp(block.timestamp + 1 seconds); vm.expectEmit(true, true, true, true, address(bondLock)); - emit CSBondLock.BondLockChanged(noId, rest, periodWhenLock); + emit ICSBondLock.BondLockChanged(noId, rest, periodWhenLock); bondLock.reduceAmount(noId, toRelease); @@ -223,7 +224,7 @@ contract CSBondLockTest is Test { } function test_reduceAmount_RevertWhen_ZeroAmount() public { - vm.expectRevert(CSBondLock.InvalidBondLockAmount.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockAmount.selector); bondLock.reduceAmount(0, 0); } @@ -233,7 +234,7 @@ contract CSBondLockTest is Test { bondLock.lock(noId, amount); - vm.expectRevert(CSBondLock.InvalidBondLockAmount.selector); + vm.expectRevert(ICSBondLock.InvalidBondLockAmount.selector); bondLock.reduceAmount(noId, amount + 1 ether); } @@ -244,7 +245,7 @@ contract CSBondLockTest is Test { bondLock.lock(noId, amount); vm.expectEmit(true, true, true, true, address(bondLock)); - emit CSBondLock.BondLockRemoved(noId); + emit ICSBondLock.BondLockRemoved(noId); bondLock.remove(noId); diff --git a/test/CSEarlyAdoption.t.sol b/test/CSEarlyAdoption.t.sol index 92865857..458103f8 100644 --- a/test/CSEarlyAdoption.t.sol +++ b/test/CSEarlyAdoption.t.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.24; import "forge-std/Test.sol"; -import "../src/CSEarlyAdoption.sol"; +import { CSEarlyAdoption } from "../src/CSEarlyAdoption.sol"; +import { ICSEarlyAdoption } from "../src/interfaces/ICSEarlyAdoption.sol"; import { Utilities } from "./helpers/Utilities.sol"; import "./helpers/MerkleTree.sol"; @@ -36,17 +37,17 @@ contract CSEarlyAdoptionConstructorTest is Test, Utilities { } function test_constructor_RevertWhen_InvalidTreeRoot() public { - vm.expectRevert(CSEarlyAdoption.InvalidTreeRoot.selector); + vm.expectRevert(ICSEarlyAdoption.InvalidTreeRoot.selector); new CSEarlyAdoption(bytes32(0), curveId, csm); } function test_constructor_RevertWhen_InvalidCurveId() public { - vm.expectRevert(CSEarlyAdoption.InvalidCurveId.selector); + vm.expectRevert(ICSEarlyAdoption.InvalidCurveId.selector); new CSEarlyAdoption(root, 0, csm); } function test_constructor_RevertWhen_ZeroModuleAddress() public { - vm.expectRevert(CSEarlyAdoption.ZeroModuleAddress.selector); + vm.expectRevert(ICSEarlyAdoption.ZeroModuleAddress.selector); new CSEarlyAdoption(root, curveId, address(0)); } } @@ -85,7 +86,7 @@ contract CSEarlyAdoptionTest is Test, Utilities { vm.prank(csm); vm.expectEmit(true, true, true, true, address(earlyAdoption)); - emit CSEarlyAdoption.Consumed(nodeOperator); + emit ICSEarlyAdoption.Consumed(nodeOperator); earlyAdoption.consume(nodeOperator, proof); } @@ -93,7 +94,7 @@ contract CSEarlyAdoptionTest is Test, Utilities { bytes32[] memory proof = merkleTree.getProof(0); vm.prank(stranger); - vm.expectRevert(CSEarlyAdoption.SenderIsNotModule.selector); + vm.expectRevert(ICSEarlyAdoption.SenderIsNotModule.selector); earlyAdoption.consume(nodeOperator, proof); } @@ -103,7 +104,7 @@ contract CSEarlyAdoptionTest is Test, Utilities { vm.startPrank(csm); earlyAdoption.consume(nodeOperator, proof); - vm.expectRevert(CSEarlyAdoption.AlreadyConsumed.selector); + vm.expectRevert(ICSEarlyAdoption.AlreadyConsumed.selector); earlyAdoption.consume(nodeOperator, proof); } @@ -111,7 +112,7 @@ contract CSEarlyAdoptionTest is Test, Utilities { bytes32[] memory proof = merkleTree.getProof(0); vm.prank(csm); - vm.expectRevert(CSEarlyAdoption.InvalidProof.selector); + vm.expectRevert(ICSEarlyAdoption.InvalidProof.selector); earlyAdoption.consume(stranger, proof); } @@ -120,7 +121,7 @@ contract CSEarlyAdoptionTest is Test, Utilities { proof[0] = bytes32(randomBytes(32)); vm.prank(csm); - vm.expectRevert(CSEarlyAdoption.InvalidProof.selector); + vm.expectRevert(ICSEarlyAdoption.InvalidProof.selector); earlyAdoption.consume(nodeOperator, proof); } diff --git a/test/CSFeeDistributor.t.sol b/test/CSFeeDistributor.t.sol index fdc8642d..79037a95 100644 --- a/test/CSFeeDistributor.t.sol +++ b/test/CSFeeDistributor.t.sol @@ -10,6 +10,7 @@ import { IAssetRecovererLib } from "../src/lib/AssetRecovererLib.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { IStETH } from "../src/interfaces/IStETH.sol"; +import { ICSFeeDistributor } from "../src/interfaces/ICSFeeDistributor.sol"; import { Fixtures } from "./helpers/Fixtures.sol"; import { MerkleTree } from "./helpers/MerkleTree.sol"; @@ -79,17 +80,17 @@ contract CSFeeDistributorConstructorTest is CSFeeDistributorTestBase { } function test_initialize_RevertWhen_ZeroAccountingAddress() public { - vm.expectRevert(CSFeeDistributor.ZeroAccountingAddress.selector); + vm.expectRevert(ICSFeeDistributor.ZeroAccountingAddress.selector); new CSFeeDistributor(address(stETH), address(0), oracle); } function test_initialize_RevertWhen_ZeroStEthAddress() public { - vm.expectRevert(CSFeeDistributor.ZeroStEthAddress.selector); + vm.expectRevert(ICSFeeDistributor.ZeroStEthAddress.selector); new CSFeeDistributor(address(0), address(accounting), oracle); } function test_initialize_RevertWhen_ZeroOracleAddress() public { - vm.expectRevert(CSFeeDistributor.ZeroOracleAddress.selector); + vm.expectRevert(ICSFeeDistributor.ZeroOracleAddress.selector); new CSFeeDistributor(address(stETH), address(accounting), address(0)); } } @@ -113,7 +114,7 @@ contract CSFeeDistributorInitTest is CSFeeDistributorTestBase { function test_initialize_RevertWhen_zeroAdmin() public { _enableInitializers(address(feeDistributor)); - vm.expectRevert(CSFeeDistributor.ZeroAdminAddress.selector); + vm.expectRevert(ICSFeeDistributor.ZeroAdminAddress.selector); feeDistributor.initialize(address(0)); } } @@ -160,7 +161,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { ); vm.expectEmit(true, true, true, true, address(feeDistributor)); - emit CSFeeDistributor.FeeDistributed(nodeOperatorId, shares); + emit ICSFeeDistributor.FeeDistributed(nodeOperatorId, shares); vm.prank(address(accounting)); feeDistributor.distributeFees({ @@ -245,7 +246,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { .sig("treeRoot()") .checked_write(feeDistributor.hashLeaf(noId, shares)); - vm.expectRevert(CSFeeDistributor.InvalidProof.selector); + vm.expectRevert(ICSFeeDistributor.InvalidProof.selector); feeDistributor.getFeesToDistribute({ proof: new bytes32[](0), nodeOperatorId: noId, @@ -265,7 +266,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { public assertInvariants { - vm.expectRevert(CSFeeDistributor.NotAccounting.selector); + vm.expectRevert(ICSFeeDistributor.NotAccounting.selector); feeDistributor.distributeFees({ proof: new bytes32[](1), @@ -278,7 +279,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { public assertInvariants { - vm.expectRevert(CSFeeDistributor.InvalidProof.selector); + vm.expectRevert(ICSFeeDistributor.InvalidProof.selector); vm.prank(address(accounting)); feeDistributor.distributeFees({ @@ -313,7 +314,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { .with_key(nodeOperatorId) .checked_write(shares + 99); - vm.expectRevert(CSFeeDistributor.FeeSharesDecrease.selector); + vm.expectRevert(ICSFeeDistributor.FeeSharesDecrease.selector); vm.prank(address(accounting)); feeDistributor.distributeFees({ proof: proof, @@ -341,7 +342,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { shares - 1 ); - vm.expectRevert(CSFeeDistributor.NotEnoughShares.selector); + vm.expectRevert(ICSFeeDistributor.NotEnoughShares.selector); vm.prank(address(accounting)); feeDistributor.distributeFees({ proof: proof, @@ -412,14 +413,14 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { bytes32 treeRoot = someBytes32(); vm.expectEmit(true, true, true, true, address(feeDistributor)); - emit CSFeeDistributor.DistributionDataUpdated( + emit ICSFeeDistributor.DistributionDataUpdated( shares, treeRoot, treeCid ); vm.expectEmit(true, true, true, true, address(feeDistributor)); - emit CSFeeDistributor.DistributionLogUpdated(logCid); + emit ICSFeeDistributor.DistributionLogUpdated(logCid); vm.prank(oracle); feeDistributor.processOracleReport(treeRoot, treeCid, logCid, shares); @@ -471,7 +472,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { bytes32 root = tree.root(); - vm.expectRevert(CSFeeDistributor.InvalidShares.selector); + vm.expectRevert(ICSFeeDistributor.InvalidShares.selector); vm.prank(oracle); feeDistributor.processOracleReport( root, @@ -490,7 +491,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { stETH.mintShares(address(feeDistributor), shares); - vm.expectRevert(CSFeeDistributor.InvalidTreeRoot.selector); + vm.expectRevert(ICSFeeDistributor.InvalidTreeRoot.selector); vm.prank(oracle); feeDistributor.processOracleReport( bytes32(0), @@ -510,7 +511,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { stETH.mintShares(address(feeDistributor), shares); bytes32 root = feeDistributor.treeRoot(); - vm.expectRevert(CSFeeDistributor.InvalidTreeRoot.selector); + vm.expectRevert(ICSFeeDistributor.InvalidTreeRoot.selector); vm.prank(oracle); feeDistributor.processOracleReport( root, @@ -529,7 +530,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { stETH.mintShares(address(feeDistributor), shares); - vm.expectRevert(CSFeeDistributor.InvalidTreeCID.selector); + vm.expectRevert(ICSFeeDistributor.InvalidTreeCID.selector); vm.prank(oracle); feeDistributor.processOracleReport( someBytes32(), @@ -549,7 +550,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { stETH.mintShares(address(feeDistributor), shares); string memory lastTreeCid = feeDistributor.treeCid(); - vm.expectRevert(CSFeeDistributor.InvalidTreeCID.selector); + vm.expectRevert(ICSFeeDistributor.InvalidTreeCID.selector); vm.prank(oracle); feeDistributor.processOracleReport( someBytes32(), @@ -560,7 +561,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { } function test_processOracleReport_RevertWhen_ZeroLogCid() public { - vm.expectRevert(CSFeeDistributor.InvalidLogCID.selector); + vm.expectRevert(ICSFeeDistributor.InvalidLogCID.selector); vm.prank(oracle); feeDistributor.processOracleReport(someBytes32(), someCIDv0(), "", 0); } @@ -571,7 +572,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { string memory lastLogCid = feeDistributor.logCid(); - vm.expectRevert(CSFeeDistributor.InvalidLogCID.selector); + vm.expectRevert(ICSFeeDistributor.InvalidLogCID.selector); vm.prank(oracle); feeDistributor.processOracleReport( someBytes32(), @@ -588,7 +589,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { uint256 shares = 1_000_000; _makeInitialReport(shares); - vm.expectRevert(CSFeeDistributor.InvalidShares.selector); + vm.expectRevert(ICSFeeDistributor.InvalidShares.selector); vm.prank(oracle); feeDistributor.processOracleReport( someBytes32(), @@ -602,7 +603,7 @@ contract CSFeeDistributorTest is CSFeeDistributorTestBase { public assertInvariants { - vm.expectRevert(CSFeeDistributor.NotOracle.selector); + vm.expectRevert(ICSFeeDistributor.NotOracle.selector); vm.prank(stranger); feeDistributor.processOracleReport( someBytes32(), diff --git a/test/CSFeeOracle.t.sol b/test/CSFeeOracle.t.sol index 92d45ab3..e6689f52 100644 --- a/test/CSFeeOracle.t.sol +++ b/test/CSFeeOracle.t.sol @@ -12,6 +12,7 @@ import { PausableUntil } from "../src/lib/utils/PausableUntil.sol"; import { BaseOracle } from "../src/lib/base-oracle/BaseOracle.sol"; import { DistributorMock } from "./helpers/mocks/DistributorMock.sol"; import { CSFeeOracle } from "../src/CSFeeOracle.sol"; +import { ICSFeeOracle } from "../src/interfaces/ICSFeeOracle.sol"; import { Utilities } from "./helpers/Utilities.sol"; import { Stub } from "./helpers/mocks/Stub.sol"; @@ -81,7 +82,7 @@ contract CSFeeOracleTest is Test, Utilities { // INITIAL_EPOCH is far above the lastProcessingRefSlot's epoch assertNotEq(startSlot, refSlot); - CSFeeOracle.ReportData memory data = CSFeeOracle.ReportData({ + ICSFeeOracle.ReportData memory data = ICSFeeOracle.ReportData({ consensusVersion: oracle.getConsensusVersion(), refSlot: refSlot, treeRoot: keccak256("root"), @@ -130,7 +131,7 @@ contract CSFeeOracleTest is Test, Utilities { // INITIAL_EPOCH is far above the lastProcessingRefSlot's epoch assertNotEq(startSlot, refSlot); - CSFeeOracle.ReportData memory data = CSFeeOracle.ReportData({ + ICSFeeOracle.ReportData memory data = ICSFeeOracle.ReportData({ consensusVersion: oracle.getConsensusVersion(), refSlot: refSlot, treeRoot: keccak256("root"), @@ -142,7 +143,7 @@ contract CSFeeOracleTest is Test, Utilities { bytes32 reportHash = keccak256(abi.encode(data)); _reachConsensus(refSlot, reportHash); - vm.expectRevert(CSFeeOracle.SenderNotAllowed.selector); + vm.expectRevert(ICSFeeOracle.SenderNotAllowed.selector); vm.prank(stranger); oracle.submitReportData({ data: data, contractVersion: 1 }); } @@ -167,7 +168,7 @@ contract CSFeeOracleTest is Test, Utilities { // INITIAL_EPOCH is far above the lastProcessingRefSlot's epoch assertNotEq(startSlot, refSlot); - CSFeeOracle.ReportData memory data = CSFeeOracle.ReportData({ + ICSFeeOracle.ReportData memory data = ICSFeeOracle.ReportData({ consensusVersion: oracle.getConsensusVersion(), refSlot: refSlot, treeRoot: keccak256("root"), @@ -201,7 +202,7 @@ contract CSFeeOracleTest is Test, Utilities { // INITIAL_EPOCH is far above the lastProcessingRefSlot's epoch assertNotEq(startSlot, refSlot); - CSFeeOracle.ReportData memory data = CSFeeOracle.ReportData({ + ICSFeeOracle.ReportData memory data = ICSFeeOracle.ReportData({ consensusVersion: oracle.getConsensusVersion(), refSlot: refSlot, treeRoot: keccak256("root"), @@ -237,7 +238,7 @@ contract CSFeeOracleTest is Test, Utilities { // INITIAL_EPOCH is far above the lastProcessingRefSlot's epoch assertNotEq(startSlot, refSlot); - CSFeeOracle.ReportData memory data = CSFeeOracle.ReportData({ + ICSFeeOracle.ReportData memory data = ICSFeeOracle.ReportData({ consensusVersion: oracle.getConsensusVersion(), refSlot: refSlot, treeRoot: keccak256("root"), @@ -331,7 +332,7 @@ contract CSFeeOracleTest is Test, Utilities { address(0), address(0) ); - vm.expectRevert(CSFeeOracle.ZeroAdminAddress.selector); + vm.expectRevert(ICSFeeOracle.ZeroAdminAddress.selector); oracle.initialize( address(0), address(distributor), @@ -352,7 +353,7 @@ contract CSFeeOracleTest is Test, Utilities { address newDistributor = nextAddress(); vm.expectEmit(true, true, true, true, address(oracle)); - emit CSFeeOracle.FeeDistributorContractSet(newDistributor); + emit ICSFeeOracle.FeeDistributorContractSet(newDistributor); vm.prank(ORACLE_ADMIN); oracle.setFeeDistributorContract(newDistributor); @@ -369,7 +370,7 @@ contract CSFeeOracleTest is Test, Utilities { _setInitialEpoch(); } - vm.expectRevert(CSFeeOracle.ZeroFeeDistributorAddress.selector); + vm.expectRevert(ICSFeeOracle.ZeroFeeDistributorAddress.selector); vm.prank(ORACLE_ADMIN); oracle.setFeeDistributorContract(address(0)); } @@ -385,7 +386,7 @@ contract CSFeeOracleTest is Test, Utilities { uint256 newThreshold = 4200; vm.expectEmit(true, true, true, true, address(oracle)); - emit CSFeeOracle.PerfLeewaySet(newThreshold); + emit ICSFeeOracle.PerfLeewaySet(newThreshold); vm.prank(ORACLE_ADMIN); oracle.setPerformanceLeeway(newThreshold); @@ -400,7 +401,7 @@ contract CSFeeOracleTest is Test, Utilities { _setInitialEpoch(); } - vm.expectRevert(CSFeeOracle.InvalidPerfLeeway.selector); + vm.expectRevert(ICSFeeOracle.InvalidPerfLeeway.selector); vm.prank(ORACLE_ADMIN); oracle.setPerformanceLeeway(99999); } diff --git a/test/CSModule.t.sol b/test/CSModule.t.sol index 4e2f1c6b..dd3fa174 100644 --- a/test/CSModule.t.sol +++ b/test/CSModule.t.sol @@ -571,7 +571,7 @@ contract CsmInitialize is CSMCommon { } function test_constructor_RevertWhen_ZeroLocator() public { - vm.expectRevert(CSModule.ZeroLocatorAddress.selector); + vm.expectRevert(ICSModule.ZeroLocatorAddress.selector); new CSModule({ moduleType: "community-staking-module", minSlashingPenaltyQuotient: 32, @@ -639,7 +639,7 @@ contract CsmInitialize is CSMCommon { }); _enableInitializers(address(csm)); - vm.expectRevert(CSModule.ZeroAccountingAddress.selector); + vm.expectRevert(ICSModule.ZeroAccountingAddress.selector); csm.initialize({ _accounting: address(0), _earlyAdoption: address(1337), @@ -659,7 +659,7 @@ contract CsmInitialize is CSMCommon { }); _enableInitializers(address(csm)); - vm.expectRevert(CSModule.ZeroAdminAddress.selector); + vm.expectRevert(ICSModule.ZeroAdminAddress.selector); csm.initialize({ _accounting: address(154), _earlyAdoption: address(1337), @@ -866,11 +866,11 @@ contract CSMAddNodeOperatorETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(0, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } vm.prank(nodeOperator); @@ -904,11 +904,11 @@ contract CSMAddNodeOperatorETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(0, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } vm.prank(nodeOperator); @@ -942,7 +942,7 @@ contract CSMAddNodeOperatorETH is CSMCommon { address reward = address(42); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, manager, reward); + emit ICSModule.NodeOperatorAdded(0, manager, reward); vm.prank(nodeOperator); csm.addNodeOperatorETH{ value: BOND_SIZE }( keysCount, @@ -971,9 +971,9 @@ contract CSMAddNodeOperatorETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ReferrerSet(0, address(154)); + emit ICSModule.ReferrerSet(0, address(154)); } vm.prank(nodeOperator); @@ -1001,7 +1001,7 @@ contract CSMAddNodeOperatorETH is CSMCommon { ); vm.deal(nodeOperator, BOND_SIZE - 1); - vm.expectRevert(CSModule.InvalidAmount.selector); + vm.expectRevert(ICSModule.InvalidAmount.selector); vm.prank(nodeOperator); csm.addNodeOperatorETH{ value: BOND_SIZE - 1 ether }( keysCount, @@ -1032,11 +1032,11 @@ contract CSMAddNodeOperatorStETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(0, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } vm.prank(nodeOperator); @@ -1079,7 +1079,7 @@ contract CSMAddNodeOperatorStETH is CSMCommon { address reward = address(42); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, manager, reward); + emit ICSModule.NodeOperatorAdded(0, manager, reward); vm.prank(nodeOperator); csm.addNodeOperatorStETH( 1, @@ -1117,9 +1117,9 @@ contract CSMAddNodeOperatorStETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ReferrerSet(0, address(154)); + emit ICSModule.ReferrerSet(0, address(154)); } vm.prank(nodeOperator); @@ -1157,7 +1157,7 @@ contract CSMAddNodeOperatorStETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(stETH)); emit StETHMock.Approval( nodeOperator, @@ -1165,7 +1165,7 @@ contract CSMAddNodeOperatorStETH is CSMCommon { BOND_SIZE ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } vm.prank(nodeOperator); @@ -1209,11 +1209,11 @@ contract CSMAddNodeOperatorWstETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(0, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } csm.addNodeOperatorWstETH( @@ -1257,7 +1257,7 @@ contract CSMAddNodeOperatorWstETH is CSMCommon { address reward = address(42); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, manager, reward); + emit ICSModule.NodeOperatorAdded(0, manager, reward); csm.addNodeOperatorWstETH( keysCount, keys, @@ -1296,9 +1296,9 @@ contract CSMAddNodeOperatorWstETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ReferrerSet(0, address(154)); + emit ICSModule.ReferrerSet(0, address(154)); } csm.addNodeOperatorWstETH( @@ -1336,7 +1336,7 @@ contract CSMAddNodeOperatorWstETH is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); vm.expectEmit(true, true, true, true, address(wstETH)); emit WstETHMock.Approval( nodeOperator, @@ -1344,7 +1344,7 @@ contract CSMAddNodeOperatorWstETH is CSMCommon { wstETHAmount ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(0, 1); + emit ICSModule.TotalSigningKeysCountChanged(0, 1); } csm.addNodeOperatorWstETH( @@ -1391,7 +1391,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.addValidatorKeysWstETH( noId, @@ -1434,7 +1434,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.addValidatorKeysWstETH( noId, @@ -1470,7 +1470,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.addValidatorKeysStETH( noId, @@ -1512,7 +1512,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } vm.prank(nodeOperator); csm.addValidatorKeysStETH( @@ -1549,7 +1549,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.addValidatorKeysETH{ value: required }(noId, 1, keys, signatures); assertEq(csm.getNonce(), nonce + 1); @@ -1573,7 +1573,7 @@ contract CSMAddValidatorKeys is CSMCommon { vm.expectEmit(true, true, true, true, address(csm)); emit IStakingModule.SigningKeyAdded(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.addValidatorKeysETH{ value: deposit }(noId, 1, keys, signatures); assertEq(csm.getNonce(), nonce + 1); @@ -1590,7 +1590,7 @@ contract CSMAddValidatorKeys is CSMCommon { uint256 required = accounting.getRequiredBondForNextKeys(0, 1); vm.deal(nodeOperator, required - 1 ether); - vm.expectRevert(CSModule.InvalidAmount.selector); + vm.expectRevert(ICSModule.InvalidAmount.selector); vm.prank(nodeOperator); csm.addValidatorKeysETH{ value: required - 1 ether }( noId, @@ -2501,7 +2501,7 @@ contract CSMObtainDepositData is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositableSigningKeysCountChanged(0, 0); + emit ICSModule.DepositableSigningKeysCountChanged(0, 0); (bytes memory obtainedKeys, bytes memory obtainedSignatures) = csm .obtainDepositData(1, ""); assertEq(obtainedKeys, keys); @@ -2517,11 +2517,11 @@ contract CSMObtainDepositData is CSMCommon { uint256 thirdId = createNodeOperator(1); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositableSigningKeysCountChanged(firstId, 0); + emit ICSModule.DepositableSigningKeysCountChanged(firstId, 0); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositableSigningKeysCountChanged(secondId, 0); + emit ICSModule.DepositableSigningKeysCountChanged(secondId, 0); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositableSigningKeysCountChanged(thirdId, 0); + emit ICSModule.DepositableSigningKeysCountChanged(thirdId, 0); csm.obtainDepositData(6, ""); } @@ -2538,7 +2538,7 @@ contract CSMObtainDepositData is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositedSigningKeysCountChanged(noId, keysCount); + emit ICSModule.DepositedSigningKeysCountChanged(noId, keysCount); (bytes memory depositedKeys, bytes memory depositedSignatures) = csm .obtainDepositData(keysCount, ""); @@ -2591,7 +2591,7 @@ contract CSMObtainDepositData is CSMCommon { uint256 noId = createNodeOperator(7); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.DepositedSigningKeysCountChanged(noId, 3); + emit ICSModule.DepositedSigningKeysCountChanged(noId, 3); csm.obtainDepositData(3, ""); NodeOperator memory no = csm.getNodeOperator(noId); @@ -2604,7 +2604,7 @@ contract CSMObtainDepositData is CSMCommon { public assertInvariants { - vm.expectRevert(CSModule.NotEnoughKeys.selector); + vm.expectRevert(ICSModule.NotEnoughKeys.selector); csm.obtainDepositData(1, ""); } @@ -2749,7 +2749,7 @@ contract CSMClaimRewards is CSMCommon { assertInvariants { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SenderIsNotEligible.selector); + vm.expectRevert(ICSModule.SenderIsNotEligible.selector); csm.claimRewardsStETH(noId, UINT256_MAX, 0, new bytes32[](0)); } @@ -2838,7 +2838,7 @@ contract CSMClaimRewards is CSMCommon { assertInvariants { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SenderIsNotEligible.selector); + vm.expectRevert(ICSModule.SenderIsNotEligible.selector); csm.claimRewardsWstETH(noId, UINT256_MAX, 0, new bytes32[](0)); } @@ -2910,7 +2910,7 @@ contract CSMClaimRewards is CSMCommon { assertInvariants { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SenderIsNotEligible.selector); + vm.expectRevert(ICSModule.SenderIsNotEligible.selector); csm.claimRewardsUnstETH(noId, UINT256_MAX, 0, new bytes32[](0)); } } @@ -3341,7 +3341,7 @@ contract CsmChangeNodeOperatorRewardAddress is CSMCommon { contract CsmOnWithdrawalCredentialsChanged is CSMCommon { function test_onWithdrawalCredentialsChanged() public assertInvariants { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.KeyRemovalChargeSet(0 ether); + emit ICSModule.KeyRemovalChargeSet(0 ether); csm.onWithdrawalCredentialsChanged(); assertEq(csm.keyRemovalCharge(), 0 ether); @@ -3354,7 +3354,7 @@ contract CsmVetKeys is CSMCommon { uint256 keys = 7; vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged(noId, keys); + emit ICSModule.VettedSigningKeysCountChanged(noId, keys); vm.expectEmit(true, true, true, true, address(csm)); emit IQueueLib.BatchEnqueued(noId, keys); createNodeOperator(keys); @@ -3368,7 +3368,7 @@ contract CsmVetKeys is CSMCommon { uint256 noId = createNodeOperator(2); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged(noId, 3); + emit ICSModule.VettedSigningKeysCountChanged(noId, 3); vm.expectEmit(true, true, true, true, address(csm)); emit IQueueLib.BatchEnqueued(noId, 1); uploadMoreKeys(noId, 1); @@ -3401,7 +3401,7 @@ contract CsmVetKeys is CSMCommon { assertEq(no.totalVettedKeys, 4); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged(noId, 5); // 7 - 2 removed at the next step. + emit ICSModule.VettedSigningKeysCountChanged(noId, 5); // 7 - 2 removed at the next step. vm.prank(nodeOperator); csm.removeKeys(noId, 4, 2); // Remove keys 4 and 5. @@ -3613,9 +3613,9 @@ contract CsmDecreaseVettedSigningKeysCount is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged(noId, 1); + emit ICSModule.VettedSigningKeysCountChanged(noId, 1); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountDecreased(noId); + emit ICSModule.VettedSigningKeysCountDecreased(noId); unvetKeys({ noId: noId, to: 1 }); NodeOperator memory no = csm.getNodeOperator(noId); @@ -3635,17 +3635,17 @@ contract CsmDecreaseVettedSigningKeysCount is CSMCommon { uint256 newVettedSecond = 3; vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged(firstNoId, newVettedFirst); + emit ICSModule.VettedSigningKeysCountChanged(firstNoId, newVettedFirst); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountDecreased(firstNoId); + emit ICSModule.VettedSigningKeysCountDecreased(firstNoId); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountChanged( + emit ICSModule.VettedSigningKeysCountChanged( secondNoId, newVettedSecond ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.VettedSigningKeysCountDecreased(secondNoId); + emit ICSModule.VettedSigningKeysCountDecreased(secondNoId); csm.decreaseVettedSigningKeysCount( bytes.concat(bytes8(uint64(firstNoId)), bytes8(uint64(secondNoId))), @@ -3689,7 +3689,7 @@ contract CsmDecreaseVettedSigningKeysCount is CSMCommon { uint256 noId = createNodeOperator(10); uint256 newVetted = 10; - vm.expectRevert(CSModule.InvalidVetKeysPointer.selector); + vm.expectRevert(ICSModule.InvalidVetKeysPointer.selector); unvetKeys(noId, newVetted); } @@ -3699,7 +3699,7 @@ contract CsmDecreaseVettedSigningKeysCount is CSMCommon { uint256 noId = createNodeOperator(10); uint256 newVetted = 15; - vm.expectRevert(CSModule.InvalidVetKeysPointer.selector); + vm.expectRevert(ICSModule.InvalidVetKeysPointer.selector); unvetKeys(noId, newVetted); } @@ -3710,7 +3710,7 @@ contract CsmDecreaseVettedSigningKeysCount is CSMCommon { csm.obtainDepositData(5, ""); uint256 newVetted = 4; - vm.expectRevert(CSModule.InvalidVetKeysPointer.selector); + vm.expectRevert(ICSModule.InvalidVetKeysPointer.selector); unvetKeys(noId, newVetted); } @@ -3759,7 +3759,7 @@ contract CsmGetSigningKeys is CSMCommon { signatures: randomBytes(96) }); - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.getSigningKeys({ nodeOperatorId: noId, startIndex: 0, @@ -3800,7 +3800,7 @@ contract CsmGetSigningKeys is CSMCommon { assertInvariants brutalizeMemory { - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.getSigningKeys(0, 0, 1); } } @@ -3847,7 +3847,7 @@ contract CsmGetSigningKeysWithSignatures is CSMCommon { signatures: signatures }); - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.getSigningKeysWithSignatures({ nodeOperatorId: noId, startIndex: 0, @@ -3900,7 +3900,7 @@ contract CsmGetSigningKeysWithSignatures is CSMCommon { assertInvariants brutalizeMemory { - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.getSigningKeysWithSignatures(0, 0, 1); } } @@ -3928,7 +3928,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key0); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 4); + emit ICSModule.TotalSigningKeysCountChanged(noId, 4); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 0, keysCount: 1 }); /* @@ -3944,7 +3944,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key1); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 3); + emit ICSModule.TotalSigningKeysCountChanged(noId, 3); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 1, keysCount: 1 }); /* @@ -3959,7 +3959,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key2); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 2); + emit ICSModule.TotalSigningKeysCountChanged(noId, 2); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 2, keysCount: 1 }); /* @@ -4000,7 +4000,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key0); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 3); + emit ICSModule.TotalSigningKeysCountChanged(noId, 3); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 0, keysCount: 2 }); @@ -4042,7 +4042,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key1); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 3); + emit ICSModule.TotalSigningKeysCountChanged(noId, 3); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 1, keysCount: 2 }); @@ -4084,7 +4084,7 @@ contract CsmRemoveKeys is CSMCommon { emit IStakingModule.SigningKeyRemoved(noId, key3); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 3); + emit ICSModule.TotalSigningKeysCountChanged(noId, 3); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 3, keysCount: 2 }); @@ -4114,7 +4114,7 @@ contract CsmRemoveKeys is CSMCommon { { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TotalSigningKeysCountChanged(noId, 0); + emit ICSModule.TotalSigningKeysCountChanged(noId, 0); } csm.removeKeys({ nodeOperatorId: noId, startIndex: 0, keysCount: 5 }); @@ -4156,7 +4156,7 @@ contract CSMRemoveKeysChargeFee is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.KeyRemovalChargeApplied(noId); + emit ICSModule.KeyRemovalChargeApplied(noId); vm.prank(nodeOperator); csm.removeKeys(noId, 1, 2); @@ -4180,7 +4180,7 @@ contract CSMRemoveKeysChargeFee is CSMCommon { for (uint256 i = 0; i < entries.length; i++) { assertNotEq( entries[i].topics[0], - CSModule.KeyRemovalChargeApplied.selector + ICSModule.KeyRemovalChargeApplied.selector ); } } @@ -4219,7 +4219,7 @@ contract CSMRemoveKeysReverts is CSMCommon { csm.obtainDepositData(1, ""); - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.removeKeys({ nodeOperatorId: noId, startIndex: 0, keysCount: 1 }); } @@ -4230,7 +4230,7 @@ contract CSMRemoveKeysReverts is CSMCommon { }); vm.prank(stranger); - vm.expectRevert(CSModule.SenderIsNotEligible.selector); + vm.expectRevert(ICSModule.SenderIsNotEligible.selector); csm.removeKeys({ nodeOperatorId: noId, startIndex: 0, keysCount: 1 }); } @@ -4928,7 +4928,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 1, 1); + emit ICSModule.TargetValidatorsCountChanged(noId, 1, 1); csm.updateTargetValidatorsLimits(noId, 1, 1); assertEq(csm.getNonce(), nonce + 1); } @@ -4940,7 +4940,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { uint256 noId = createNodeOperator(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 1, 1); + emit ICSModule.TargetValidatorsCountChanged(noId, 1, 1); csm.updateTargetValidatorsLimits(noId, 1, 1); vm.recordLogs(); @@ -4959,7 +4959,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { { uint256 noId = createNodeOperator(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 1, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 1, 0); csm.updateTargetValidatorsLimits(noId, 1, 0); } @@ -4971,7 +4971,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 2, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 0, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 0, 0); csm.updateTargetValidatorsLimits(noId, 0, 0); vm.recordLogs(); @@ -4990,7 +4990,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 0, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 1, 10); + emit ICSModule.TargetValidatorsCountChanged(noId, 1, 10); csm.updateTargetValidatorsLimits(noId, 1, 10); } @@ -5002,7 +5002,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 0, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 2, 10); + emit ICSModule.TargetValidatorsCountChanged(noId, 2, 10); csm.updateTargetValidatorsLimits(noId, 2, 10); } @@ -5014,7 +5014,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 1, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 0, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 0, 0); csm.updateTargetValidatorsLimits(noId, 0, 10); } @@ -5026,7 +5026,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 1, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 0, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 0, 0); csm.updateTargetValidatorsLimits(noId, 0, 0); } @@ -5038,7 +5038,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 2, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 0, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 0, 0); csm.updateTargetValidatorsLimits(noId, 0, 10); } @@ -5050,7 +5050,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 2, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 0, 0); + emit ICSModule.TargetValidatorsCountChanged(noId, 0, 0); csm.updateTargetValidatorsLimits(noId, 0, 0); } @@ -5061,7 +5061,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 2, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 1, 5); + emit ICSModule.TargetValidatorsCountChanged(noId, 1, 5); csm.updateTargetValidatorsLimits(noId, 1, 5); } @@ -5072,7 +5072,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { csm.updateTargetValidatorsLimits(noId, 1, 10); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.TargetValidatorsCountChanged(noId, 2, 5); + emit ICSModule.TargetValidatorsCountChanged(noId, 2, 5); csm.updateTargetValidatorsLimits(noId, 2, 5); } @@ -5097,7 +5097,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { public { createNodeOperator(1); - vm.expectRevert(CSModule.InvalidInput.selector); + vm.expectRevert(ICSModule.InvalidInput.selector); csm.updateTargetValidatorsLimits(0, 1, uint256(type(uint32).max) + 1); } @@ -5105,7 +5105,7 @@ contract CsmUpdateTargetValidatorsLimits is CSMCommon { public { createNodeOperator(1); - vm.expectRevert(CSModule.InvalidInput.selector); + vm.expectRevert(ICSModule.InvalidInput.selector); csm.updateTargetValidatorsLimits(0, 3, 1); } } @@ -5117,7 +5117,7 @@ contract CsmUpdateStuckValidatorsCount is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.StuckSigningKeysCountChanged(noId, 1); + emit ICSModule.StuckSigningKeysCountChanged(noId, 1); csm.updateStuckValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000001)) @@ -5139,7 +5139,7 @@ contract CsmUpdateStuckValidatorsCount is CSMCommon { csm.obtainDepositData(1, ""); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.StuckSigningKeysCountChanged(noId, 1); + emit ICSModule.StuckSigningKeysCountChanged(noId, 1); csm.updateStuckValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000001)) @@ -5170,7 +5170,7 @@ contract CsmUpdateStuckValidatorsCount is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.StuckSigningKeysCountChanged(noId, 0); + emit ICSModule.StuckSigningKeysCountChanged(noId, 0); emit IQueueLib.BatchEnqueued(noId, 1); csm.updateStuckValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), @@ -5200,7 +5200,7 @@ contract CsmUpdateStuckValidatorsCount is CSMCommon { createNodeOperator(3); csm.obtainDepositData(1, ""); - vm.expectRevert(CSModule.StuckKeysHigherThanNonExited.selector); + vm.expectRevert(ICSModule.StuckKeysHigherThanNonExited.selector); csm.updateStuckValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000002)) @@ -5238,7 +5238,7 @@ contract CsmUpdateExitedValidatorsCount is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ExitedSigningKeysCountChanged(noId, 1); + emit ICSModule.ExitedSigningKeysCountChanged(noId, 1); csm.updateExitedValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000001)) @@ -5265,7 +5265,7 @@ contract CsmUpdateExitedValidatorsCount is CSMCommon { { createNodeOperator(1); - vm.expectRevert(CSModule.ExitedKeysHigherThanTotalDeposited.selector); + vm.expectRevert(ICSModule.ExitedKeysHigherThanTotalDeposited.selector); csm.updateExitedValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000001)) @@ -5283,7 +5283,7 @@ contract CsmUpdateExitedValidatorsCount is CSMCommon { bytes.concat(bytes16(0x00000000000000000000000000000001)) ); - vm.expectRevert(CSModule.ExitedKeysDecrease.selector); + vm.expectRevert(ICSModule.ExitedKeysDecrease.selector); csm.updateExitedValidatorsCount( bytes.concat(bytes8(0x0000000000000000)), bytes.concat(bytes16(0x00000000000000000000000000000000)) @@ -5323,8 +5323,8 @@ contract CsmUnsafeUpdateValidatorsCount is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.StuckSigningKeysCountChanged(noId, 1); - emit CSModule.ExitedSigningKeysCountChanged(noId, 1); + emit ICSModule.StuckSigningKeysCountChanged(noId, 1); + emit ICSModule.ExitedSigningKeysCountChanged(noId, 1); csm.unsafeUpdateValidatorsCount({ nodeOperatorId: noId, exitedValidatorsKeysCount: 1, @@ -5370,7 +5370,7 @@ contract CsmUnsafeUpdateValidatorsCount is CSMCommon { { uint256 noId = createNodeOperator(1); - vm.expectRevert(CSModule.ExitedKeysHigherThanTotalDeposited.selector); + vm.expectRevert(ICSModule.ExitedKeysHigherThanTotalDeposited.selector); csm.unsafeUpdateValidatorsCount({ nodeOperatorId: noId, exitedValidatorsKeysCount: 100500, @@ -5384,7 +5384,7 @@ contract CsmUnsafeUpdateValidatorsCount is CSMCommon { uint256 noId = createNodeOperator(1); csm.obtainDepositData(1, ""); - vm.expectRevert(CSModule.StuckKeysHigherThanNonExited.selector); + vm.expectRevert(ICSModule.StuckKeysHigherThanNonExited.selector); csm.unsafeUpdateValidatorsCount({ nodeOperatorId: noId, exitedValidatorsKeysCount: 1, @@ -5445,7 +5445,7 @@ contract CsmReportELRewardsStealingPenalty is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltyReported( + emit ICSModule.ELRewardsStealingPenaltyReported( noId, blockhash(block.number), BOND_SIZE / 2 @@ -5475,7 +5475,7 @@ contract CsmReportELRewardsStealingPenalty is CSMCommon { public { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.InvalidAmount.selector); + vm.expectRevert(ICSModule.InvalidAmount.selector); csm.reportELRewardsStealingPenalty( noId, blockhash(block.number), @@ -5521,7 +5521,7 @@ contract CsmCancelELRewardsStealingPenalty is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltyCancelled( + emit ICSModule.ELRewardsStealingPenaltyCancelled( noId, BOND_SIZE / 2 + csm.EL_REWARDS_STEALING_ADDITIONAL_FINE() ); @@ -5550,7 +5550,7 @@ contract CsmCancelELRewardsStealingPenalty is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltyCancelled(noId, BOND_SIZE / 2); + emit ICSModule.ELRewardsStealingPenaltyCancelled(noId, BOND_SIZE / 2); csm.cancelELRewardsStealingPenalty(noId, BOND_SIZE / 2); uint256 lockedBond = accounting.getActualLockedBond(noId); @@ -5580,7 +5580,7 @@ contract CsmSettleELRewardsStealingPenaltyBasic is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(noId); + emit ICSModule.ELRewardsStealingPenaltySettled(noId); vm.expectCall( address(accounting), abi.encodeWithSelector(accounting.resetBondCurve.selector, noId) @@ -5613,9 +5613,9 @@ contract CsmSettleELRewardsStealingPenaltyBasic is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(firstNoId); + emit ICSModule.ELRewardsStealingPenaltySettled(firstNoId); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(secondNoId); + emit ICSModule.ELRewardsStealingPenaltySettled(secondNoId); vm.expectCall( address(accounting), abi.encodeWithSelector( @@ -5718,7 +5718,7 @@ contract CsmSettleELRewardsStealingPenaltyBasic is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(secondNoId); + emit ICSModule.ELRewardsStealingPenaltySettled(secondNoId); expectNoCall( address(accounting), abi.encodeWithSelector( @@ -5765,7 +5765,7 @@ contract CsmSettleELRewardsStealingPenaltyBasic is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(secondNoId); + emit ICSModule.ELRewardsStealingPenaltySettled(secondNoId); vm.expectCall( address(accounting), abi.encodeWithSelector( @@ -5849,7 +5849,7 @@ contract CsmSettleELRewardsStealingPenaltyAdvanced is CSMCommon { ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(secondNoId); + emit ICSModule.ELRewardsStealingPenaltySettled(secondNoId); vm.expectCall( address(accounting), abi.encodeWithSelector( @@ -5974,7 +5974,7 @@ contract CsmSettleELRewardsStealingPenaltyAdvanced is CSMCommon { amount ); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltySettled(noId); + emit ICSModule.ELRewardsStealingPenaltySettled(noId); vm.expectCall( address(accounting), abi.encodeWithSelector(accounting.resetBondCurve.selector, noId) @@ -5997,7 +5997,7 @@ contract CSMCompensateELRewardsStealingPenalty is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltyCompensated(noId, amount + fine); + emit ICSModule.ELRewardsStealingPenaltyCompensated(noId, amount + fine); vm.expectCall( address(accounting), @@ -6031,7 +6031,7 @@ contract CSMCompensateELRewardsStealingPenalty is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.ELRewardsStealingPenaltyCompensated(noId, amount); + emit ICSModule.ELRewardsStealingPenaltyCompensated(noId, amount); vm.expectCall( address(accounting), @@ -6089,7 +6089,7 @@ contract CSMCompensateELRewardsStealingPenalty is CSMCommon { public { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SenderIsNotEligible.selector); + vm.expectRevert(ICSModule.SenderIsNotEligible.selector); csm.compensateELRewardsStealingPenalty{ value: 1 ether }(noId); } } @@ -6103,7 +6103,12 @@ contract CsmSubmitWithdrawal is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.WithdrawalSubmitted(noId, keyIndex, DEPOSIT_SIZE, pubkey); + emit ICSModule.WithdrawalSubmitted( + noId, + keyIndex, + DEPOSIT_SIZE, + pubkey + ); csm.submitWithdrawal(noId, keyIndex, DEPOSIT_SIZE, false); NodeOperator memory no = csm.getNodeOperator(noId); @@ -6123,7 +6128,7 @@ contract CsmSubmitWithdrawal is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.WithdrawalSubmitted( + emit ICSModule.WithdrawalSubmitted( noId, keyIndex, DEPOSIT_SIZE - BOND_SIZE - 1 ether, @@ -6231,7 +6236,7 @@ contract CsmSubmitWithdrawal is CSMCommon { assertInvariants { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.submitWithdrawal(noId, 0, 0, false); } @@ -6244,7 +6249,7 @@ contract CsmSubmitWithdrawal is CSMCommon { uint256 depositSize = DEPOSIT_SIZE; csm.submitWithdrawal(noId, 0, depositSize, false); - vm.expectRevert(CSModule.AlreadySubmitted.selector); + vm.expectRevert(ICSModule.AlreadySubmitted.selector); csm.submitWithdrawal(noId, 0, depositSize, false); } } @@ -6258,7 +6263,7 @@ contract CsmSubmitInitialSlashing is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.InitialSlashingSubmitted(noId, keyIndex, pubkey); + emit ICSModule.InitialSlashingSubmitted(noId, keyIndex, pubkey); vm.expectCall( address(accounting), abi.encodeWithSelector( @@ -6286,7 +6291,7 @@ contract CsmSubmitInitialSlashing is CSMCommon { uint256 nonce = csm.getNonce(); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.InitialSlashingSubmitted(noId, 0, pubkey); + emit ICSModule.InitialSlashingSubmitted(noId, 0, pubkey); vm.expectCall( address(accounting), abi.encodeWithSelector( @@ -6311,11 +6316,11 @@ contract CsmSubmitInitialSlashing is CSMCommon { bytes memory pubkey1 = slice(pubkeys, 48, 48); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.InitialSlashingSubmitted(noId, 0, pubkey0); + emit ICSModule.InitialSlashingSubmitted(noId, 0, pubkey0); csm.submitInitialSlashing(noId, 0); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.InitialSlashingSubmitted(noId, 1, pubkey1); + emit ICSModule.InitialSlashingSubmitted(noId, 1, pubkey1); csm.submitInitialSlashing(noId, 1); } @@ -6344,7 +6349,7 @@ contract CsmSubmitInitialSlashing is CSMCommon { public { uint256 noId = createNodeOperator(); - vm.expectRevert(CSModule.SigningKeysInvalidOffset.selector); + vm.expectRevert(ICSModule.SigningKeysInvalidOffset.selector); csm.submitInitialSlashing(noId, 0); } @@ -6356,7 +6361,7 @@ contract CsmSubmitInitialSlashing is CSMCommon { csm.obtainDepositData(1, ""); csm.submitInitialSlashing(noId, 0); - vm.expectRevert(CSModule.AlreadySubmitted.selector); + vm.expectRevert(ICSModule.AlreadySubmitted.selector); csm.submitInitialSlashing(noId, 0); } } @@ -6681,7 +6686,7 @@ contract CSMStakingRouterAccessControl is CSMCommonNoRoles { vm.prank(admin); csm.grantRole(role, actor); - vm.expectRevert(CSModule.NotSupported.selector); + vm.expectRevert(ICSModule.NotSupported.selector); vm.prank(actor); csm.updateRefundedValidatorsCount(noId, 0); } @@ -6826,7 +6831,7 @@ contract CSMStakingRouterAccessControl is CSMCommonNoRoles { contract CSMActivatePublicRelease is CSMCommonNoPublicRelease { function test_activatePublicRelease() public assertInvariants { vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.PublicRelease(); + emit ICSModule.PublicRelease(); csm.activatePublicRelease(); assertTrue(csm.publicRelease()); @@ -6838,7 +6843,7 @@ contract CSMActivatePublicRelease is CSMCommonNoPublicRelease { { csm.activatePublicRelease(); - vm.expectRevert(CSModule.AlreadyActivated.selector); + vm.expectRevert(ICSModule.AlreadyActivated.selector); csm.activatePublicRelease(); } @@ -6851,7 +6856,7 @@ contract CSMActivatePublicRelease is CSMCommonNoPublicRelease { keysCount ); - vm.expectRevert(CSModule.NotAllowedToJoinYet.selector); + vm.expectRevert(ICSModule.NotAllowedToJoinYet.selector); csm.addNodeOperatorETH{ value: keysCount * BOND_SIZE }( keysCount, keys, @@ -6905,7 +6910,7 @@ contract CSMEarlyAdoptionTest is CSMCommonNoPublicRelease { vm.deal(nodeOperator, BOND_SIZE / 2); vm.prank(nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -6932,7 +6937,7 @@ contract CSMEarlyAdoptionTest is CSMCommonNoPublicRelease { vm.deal(nodeOperator, BOND_SIZE / 2); vm.prank(nodeOperator); - vm.expectRevert(CSModule.NotAllowedToJoinYet.selector); + vm.expectRevert(ICSModule.NotAllowedToJoinYet.selector); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -6961,7 +6966,7 @@ contract CSMEarlyAdoptionTest is CSMCommonNoPublicRelease { vm.deal(nodeOperator, BOND_SIZE / 2); vm.prank(nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -6991,7 +6996,7 @@ contract CSMEarlyAdoptionTest is CSMCommonNoPublicRelease { vm.deal(nodeOperator, BOND_SIZE); vm.prank(nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); csm.addNodeOperatorETH{ value: (BOND_SIZE) * keysCount }( keysCount, keys, @@ -7021,7 +7026,7 @@ contract CSMEarlyAdoptionTest is CSMCommonNoPublicRelease { vm.deal(nodeOperator, (BOND_SIZE / 2) * keysCount); vm.prank(nodeOperator); - vm.expectRevert(CSModule.MaxSigningKeysCountExceeded.selector); + vm.expectRevert(ICSModule.MaxSigningKeysCountExceeded.selector); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -7050,7 +7055,7 @@ contract CSMEarlyAdoptionTestNoEA is CSMCommonNoPublicReleaseNoEA { vm.deal(nodeOperator, BOND_SIZE / 2); vm.prank(nodeOperator); - vm.expectRevert(CSModule.NotAllowedToJoinYet.selector); + vm.expectRevert(ICSModule.NotAllowedToJoinYet.selector); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -7075,7 +7080,7 @@ contract CSMEarlyAdoptionTestNoEA is CSMCommonNoPublicReleaseNoEA { vm.deal(nodeOperator, BOND_SIZE / 2); vm.prank(nodeOperator); - vm.expectRevert(CSModule.NotAllowedToJoinYet.selector); + vm.expectRevert(ICSModule.NotAllowedToJoinYet.selector); csm.addNodeOperatorETH{ value: (BOND_SIZE / 2) * keysCount }( keysCount, keys, @@ -7104,7 +7109,7 @@ contract CSMEarlyAdoptionTestNoEA is CSMCommonNoPublicReleaseNoEA { vm.deal(nodeOperator, BOND_SIZE); vm.prank(nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); csm.addNodeOperatorETH{ value: (BOND_SIZE) * keysCount }( keysCount, keys, @@ -7134,7 +7139,7 @@ contract CSMEarlyAdoptionTestNoEA is CSMCommonNoPublicReleaseNoEA { vm.deal(nodeOperator, BOND_SIZE); vm.prank(nodeOperator); vm.expectEmit(true, true, true, true, address(csm)); - emit CSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); + emit ICSModule.NodeOperatorAdded(0, nodeOperator, nodeOperator); csm.addNodeOperatorETH{ value: (BOND_SIZE) * keysCount }( keysCount, keys, @@ -7794,7 +7799,7 @@ contract CSMMisc is CSMCommon { function test_updateRefundedValidatorsCount() public assertInvariants { uint256 noId = createNodeOperator(); uint256 refunded = 1; - vm.expectRevert(CSModule.NotSupported.selector); + vm.expectRevert(ICSModule.NotSupported.selector); csm.updateRefundedValidatorsCount(noId, refunded); } @@ -7975,7 +7980,7 @@ contract CSMMisc is CSMCommon { public assertInvariants { - vm.expectRevert(CSModule.InvalidInput.selector); + vm.expectRevert(ICSModule.InvalidInput.selector); csm.setKeyRemovalCharge(1 ether); } } diff --git a/test/CSVerifier.t.sol b/test/CSVerifier.t.sol index 3e5e4f37..bda7d22f 100644 --- a/test/CSVerifier.t.sol +++ b/test/CSVerifier.t.sol @@ -118,7 +118,7 @@ contract CSVerifierTestConstructor is CSVerifierTestBase { } function test_constructor_RevertWhen_InvalidChainConfig() public { - vm.expectRevert(CSVerifier.InvalidChainConfig.selector); + vm.expectRevert(ICSVerifier.InvalidChainConfig.selector); verifier = new CSVerifier({ withdrawalAddress: nextAddress(), module: address(module), @@ -135,7 +135,7 @@ contract CSVerifierTestConstructor is CSVerifierTestBase { } function test_constructor_RevertWhen_ZeroModuleAddress() public { - vm.expectRevert(CSVerifier.ZeroModuleAddress.selector); + vm.expectRevert(ICSVerifier.ZeroModuleAddress.selector); verifier = new CSVerifier({ withdrawalAddress: nextAddress(), module: address(0), @@ -152,7 +152,7 @@ contract CSVerifierTestConstructor is CSVerifierTestBase { } function test_constructor_RevertWhen_ZeroWithdrawalAddress() public { - vm.expectRevert(CSVerifier.ZeroWithdrawalAddress.selector); + vm.expectRevert(ICSVerifier.ZeroWithdrawalAddress.selector); verifier = new CSVerifier({ withdrawalAddress: address(0), module: address(module), @@ -216,7 +216,7 @@ contract CSVerifierSlashingTest is CSVerifierTestBase { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.beaconBlock.header.slot ) ); @@ -242,7 +242,7 @@ contract CSVerifierSlashingTest is CSVerifierTestBase { abi.encode("lol") ); - vm.expectRevert(CSVerifier.InvalidBlockHeader.selector); + vm.expectRevert(ICSVerifier.InvalidBlockHeader.selector); verifier.processSlashingProof( fixture.beaconBlock, fixture.witness, @@ -335,7 +335,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.beaconBlock.header.slot ) ); @@ -363,7 +363,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { abi.encode("lol") ); - vm.expectRevert(CSVerifier.InvalidBlockHeader.selector); + vm.expectRevert(ICSVerifier.InvalidBlockHeader.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, @@ -392,7 +392,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { vm.etch(verifier.BEACON_ROOTS(), new bytes(0)); - vm.expectRevert(CSVerifier.RootNotFound.selector); + vm.expectRevert(ICSVerifier.RootNotFound.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, @@ -415,7 +415,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { "" ); - vm.expectRevert(CSVerifier.RootNotFound.selector); + vm.expectRevert(ICSVerifier.RootNotFound.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, @@ -436,7 +436,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { fixture.witness.withdrawalCredentials = bytes32(0); - vm.expectRevert(CSVerifier.InvalidWithdrawalAddress.selector); + vm.expectRevert(ICSVerifier.InvalidWithdrawalAddress.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, @@ -460,7 +460,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { 32 + 154; - vm.expectRevert(CSVerifier.ValidatorNotWithdrawn.selector); + vm.expectRevert(ICSVerifier.ValidatorNotWithdrawn.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, @@ -479,7 +479,7 @@ contract CSVerifierWithdrawalTest is CSVerifierTestBase { fixture.witness.amount = 154; - vm.expectRevert(CSVerifier.PartialWithdrawal.selector); + vm.expectRevert(ICSVerifier.PartialWithdrawal.selector); verifier.processWithdrawalProof( fixture.beaconBlock, fixture.witness, diff --git a/test/CSVerifierHistorical.t.sol b/test/CSVerifierHistorical.t.sol index 665c47ac..97920ecd 100644 --- a/test/CSVerifierHistorical.t.sol +++ b/test/CSVerifierHistorical.t.sol @@ -11,6 +11,7 @@ import { ICSModule } from "../src/interfaces/ICSModule.sol"; import { GIndex } from "../src/lib/GIndex.sol"; import { CSVerifier } from "../src/CSVerifier.sol"; +import { ICSVerifier } from "../src/interfaces/ICSVerifier.sol"; import { pack } from "../src/lib/GIndex.sol"; import { Slot } from "../src/lib/Types.sol"; @@ -90,7 +91,7 @@ contract CSVerifierHistoricalTest is Test { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.beaconBlock.header.slot ) ); @@ -115,7 +116,7 @@ contract CSVerifierHistoricalTest is Test { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.oldBlock.header.slot ) ); @@ -142,7 +143,7 @@ contract CSVerifierHistoricalTest is Test { abi.encode("lol") ); - vm.expectRevert(CSVerifier.InvalidBlockHeader.selector); + vm.expectRevert(ICSVerifier.InvalidBlockHeader.selector); // solhint-disable-next-line func-named-parameters verifier.processHistoricalWithdrawalProof( fixture.beaconBlock, @@ -159,7 +160,7 @@ contract CSVerifierHistoricalTest is Test { fixture.oldBlock.rootGIndex = GIndex.wrap(bytes32(0)); - vm.expectRevert(CSVerifier.InvalidGIndex.selector); + vm.expectRevert(ICSVerifier.InvalidGIndex.selector); // solhint-disable-next-line func-named-parameters verifier.processHistoricalWithdrawalProof( fixture.beaconBlock, diff --git a/test/CSVerifierHistoricalCrossForks.t.sol b/test/CSVerifierHistoricalCrossForks.t.sol index fbb7154e..b6f9b9f2 100644 --- a/test/CSVerifierHistoricalCrossForks.t.sol +++ b/test/CSVerifierHistoricalCrossForks.t.sol @@ -90,7 +90,7 @@ contract CSVerifierBiForkTestConstructor is Test, Utilities { } function test_constructor_RevertWhen_InvalidChainConfig() public { - vm.expectRevert(CSVerifier.InvalidChainConfig.selector); + vm.expectRevert(ICSVerifier.InvalidChainConfig.selector); verifier = new CSVerifier({ withdrawalAddress: nextAddress(), module: address(module), @@ -107,7 +107,7 @@ contract CSVerifierBiForkTestConstructor is Test, Utilities { } function test_constructor_RevertWhen_ZeroModuleAddress() public { - vm.expectRevert(CSVerifier.ZeroModuleAddress.selector); + vm.expectRevert(ICSVerifier.ZeroModuleAddress.selector); verifier = new CSVerifier({ withdrawalAddress: nextAddress(), module: address(0), // <-- @@ -124,7 +124,7 @@ contract CSVerifierBiForkTestConstructor is Test, Utilities { } function test_constructor_RevertWhen_ZeroWithdrawalAddress() public { - vm.expectRevert(CSVerifier.ZeroWithdrawalAddress.selector); + vm.expectRevert(ICSVerifier.ZeroWithdrawalAddress.selector); verifier = new CSVerifier({ withdrawalAddress: address(0), module: address(module), @@ -141,7 +141,7 @@ contract CSVerifierBiForkTestConstructor is Test, Utilities { } function test_constructor_RevertWhen_InvalidPivotSlot() public { - vm.expectRevert(CSVerifier.InvalidPivotSlot.selector); + vm.expectRevert(ICSVerifier.InvalidPivotSlot.selector); verifier = new CSVerifier({ withdrawalAddress: nextAddress(), module: address(module), @@ -224,7 +224,7 @@ contract CSVerifierBiForkHistoricalTest is Test { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.beaconBlock.header.slot ) ); @@ -249,7 +249,7 @@ contract CSVerifierBiForkHistoricalTest is Test { vm.expectRevert( abi.encodeWithSelector( - CSVerifier.UnsupportedSlot.selector, + ICSVerifier.UnsupportedSlot.selector, fixture.oldBlock.header.slot ) ); @@ -276,7 +276,7 @@ contract CSVerifierBiForkHistoricalTest is Test { abi.encode("lol") ); - vm.expectRevert(CSVerifier.InvalidBlockHeader.selector); + vm.expectRevert(ICSVerifier.InvalidBlockHeader.selector); // solhint-disable-next-line func-named-parameters verifier.processHistoricalWithdrawalProof( fixture.beaconBlock, @@ -293,7 +293,7 @@ contract CSVerifierBiForkHistoricalTest is Test { fixture.oldBlock.rootGIndex = GIndex.wrap(bytes32(0)); - vm.expectRevert(CSVerifier.InvalidGIndex.selector); + vm.expectRevert(ICSVerifier.InvalidGIndex.selector); // solhint-disable-next-line func-named-parameters verifier.processHistoricalWithdrawalProof( fixture.beaconBlock, diff --git a/test/fork/integration/Penalty.t.sol b/test/fork/integration/Penalty.t.sol index 0e6c6ae3..5f9edf50 100644 --- a/test/fork/integration/Penalty.t.sol +++ b/test/fork/integration/Penalty.t.sol @@ -124,7 +124,7 @@ contract PenaltyIntegrationTest is csm.reportELRewardsStealingPenalty( defaultNoId, blockhash(block.number), - amount - csm.EL_REWARDS_STEALING_ADDITIONAL_FINE() + amount - csm.EL_REWARDS_STEALING_FINE() ); uint256[] memory idsToSettle = new uint256[](1); diff --git a/test/fork/voting/StakingRouter.t.sol b/test/fork/voting/StakingRouter.t.sol index 5cdb1f13..fc541b61 100644 --- a/test/fork/voting/StakingRouter.t.sol +++ b/test/fork/voting/StakingRouter.t.sol @@ -6,6 +6,7 @@ pragma solidity 0.8.24; import "forge-std/Test.sol"; import { CSModule, NodeOperator, NodeOperatorManagementProperties } from "../../../src/CSModule.sol"; +import { ICSModule } from "../../../src/interfaces/ICSModule.sol"; import { ILidoLocator } from "../../../src/interfaces/ILidoLocator.sol"; import { IStakingRouter } from "../../../src/interfaces/IStakingRouter.sol"; import { IWithdrawalQueue } from "../../../src/interfaces/IWithdrawalQueue.sol"; @@ -225,7 +226,7 @@ contract StakingRouterIntegrationTest is address nodeOperatorManager = nextAddress(); uint256 noId = addNodeOperator(nodeOperatorManager, 5); - vm.expectRevert(CSModule.NotSupported.selector); + vm.expectRevert(ICSModule.NotSupported.selector); vm.prank(agent); stakingRouter.updateRefundedValidatorsCount(moduleId, noId, 1); }