LRTWithdrawalManager

创建于 差异永不过期
90 删除
434 行
221 添加
564 行
// SPDX-License-Identifier: BUSL-1.1
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
pragma solidity 0.8.27;


import { UtilLib } from "./utils/UtilLib.sol";
import { UtilLib } from "./utils/UtilLib.sol";
import { LRTConstants } from "./utils/LRTConstants.sol";
import { LRTConstants } from "./utils/LRTConstants.sol";
import { DoubleEndedQueue } from "./utils/DoubleEndedQueue.sol";
import { DoubleEndedQueue } from "./utils/DoubleEndedQueue.sol";


import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol";
import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol";
import { IRSETH } from "./interfaces/IRSETH.sol";
import { IRSETH } from "./interfaces/IRSETH.sol";
import { ILRTOracle } from "./interfaces/ILRTOracle.sol";
import { ILRTOracle } from "./interfaces/ILRTOracle.sol";
import { ILRTWithdrawalManager } from "./interfaces/ILRTWithdrawalManager.sol";
import { ILRTWithdrawalManager } from "./interfaces/ILRTWithdrawalManager.sol";
import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol";
import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol";
import { ILRTUnstakingVault } from "./interfaces/ILRTUnstakingVault.sol";
import { ILRTUnstakingVault } from "./interfaces/ILRTUnstakingVault.sol";

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {
ReentrancyGuardUpgradeable
} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";


