LRTWithdrawalManager

建立於 差異永不過期
196 刪除
564 行
186 新增
550 行
// 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 {
import {
ReentrancyGuardUpgradeable
ReentrancyGuardUpgradeable
} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
} 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";
import { IWrappedTokenGatewayV3 } from "./interfaces/aave/IWrappedTokenGatewayV3.sol";
import { IAToken } from "./interfaces/aave/IAToken.sol";
import { IPoolDataProvider } from "./interfaces/aave/IPoolDataProvider.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 ordered 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 committed 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;
mapping(address asset => bool) public isInstantWithdrawalEnabled;
uint256 public instantWithdrawalFee; // Fee in basis points (1 = 0.01%)
uint256 public instantWithdrawalFee; // Fee in basis points (1 = 0.01%)


mapping(address asset => uint256) public unlockedWithdrawalsCount;
mapping(address asset => uint256) public unlockedWithdrawalsCount;


IWrappedTokenGatewayV3 public aaveWETHGateway;
IAToken public aaveAWETH;
address public aavePool;
IPoolDataProvider public aaveDataProvider;
bool public isAaveIntegrationEnabled;
uint256 public totalETHDepositedToAave;
address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

/// @notice Address that receives instant withdrawal fees. If unset, fees go to the protocol treasury.
address public instantWithdrawalFeeRecipient;

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) {
modifier onlyInstantWithdrawalAllowed(address asset) {
if (!isInstantWithdrawalEnabled[asset]) revert InstantWithdrawalNotEnabled();
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
/// @notice Initializes unlocked withdrawals count for ETHx, STETH and ETH
/// @dev Upgrade-only reinitializer used to seed `unlockedWithdrawalsCount` for the existing deployments.
/// Can be called exactly once and only by the UNLOCKED_WITHDRAWAL_INITIALIZER role.
/// After this call, the per-asset `unlockedWithdrawalsCount` is only changed by the normal
/// withdrawal lifecycle and cannot be manually overridden. New deployments MUST NOT call
/// this function, as they are expected to start from zero unlocked withdrawals.
/// @param unlockedWithdrawalsCountETHx Initial unlocked withdrawals count for ETHx
/// @param unlockedWithdrawalsCountETHx Initial unlocked withdrawals count for ETHx
/// @param unlockedWithdrawalsCountSTETH Initial unlocked withdrawals count for STETH
/// @param unlockedWithdrawalsCountSTETH Initial unlocked withdrawals count for STETH
/// @param unlockedWithdrawalsCountETH Initial unlocked withdrawals count for ETH
/// @param unlockedWithdrawalsCountETH Initial unlocked withdrawals count for ETH
function initialize2(
function initialize2(
uint256 unlockedWithdrawalsCountETHx,
uint256 unlockedWithdrawalsCountETHx,
uint256 unlockedWithdrawalsCountSTETH,
uint256 unlockedWithdrawalsCountSTETH,
uint256 unlockedWithdrawalsCountETH
uint256 unlockedWithdrawalsCountETH
)
)
external
external
reinitializer(2)
reinitializer(2)