Skip to content

Commit

Permalink
chore: cleanup staking vault interface
Browse files Browse the repository at this point in the history
  • Loading branch information
tamtamchik committed Feb 3, 2025
1 parent ab1a048 commit daf96c4
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 84 deletions.
12 changes: 6 additions & 6 deletions contracts/0.8.25/vaults/Permissions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ abstract contract Permissions is AccessControlVoteable {
/**
* @notice Permission for force validators exit from the StakingVault using EIP-7002 triggerable exit.
*/
bytes32 public constant FORCE_VALIDATORS_EXIT_ROLE = keccak256("StakingVault.Permissions.ForceValidatorsExit");
bytes32 public constant INITIATE_VALIDATOR_WITHDRAWAL_ROLE = keccak256("StakingVault.Permissions.InitiateValidatorWithdrawal");

/**
* @notice Permission for voluntary disconnecting the StakingVault.
Expand Down Expand Up @@ -147,15 +147,15 @@ abstract contract Permissions is AccessControlVoteable {
}

function _requestValidatorExit(bytes calldata _pubkey) internal onlyRole(REQUEST_VALIDATOR_EXIT_ROLE) {
stakingVault().requestValidatorsExit(_pubkey);
stakingVault().requestValidatorExit(_pubkey);
}

function _forceValidatorsExit(bytes calldata _pubkeys) internal onlyRole(FORCE_VALIDATORS_EXIT_ROLE) {
stakingVault().forceValidatorsExit(_pubkeys);
function _initiateFullValidatorsWithdrawal(bytes calldata _pubkeys) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiateFullValidatorWithdrawal(_pubkeys);
}

function _forcePartialValidatorsExit(bytes calldata _pubkeys, uint64[] calldata _amounts) internal onlyRole(FORCE_VALIDATORS_EXIT_ROLE) {
stakingVault().forcePartialValidatorsExit(_pubkeys, _amounts);
function _initiatePartialValidatorsWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiatePartialValidatorWithdrawal(_pubkeys, _amounts);
}

function _voluntaryDisconnect() internal onlyRole(VOLUNTARY_DISCONNECT_ROLE) {
Expand Down
78 changes: 13 additions & 65 deletions contracts/0.8.25/vaults/StakingVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
uint128 locked;
int128 inOutDelta;
address nodeOperator;
/// Status variables
bool beaconChainDepositsPaused;
uint256 unbalancedSince;
}

/**
Expand All @@ -96,11 +94,6 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
bytes32 private constant ERC7201_STORAGE_LOCATION =
0x2ec50241a851d8d3fea472e7057288d4603f7a7f78e6d18a9c12cad84552b100;

/**
* @notice Update constant for exit timelock duration to 3 days
*/
uint256 private constant EXIT_TIMELOCK_DURATION = 3 days;

/**
* @notice Constructs the implementation of `StakingVault`
* @param _vaultHub Address of `VaultHub`
Expand Down Expand Up @@ -217,28 +210,6 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
return _getStorage().report;
}

/**
* @notice Returns whether `StakingVault` is balanced, i.e. its valuation is greater than the locked amount
* @return True if `StakingVault` is balanced
* @dev Not to be confused with the ether balance of the contract (`address(this).balance`).
* Semantically, this state has nothing to do with the actual balance of the contract,
* althogh, of course, the balance of the contract is accounted for in its valuation.
* The `isBalanced()` state indicates whether `StakingVault` is in a good shape
* in terms of the balance of its valuation against the locked amount.
*/
function isBalanced() public view returns (bool) {
return valuation() >= _getStorage().locked;
}

/**
* @notice Returns the timestamp when `StakingVault` became unbalanced
* @return Timestamp when `StakingVault` became unbalanced
* @dev If `StakingVault` is balanced, returns 0
*/
function unbalancedSince() external view returns (uint256) {
return _getStorage().unbalancedSince;
}

/**
* @notice Returns the address of the node operator
* Node operator is the party responsible for managing the validators.
Expand Down Expand Up @@ -269,10 +240,6 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
ERC7201Storage storage $ = _getStorage();
$.inOutDelta += int128(int256(msg.value));

if (isBalanced()) {
$.unbalancedSince = 0;
}

emit Funded(msg.sender, msg.value);
}

Expand All @@ -282,8 +249,8 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
* @param _ether Amount of ether to withdraw.
* @dev Cannot withdraw more than the unlocked amount or the balance of the contract, whichever is less.
* @dev Updates inOutDelta to track the net difference between funded and withdrawn ether
* @dev Includes the `isBalanced()` check to ensure `StakingVault` remains balanced after the withdrawal,
* to safeguard against possible reentrancy attacks.
* @dev Includes a check that valuation remains greater than locked amount after withdrawal to ensure
* `StakingVault` stays balanced and prevent reentrancy attacks.
*/
function withdraw(address _recipient, uint256 _ether) external onlyOwner {
if (_recipient == address(0)) revert ZeroArgument("_recipient");
Expand All @@ -297,7 +264,8 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad

(bool success, ) = _recipient.call{value: _ether}("");
if (!success) revert TransferFailed(_recipient, _ether);
if (!isBalanced()) revert Unbalanced();

if (valuation() < $.locked) revert Unbalanced();

emit Withdrawn(msg.sender, _recipient, _ether);
}
Expand All @@ -315,10 +283,6 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad

$.locked = uint128(_locked);

if (!isBalanced()) {
$.unbalancedSince = block.timestamp;
}

emit LockedIncreased(_locked);
}

Expand All @@ -334,8 +298,9 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
uint256 _valuation = valuation();
if (_ether > _valuation) revert RebalanceAmountExceedsValuation(_valuation, _ether);