/// @title LRTWithdrawalManager - Withdraw Manager Contract for rsETH => LSTs
/// @title LRTWithdrawalManager - Withdraw Manager Contract for rsETH => LSTs
/// @notice Handles LST asset withdraws
/// @notice Handles LST asset withdraws
contract LRTWithdrawalManager is
contract LRTWithdrawalManager is
ILRTWithdrawalManager,
ILRTWithdrawalManager,
LRTConfigRoleChecker,
LRTConfigRoleChecker,
PausableUpgradeable,
PausableUpgradeable,
ReentrancyGuardUpgradeable
ReentrancyGuardUpgradeable
{
{
using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque;
using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;


mapping(address asset => uint256) public minRsEthAmountToWithdraw;
mapping(address asset => uint256) public minRsEthAmountToWithdraw;
uint256 public withdrawalDelayBlocks;
uint256 public withdrawalDelayBlocks;


// Next available nonce for withdrawal requests per asset, indicating total requests made.
// Next available nonce for withdrawal requests per asset, indicating total requests made.
mapping(address asset => uint256 nonce) public nextUnusedNonce;
mapping(address asset => uint256 nonce) public nextUnusedNonce;


// Next nonce for which a withdrawal request remains locked.
// Next nonce for which a withdrawal request remains locked.
mapping(address asset => uint256 requestNonce) public nextLockedNonce;
mapping(address asset => uint256 requestNonce) public nextLockedNonce;


// Mapping from a unique request identifier to its corresponding withdrawal request
// Mapping from a unique request identifier to its corresponding withdrawal request
mapping(bytes32 requestId => WithdrawalRequest) public withdrawalRequests;
mapping(bytes32 requestId => WithdrawalRequest) public withdrawalRequests;


// Maps each asset to user addresses, pointing to an ordert list of their withdrawal request nonces.
// Maps each asset to user addresses, pointing to an ordered list of their withdrawal request nonces.
// Utilizes a double-ended queue for efficient management and removal of initial requests.
// Utilizes a double-ended queue for efficient management and removal of initial requests.
mapping(address asset => mapping(address user => DoubleEndedQueue.Uint256Deque requestNonces)) public
mapping(address asset => mapping(address user => DoubleEndedQueue.Uint256Deque requestNonces)) public
userAssociatedNonces;
userAssociatedNonces;


// Asset amount commited to be withdrawn by users.
// Asset amount committed to be withdrawn by users.
mapping(address asset => uint256 amount) public assetsCommitted;
mapping(address asset => uint256 amount) public assetsCommitted;


mapping(address asset => bool) public isInstantWithdrawalEnabled;
uint256 public instantWithdrawalFee; // Fee in basis points (1 = 0.01%)

mapping(address asset => uint256) public unlockedWithdrawalsCount;

modifier onlySupportedStrategy(address asset) {
modifier onlySupportedStrategy(address asset) {
if (asset != LRTConstants.ETH_TOKEN && lrtConfig.assetStrategy(asset) == address(0)) {
if (asset != LRTConstants.ETH_TOKEN && lrtConfig.assetStrategy(asset) == address(0)) {
revert StrategyNotSupported();
revert StrategyNotSupported();
}
}
_;
_;
}
}


modifier onlyInstantWithdrawalAllowed(address asset) {
if (!isInstantWithdrawalEnabled[asset]) revert InstantWithdrawalNotEnabled();
_;
}

modifier onlyAfterInitialize2() {
if (!isInitialized2()) revert NotInitialized();
_;
}

/// @custom:oz-upgrades-unsafe-allow constructor
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
constructor() {
_disableInitializers();
_disableInitializers();
}
}


/// @notice Initializes the contract
/// @notice Initializes the contract
/// @param lrtConfigAddr LRT config address
/// @param lrtConfigAddr LRT config address
function initialize(address lrtConfigAddr) external initializer {
function initialize(address lrtConfigAddr) external initializer {
UtilLib.checkNonZeroAddress(lrtConfigAddr);
UtilLib.checkNonZeroAddress(lrtConfigAddr);
__Pausable_init();
__Pausable_init();
__ReentrancyGuard_init();
__ReentrancyGuard_init();
withdrawalDelayBlocks = 8 days / 12 seconds;
withdrawalDelayBlocks = 8 days / 12 seconds;


lrtConfig = ILRTConfig(lrtConfigAddr);
lrtConfig = ILRTConfig(lrtConfigAddr);
emit UpdatedLRTConfig(lrtConfigAddr);
emit UpdatedLRTConfig(lrtConfigAddr);
}
}


/// @notice Initializes unlocked withdrawals count for ETHx, STETH and ETH
/// @param unlockedWithdrawalsCountETHx Initial unlocked withdrawals count for ETHx
/// @param unlockedWithdrawalsCountSTETH Initial unlocked withdrawals count for STETH
/// @param unlockedWithdrawalsCountETH Initial unlocked withdrawals count for ETH
function initialize2(
uint256 unlockedWithdrawalsCountETHx,
uint256 unlockedWithdrawalsCountSTETH,
uint256 unlockedWithdrawalsCountETH
)
external
reinitializer(2)
onlyRole(LRTConstants.UNLOCKED_WITHDRAWAL_INITIALIZER)
{
unlockedWithdrawalsCount[lrtConfig.getLSTToken(LRTConstants.ST_ETH_TOKEN)] = unlockedWithdrawalsCountSTETH;
unlockedWithdrawalsCount[lrtConfig.getLSTToken(LRTConstants.ETHX_TOKEN)] = unlockedWithdrawalsCountETHx;
unlockedWithdrawalsCount[LRTConstants.ETH_TOKEN] = unlockedWithdrawalsCountETH;
}

/*//////////////////////////////////////////////////////////////
/*//////////////////////////////////////////////////////////////
receive functions
receive functions
//////////////////////////////////////////////////////////////*/
//////////////////////////////////////////////////////////////*/


receive() external payable { }
receive() external payable { }


/// @dev receive from LRTUnstakingVault
/// @dev receive from LRTUnstakingVault
function receiveFromLRTUnstakingVault() external payable { }
function receiveFromLRTUnstakingVault() external payable { }


/*//////////////////////////////////////////////////////////////
/*//////////////////////////////////////////////////////////////
User Withdrawal functions
User Withdrawal functions
//////////////////////////////////////////////////////////////*/
//////////////////////////////////////////////////////////////*/


/// @notice Initiates a withdrawal request for converting rsETH to a specified LST.
/// @notice Initiates a withdrawal request for converting rsETH to a specified LST.
/// @param asset The LST address the user wants to receive.
/// @param asset The LST address the user wants to receive.
/// @param rsETHUnstaked The amount of rsETH the user wishes to unstake.
/// @param rsETHUnstaked The amount of rsETH the user wishes to unstake.
/// @dev This function is only callable by the user and is used to initiate a withdrawal request for a specific
/// @dev This function is only callable by the user and is used to initiate a withdrawal request for a specific
/// asset. Will be finalised by calling `completeWithdrawal` after the manager unlocked the request and the delay
/// asset. Will be finalised by calling `completeWithdrawal` after the manager unlocked the request and the delay
/// has past. There is an edge case were the user withdraws last underlying asset and that asset gets slashed.
/// has past. There is an edge case were the user withdraws last underlying asset and that asset gets slashed.
function initiateWithdrawal(
function initiateWithdrawal(
address asset,
address asset,
uint256 rsETHUnstaked,
uint256 rsETHUnstaked,
string calldata referralId
string calldata referralId