Skip to content

Commit

Permalink
Merge pull request #554 from lidofinance/refactor/recipient-to-owner
Browse files Browse the repository at this point in the history
Refactor/recipient to owner
  • Loading branch information
folkyatina authored Feb 5, 2023
2 parents fcbe399 + 17bf4ee commit 375a1e2
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 183 deletions.
84 changes: 43 additions & 41 deletions contracts/0.8.9/WithdrawalQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {AccessControlEnumerable} from "./utils/access/AccessControlEnumerable.so
import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol";

import {Versioned} from "./utils/Versioned.sol";
import {SafeCast} from "../common/lib/SafeCast.sol";

/**
* @title Interface defining a Lido liquid staking pool
Expand Down Expand Up @@ -54,6 +55,7 @@ interface IWstETH is IERC20, IERC20Permit {
* @author folkyatina
*/
contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versioned {
using SafeCast for uint256;
using SafeERC20 for IWstETH;
using SafeERC20 for IStETH;
using UnstructuredStorage for bytes32;
Expand Down Expand Up @@ -111,14 +113,6 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
error RequestIdsNotSorted();
error ZeroPauseDuration();

/// @notice Reverts when the contract is uninitialized
modifier whenInitialized() {
if (CONTRACT_VERSION_POSITION.getStorageUint256() == 0) {
revert Uninitialized();
}
_;
}

/// @notice Reverts when new withdrawal requests placement and finalization resumed
modifier whenPaused() {
if (block.timestamp >= RESUME_SINCE_TIMESTAMP_POSITION.getStorageUint256()) {
Expand Down Expand Up @@ -172,7 +166,7 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
* @dev Reverts with `PausedExpected()` if contract is already resumed
* @dev Reverts with `AccessControl:...` reason if sender has no `RESUME_ROLE`
*/
function resume() external whenInitialized whenPaused onlyRole(RESUME_ROLE) {
function resume() external whenPaused onlyRole(RESUME_ROLE) {
RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(block.timestamp);

emit Resumed();
Expand Down Expand Up @@ -208,14 +202,14 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
struct WithdrawalRequestInput {
/// @notice Amount of the wstETH/StETH tokens that will be locked for withdrawal
uint256 amount;
/// @notice Address to send ether to upon withdrawal
address recipient;
/// @notice Address that will be able to manage or claim the request
address owner;
}

/// @notice Request the sequence of stETH withdrawals according to passed `withdrawalRequestInputs` data
/// @param _withdrawalRequestInputs an array of `WithdrawalRequestInput` data. The standalone withdrawal request will
/// be created for each item in the passed list. If `WithdrawalRequestInput.recipient` is set to `address(0)`,
/// `msg.sender` will be used as recipient.
/// be created for each item in the passed list. If `WithdrawalRequestInput.owner` is set to `address(0)`,
/// `msg.sender` will be used as owner.
/// @return requestIds an array of the created withdrawal requests
function requestWithdrawals(WithdrawalRequestInput[] calldata _withdrawalRequestInputs)
public
Expand All @@ -226,15 +220,15 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
for (uint256 i = 0; i < _withdrawalRequestInputs.length; ++i) {
requestIds[i] = _requestWithdrawal(
_withdrawalRequestInputs[i].amount,
_checkWithdrawalRequestInput(_withdrawalRequestInputs[i].amount, _withdrawalRequestInputs[i].recipient)
_checkWithdrawalRequestInput(_withdrawalRequestInputs[i].amount, _withdrawalRequestInputs[i].owner)
);
}
}

/// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data
/// @param _withdrawalRequestInputs an array of `WithdrawalRequestInput` data. The standalone withdrawal request will
/// be created for each item in the passed list. If `WithdrawalRequestInput.recipient` is set to `address(0)`,
/// `msg.sender` will be used as recipient.
/// be created for each item in the passed list. If `WithdrawalRequestInput.owner` is set to `address(0)`,
/// `msg.sender` will be used as owner.
/// @return requestIds an array of the created withdrawal requests
function requestWithdrawalsWstETH(WithdrawalRequestInput[] calldata _withdrawalRequestInputs)
public
Expand All @@ -244,10 +238,10 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
requestIds = new uint256[](_withdrawalRequestInputs.length);
for (uint256 i = 0; i < _withdrawalRequestInputs.length; ++i) {
uint256 amountOfWstETH = _withdrawalRequestInputs[i].amount;
address recipient = _checkWithdrawalRequestInput(
IWstETH(WSTETH).getStETHByWstETH(amountOfWstETH), _withdrawalRequestInputs[i].recipient
address owner = _checkWithdrawalRequestInput(
IWstETH(WSTETH).getStETHByWstETH(amountOfWstETH), _withdrawalRequestInputs[i].owner
);
requestIds[i] = _requestWithdrawalWstETH(amountOfWstETH, recipient);
requestIds[i] = _requestWithdrawalWstETH(amountOfWstETH, owner);
}
}

Expand All @@ -261,8 +255,8 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio

/// @notice Request the sequence of stETH withdrawals according to passed `withdrawalRequestInputs` data using EIP-2612 Permit
/// @param _withdrawalRequestInputs an array of `WithdrawalRequestInput` data. The standalone withdrawal request will
/// be created for each item in the passed list. If `WithdrawalRequestInput.recipient` is set to `address(0)`,
/// `msg.sender` will be used as recipient.
/// be created for each item in the passed list. If `WithdrawalRequestInput.owner` is set to `address(0)`,
/// `msg.sender` will be used as owner.
/// @param _permit data required for the stETH.permit() method to set the allowance
/// @return requestIds an array of the created withdrawal requests
function requestWithdrawalsWithPermit(
Expand All @@ -275,8 +269,8 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio

/// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data using EIP-2612 Permit
/// @param _withdrawalRequestInputs an array of `WithdrawalRequestInput` data. The standalone withdrawal request will
/// be created for each item in the passed list. If `WithdrawalRequestInput.recipient` is set to `address(0)`,
/// `msg.sender` will be used as recipient.
/// be created for each item in the passed list. If `WithdrawalRequestInput.owner` is set to `address(0)`,
/// `msg.sender` will be used as owner.
/// @param _permit data required for the wstETH.permit() method to set the allowance
/// @return requestIds an array of the created withdrawal requests
function requestWithdrawalsWstETHWithPermit(
Expand All @@ -287,6 +281,18 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
return requestWithdrawalsWstETH(_withdrawalRequestInputs);
}

/// @notice return statuses for the bunch of requests
/// @param _requestIds list of withdrawal request ids and hints to claim
function getWithdrawalRequestStatuses(uint256[] calldata _requestIds)
external
returns (WithdrawalRequestStatus[] memory statuses)
{
statuses = new WithdrawalRequestStatus[](_requestIds.length);
for (uint256 i = 0; i < _requestIds.length; ++i) {
statuses[i] = getWithdrawalRequestStatus(_requestIds[i]);
}
}

struct ClaimWithdrawalInput {
/// @notice id of the finalized requests to claim
uint256 requestId;
Expand Down Expand Up @@ -339,30 +345,28 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
* @param _lastRequestIdToFinalize request index in the queue that will be last finalized request in a batch
*/
function finalize(uint256 _lastRequestIdToFinalize) external payable whenResumed onlyRole(FINALIZE_ROLE) {
_finalize(_lastRequestIdToFinalize, uint128(msg.value));
_finalize(_lastRequestIdToFinalize, msg.value.toUint128());
}

/**
* @notice Update bunker mode state
* @dev should be called by oracle
*
* NB: timestamp should correspond to the previous oracle report
*
* @param _isBunkerModeNow oracle report
* @param _previousOracleReportTimestamp timestamp of the previous oracle report
* @param _bunkerModeSinceTimestamp timestamp of start of the bunker mode
*/
function updateBunkerMode(bool _isBunkerModeNow, uint256 _previousOracleReportTimestamp)
function updateBunkerMode(bool _isBunkerModeNow, uint256 _bunkerModeSinceTimestamp)
external
onlyRole(BUNKER_MODE_REPORT_ROLE)
{
if (_previousOracleReportTimestamp >= block.timestamp) revert InvalidReportTimestamp();
if (_bunkerModeSinceTimestamp >= block.timestamp) revert InvalidReportTimestamp();

bool isBunkerModeWasSetBefore = isBunkerModeActive();

// on bunker mode state change
if (_isBunkerModeNow != isBunkerModeWasSetBefore) {
// write previous timestamp to enable bunker or max uint to disable
uint256 newTimestamp = _isBunkerModeNow ? _previousOracleReportTimestamp : BUNKER_MODE_DISABLED_TIMESTAMP;
uint256 newTimestamp = _isBunkerModeNow ? _bunkerModeSinceTimestamp : BUNKER_MODE_DISABLED_TIMESTAMP;
BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(newTimestamp);
}
}
Expand Down Expand Up @@ -394,41 +398,39 @@ contract WithdrawalQueue is AccessControlEnumerable, WithdrawalQueueBase, Versio
_grantRole(FINALIZE_ROLE, _finalizer);

RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(PAUSE_INFINITELY); // pause it explicitly
BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(BUNKER_MODE_DISABLED_TIMESTAMP);

emit InitializedV1(_admin, _pauser, _resumer, _finalizer, msg.sender);
}

function _requestWithdrawal(uint256 _amountOfStETH, address _recipient) internal returns (uint256 requestId) {
function _requestWithdrawal(uint256 _amountOfStETH, address _owner) internal returns (uint256 requestId) {
STETH.safeTransferFrom(msg.sender, address(this), _amountOfStETH);

uint256 amountOfShares = STETH.getSharesByPooledEth(_amountOfStETH);

return _enqueue(uint128(_amountOfStETH), uint128(amountOfShares), _recipient);
return _enqueue(_amountOfStETH.toUint128(), amountOfShares.toUint128(), _owner);
}

function _requestWithdrawalWstETH(uint256 _amountOfWstETH, address _recipient)
internal
returns (uint256 requestId)
{
function _requestWithdrawalWstETH(uint256 _amountOfWstETH, address _owner) internal returns (uint256 requestId) {
WSTETH.safeTransferFrom(msg.sender, address(this), _amountOfWstETH);
uint256 amountOfStETH = IWstETH(WSTETH).unwrap(_amountOfWstETH);

uint256 amountOfShares = STETH.getSharesByPooledEth(amountOfStETH);

return _enqueue(uint128(amountOfStETH), uint128(amountOfShares), _recipient);
return _enqueue(amountOfStETH.toUint128(), amountOfShares.toUint128(), _owner);
}

function _checkWithdrawalRequestInput(uint256 _amountOfStETH, address _recipient) internal view returns (address) {
function _checkWithdrawalRequestInput(uint256 _amountOfStETH, address _owner) internal view returns (address) {
if (_amountOfStETH < MIN_STETH_WITHDRAWAL_AMOUNT) {
revert RequestAmountTooSmall(_amountOfStETH);
}
if (_amountOfStETH > MAX_STETH_WITHDRAWAL_AMOUNT) {
revert RequestAmountTooLarge(_amountOfStETH);
}
if (_recipient == address(0)) {
_recipient = msg.sender;
if (_owner == address(0)) {
_owner = msg.sender;
}

return _recipient;
return _owner;
}
}
Loading

0 comments on commit 375a1e2

Please sign in to comment.