if (owner() == msg.sender || (!isBalanced() && msg.sender == address(VAULT_HUB))) {
ERC7201Storage storage $ = _getStorage();
ERC7201Storage storage $ = _getStorage();
if (owner() == msg.sender || (_valuation < $.locked && msg.sender == address(VAULT_HUB))) {

$.inOutDelta -= int128(int256(_ether));

emit Withdrawn(msg.sender, address(VAULT_HUB), _ether);
Expand All @@ -361,12 +326,6 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
$.report.inOutDelta = int128(_inOutDelta);
$.locked = uint128(_locked);

if (isBalanced()) {
$.unbalancedSince = 0;
} else {
$.unbalancedSince = block.timestamp;
}

emit Reported(_valuation, _inOutDelta, _locked);
}

Expand Down Expand Up @@ -441,7 +400,7 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad

if (msg.sender != $.nodeOperator) revert NotAuthorized("depositToBeaconChain", msg.sender);
if ($.beaconChainDepositsPaused) revert BeaconChainDepositsArePaused();
if (!isBalanced()) revert Unbalanced();
if (valuation() < $.locked) revert Unbalanced();

_deposit(_deposits);
}
Expand All @@ -451,7 +410,7 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
* @param _numberOfKeys Number of validator keys
* @return Total fee amount
*/
function calculateTotalExitRequestFee(uint256 _numberOfKeys) external view returns (uint256) {
function calculateValidatorWithdrawalFee(uint256 _numberOfKeys) external view returns (uint256) {
if (_numberOfKeys == 0) revert ZeroArgument("_numberOfKeys");

return _calculateWithdrawalFee(_numberOfKeys);
Expand All @@ -462,7 +421,7 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
* @param _pubkeys Concatenated validator public keys
* @dev Signals the node operator to eject the specified validators from the beacon chain
*/
function requestValidatorsExit(bytes calldata _pubkeys) external onlyOwner {
function requestValidatorExit(bytes calldata _pubkeys) external onlyOwner {
_requestExit(_pubkeys);
}

Expand All @@ -471,18 +430,8 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
* @param _pubkeys Concatenated validators public keys
* @dev Signals the node operator to eject the specified validators from the beacon chain
*/
function forceValidatorsExit(bytes calldata _pubkeys) external payable {
// Only owner or node operator can exit validators when vault is balanced
if (isBalanced()) {
_onlyOwnerOrNodeOperator();
}

// Ensure timelock period has elapsed
uint256 exitTimelock = _getStorage().unbalancedSince + EXIT_TIMELOCK_DURATION;
if (block.timestamp < exitTimelock) {
revert ExitTimelockNotElapsed(exitTimelock);
}

function initiateFullValidatorWithdrawal(bytes calldata _pubkeys) external payable {
_onlyOwnerOrNodeOperator();
_initiateFullWithdrawal(_pubkeys);
}

Expand All @@ -492,9 +441,8 @@ contract StakingVault is IStakingVault, BeaconValidatorController, OwnableUpgrad
* @param _amounts Amounts of ether to exit
* @dev Signals the node operator to eject the specified validators from the beacon chain
*/
function forcePartialValidatorsExit(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable {
function initiatePartialValidatorWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable {
_onlyOwnerOrNodeOperator();

_initiatePartialWithdrawal(_pubkeys, _amounts);
}

Expand Down
9 changes: 4 additions & 5 deletions contracts/0.8.25/vaults/interfaces/IStakingVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ interface IStakingVault {
function nodeOperator() external view returns (address);
function locked() external view returns (uint256);
function valuation() external view returns (uint256);
function isBalanced() external view returns (bool);
function unlocked() external view returns (uint256);
function inOutDelta() external view returns (int256);

Expand All @@ -54,9 +53,9 @@ interface IStakingVault {
function resumeBeaconChainDeposits() external;
function depositToBeaconChain(Deposit[] calldata _deposits) external;

function requestValidatorsExit(bytes calldata _pubkeys) external;
function requestValidatorExit(bytes calldata _pubkeys) external;

function calculateTotalExitRequestFee(uint256 _validatorCount) external view returns (uint256);
function forceValidatorsExit(bytes calldata _pubkeys) external payable;
function forcePartialValidatorsExit(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable;
function calculateValidatorWithdrawalFee(uint256 _validatorCount) external view returns (uint256);
function initiateFullValidatorWithdrawal(bytes calldata _pubkeys) external payable;
function initiatePartialValidatorWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ contract StakingVault__HarnessForTestUpgrade is IStakingVault, OwnableUpgradeabl
return -1;
}

function isBalanced() external pure returns (bool) {
return true;
}

function nodeOperator() external view returns (address) {
return _getVaultStorage().nodeOperator;
}
Expand Down Expand Up @@ -126,16 +122,16 @@ contract StakingVault__HarnessForTestUpgrade is IStakingVault, OwnableUpgradeabl
return false;
}

function calculateTotalExitRequestFee(uint256) external pure returns (uint256) {
function calculateValidatorWithdrawalFee(uint256) external pure returns (uint256) {
return 1;
}

function pauseBeaconChainDeposits() external {}
function resumeBeaconChainDeposits() external {}

function requestValidatorsExit(bytes calldata _pubkeys) external {}
function forceValidatorsExit(bytes calldata _pubkeys) external payable {}
function forcePartialValidatorsExit(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable {}
function requestValidatorExit(bytes calldata _pubkeys) external {}
function initiateFullValidatorWithdrawal(bytes calldata _pubkeys) external payable {}
function initiatePartialValidatorWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) external payable {}

error ZeroArgument(string name);
error VaultAlreadyInitialized();
Expand Down

0 comments on commit daf96c4

Please sign in to comment.