Diff
checker
Text
Text
Images
Documents
Excel
Folders
Legal
Enterprise
Desktop
Pricing
Sign in
Download Diffchecker Desktop
Compare text
Find the difference between two text files
Tools
History
Display
Layout
Split
Unified
Real-time editor
Hide whitespace changes
Hide unchanged lines
Disable line wrap
Diff precision
Smart
Syntax
None
Change appearance
Process
Ignore
Transform text
Go to first change
Edit input
Diffchecker Desktop
The most secure way to run Diffchecker. Get the Diffchecker Desktop app: your diffs never leave your computer!
Get Desktop
LRTConverter
Created
12 months ago
Diff never expires
Clear
Export
Share
Explain
51 removals
Lines
Total
Removed
Characters
Total
Removed
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
196 lines
Copy
134 additions
Lines
Total
Added
Characters
Total
Added
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
272 lines
Copy
// SPDX-License-Identifier: BUSL-1.1
// SPDX-License-Identifier: BUSL-1.1
Copy
Copied
Copy
Copied
pragma solidity 0.8.
21
;
pragma solidity 0.8.
27
;
import { LRTConstants } from "./utils/LRTConstants.sol";
import { LRTConstants } from "./utils/LRTConstants.sol";
import { UtilLib } from "./utils/UtilLib.sol";
import { UtilLib } from "./utils/UtilLib.sol";
import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol";
import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol";
import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol";
import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol";
import { ILRTOracle } from "./interfaces/ILRTOracle.sol";
import { ILRTOracle } from "./interfaces/ILRTOracle.sol";
import { ILRTConverter } from "./interfaces/ILRTConverter.sol";
import { ILRTConverter } from "./interfaces/ILRTConverter.sol";
Copy
Copied
Copy
Copied
import { ILRTWithdrawalManager } from "./interfaces/ILRTWithdrawalManager.sol";
import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Copy
Copied
Copy
Copied
import {
SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {
ReentrancyGuardUpgradeable
import {
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 { UnstakeStETH } from "./unstaking-adapters/UnstakeStETH.sol";
import { UnstakeStETH } from "./unstaking-adapters/UnstakeStETH.sol";
Copy
Copied
Copy
Copied
/// @dev Legacy unstaking adapters for swETH are kept for upgrade compatibility
import { UnstakeSwETH } from "./unstaking-adapters/UnstakeSwETH.sol";
import { UnstakeSwETH } from "./unstaking-adapters/UnstakeSwETH.sol";
/// @title LRTConverter - Unstakes LSTs to ETH and swaps ETH to LSTs
/// @title LRTConverter - Unstakes LSTs to ETH and swaps ETH to LSTs
/// @notice This contract is responsible for unstaking LSTs to ETH and swapping ETH to LSTs
/// @notice This contract is responsible for unstaking LSTs to ETH and swapping ETH to LSTs
contract LRTConverter is
contract LRTConverter is
ILRTConverter,
ILRTConverter,
LRTConfigRoleChecker,
LRTConfigRoleChecker,
ReentrancyGuardUpgradeable,
ReentrancyGuardUpgradeable,
UnstakeSwETH,
UnstakeSwETH,
UnstakeStETH,
UnstakeStETH,
IERC721Receiver
IERC721Receiver
{
{
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;
mapping(bytes32 => bool) public _legacyProcessedWithdrawalRoots;
mapping(bytes32 => bool) public _legacyProcessedWithdrawalRoots;
Copy
Copied
Copy
Copied
mapping(address => bool) public
c
onvert
a
bleAssets;
mapping(address => bool) public
_legacyC
onvert
i
bleAssets;
mapping(address => uint256) public _legacyConversionLimit;
mapping(address => uint256) public _legacyConversionLimit;
Copy
Copied
Copy
Copied
//
needs to be added to total assets in protocol
//
needs to be added to total assets in protocol
uint256 public ethValueInWithdrawal;
uint256 public ethValueInWithdrawal;
Copy
Copied
Copy
Copied
modifier onlyConvertableAsset(address asset) {
mapping(address => bool) private whitelistedUsers;
require(convertableAssets[asset], "Asset not supported");
uint256 public whitelistedUnstakeAllowance;
modifier onlyWhitelistedUser() {
if (!isUserWhitelisted(msg.sender)) {
revert UserNotWhitelisted();
}
_;
}
/// @dev Modifier to enforce unstaking limits and update counters
/// @param amountToUnstake Amount of stETH to unstake
modifier withinUnstakeLimits(uint256 amountToUnstake) {
if (amountToUnstake == 0) {
revert InvalidAmount();
}
uint256 availableActiveETHWithdrawals = _getActiveETHUserWithdrawals();
if (amountToUnstake > whitelistedUnstakeAllowance + availableActiveETHWithdrawals) {
revert UnstakeLimitExceeded();
}
// Consume intended withdrawal limit
if (whitelistedUnstakeAllowance > 0) {
uint256 whitelistedAmountConsumed =
amountToUnstake > whitelistedUnstakeAllowance ? whitelistedUnstakeAllowance : amountToUnstake;
whitelistedUnstakeAllowance -= whitelistedAmountConsumed;
}
_;
_;
}
}
/// @custom:oz-upgrades-unsafe-allow constructor
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
constructor() {
_disableInitializers();
_disableInitializers();
}
}
/// @dev Initializes the contract
/// @dev 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);
__ReentrancyGuard_init();
__ReentrancyGuard_init();
lrtConfig = ILRTConfig(lrtConfigAddr);
lrtConfig = ILRTConfig(lrtConfigAddr);
emit UpdatedLRTConfig(lrtConfigAddr);
emit UpdatedLRTConfig(lrtConfigAddr);
}
}
/// @dev Initializes the contract
/// @dev Initializes the contract
/// @param _withdrawalQueueAddress Address of withdrawal queue (stETH)
/// @param _withdrawalQueueAddress Address of withdrawal queue (stETH)
/// @param _stETHAddress Address of stETH
/// @param _stETHAddress Address of stETH
/// @param _swEXITAddress Address of swEXIT (swETH)
/// @param _swEXITAddress Address of swEXIT (swETH)
/// @param _swETHAddress Address of swETH
/// @param _swETHAddress Address of swETH
function initialize2(
function initialize2(
address _withdrawalQueueAddress,
address _withdrawalQueueAddress,
address _stETHAddress,
address _stETHAddress,
address _swEXITAddress,
address _swEXITAddress,
address _swETHAddress
address _swETHAddress
)
)
external
external
reinitializer(2)
reinitializer(2)
onlyLRTAdmin
onlyLRTAdmin
{
{
__ReentrancyGuard_init();
__ReentrancyGuard_init();
__initializeSwETH(_swEXITAddress, _swETHAddress);
__initializeSwETH(_swEXITAddress, _swETHAddress);
__initializeStETH(_withdrawalQueueAddress, _stETHAddress);
__initializeStETH(_withdrawalQueueAddress, _stETHAddress);
}
}
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
return this.onERC721Received.selector;
return this.onERC721Received.selector;
}
}
/// @dev fallback to receive funds
/// @dev fallback to receive funds
receive() external payable { }
receive() external payable { }
/*////////////////////////////////////////////////////////////
/*////////////////////////////////////////////////////////////
write interactions
write interactions
//////////////////////////////////////////////////////////////*/
//////////////////////////////////////////////////////////////*/
Copy
Copied
Copy
Copied
/// @notice swap ETH for LST asset which is accepted by LRTConverter and send to LRTDepositPool
/// @dev use LRTOracle to get price for asset. Only callable by LRT Operator
/// @param asset Asset address to swap to
/// @param minimumExpectedReturnAmount Minimum asset amount to swap to
function swapEthToAsset(
address asset,
uint256 minimumExpectedReturnAmount
)
external
payable
onlyLRTOperator
onlyConvertableAsset(asset)
returns (uint256 returnAmount)
{
ILRTDepositPool lrtDepositPool = ILRTDepositPool(lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL));
uint256 ethAmountSent = msg.value;
returnAmount = lrtDepositPool.getSwapETHToAssetReturnAmount(asset, ethAmountSent);
if (returnAmount < minimumExpectedReturnAmount || IERC20(asset).balanceOf(address(this)) < returnAmount) {
revert NotEnoughAssetToTransfer();
}
// account for limits and the asset value in contract
_sendEthToDepositPool(ethAmountSent);
IERC20(asset).safeTransfer(msg.sender, returnAmount);
emit ETHSwappedForLST(ethAmountSent, asset, returnAmount);
}
/// @notice send asset from deposit pool to LRTConverter
/// @notice send asset from deposit pool to LRTConverter
/// @dev Only callable by LRT Operator and asset need to be approved
/// @dev Only callable by LRT Operator and asset need to be approved
/// @param _asset Asset address to send
/// @param _asset Asset address to send
/// @param _amount Asset amount to send
/// @param _amount Asset amount to send
function transferAssetFromDepositPool(
function transferAssetFromDepositPool(
address _asset,
address _asset,
uint256 _amount
uint256 _amount
)
)
external
external
Saved diffs
Original text
Open file
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { LRTConstants } from "./utils/LRTConstants.sol"; import { UtilLib } from "./utils/UtilLib.sol"; import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol"; import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol"; import { ILRTOracle } from "./interfaces/ILRTOracle.sol"; import { ILRTConverter } from "./interfaces/ILRTConverter.sol"; import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { UnstakeStETH } from "./unstaking-adapters/UnstakeStETH.sol"; import { UnstakeSwETH } from "./unstaking-adapters/UnstakeSwETH.sol"; /// @title LRTConverter - Unstakes LSTs to ETH and swaps ETH to LSTs /// @notice This contract is responsible for unstaking LSTs to ETH and swapping ETH to LSTs contract LRTConverter is ILRTConverter, LRTConfigRoleChecker, ReentrancyGuardUpgradeable, UnstakeSwETH, UnstakeStETH, IERC721Receiver { using SafeERC20 for IERC20; mapping(bytes32 => bool) public _legacyProcessedWithdrawalRoots; mapping(address => bool) public convertableAssets; mapping(address => uint256) public _legacyConversionLimit; //needs to be added to total assets in protocol uint256 public ethValueInWithdrawal; modifier onlyConvertableAsset(address asset) { require(convertableAssets[asset], "Asset not supported"); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @dev Initializes the contract /// @param lrtConfigAddr LRT config address function initialize(address lrtConfigAddr) external initializer { UtilLib.checkNonZeroAddress(lrtConfigAddr); __ReentrancyGuard_init(); lrtConfig = ILRTConfig(lrtConfigAddr); emit UpdatedLRTConfig(lrtConfigAddr); } /// @dev Initializes the contract /// @param _withdrawalQueueAddress Address of withdrawal queue (stETH) /// @param _stETHAddress Address of stETH /// @param _swEXITAddress Address of swEXIT (swETH) /// @param _swETHAddress Address of swETH function initialize2( address _withdrawalQueueAddress, address _stETHAddress, address _swEXITAddress, address _swETHAddress ) external reinitializer(2) onlyLRTAdmin { __ReentrancyGuard_init(); __initializeSwETH(_swEXITAddress, _swETHAddress); __initializeStETH(_withdrawalQueueAddress, _stETHAddress); } function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC721Received.selector; } /// @dev fallback to receive funds receive() external payable { } /*//////////////////////////////////////////////////////////// write interactions //////////////////////////////////////////////////////////////*/ /// @notice swap ETH for LST asset which is accepted by LRTConverter and send to LRTDepositPool /// @dev use LRTOracle to get price for asset. Only callable by LRT Operator /// @param asset Asset address to swap to /// @param minimumExpectedReturnAmount Minimum asset amount to swap to function swapEthToAsset( address asset, uint256 minimumExpectedReturnAmount ) external payable onlyLRTOperator onlyConvertableAsset(asset) returns (uint256 returnAmount) { ILRTDepositPool lrtDepositPool = ILRTDepositPool(lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL)); uint256 ethAmountSent = msg.value; returnAmount = lrtDepositPool.getSwapETHToAssetReturnAmount(asset, ethAmountSent); if (returnAmount < minimumExpectedReturnAmount || IERC20(asset).balanceOf(address(this)) < returnAmount) { revert NotEnoughAssetToTransfer(); } // account for limits and the asset value in contract _sendEthToDepositPool(ethAmountSent); IERC20(asset).safeTransfer(msg.sender, returnAmount); emit ETHSwappedForLST(ethAmountSent, asset, returnAmount); } /// @notice send asset from deposit pool to LRTConverter /// @dev Only callable by LRT Operator and asset need to be approved /// @param _asset Asset address to send /// @param _amount Asset amount to send function transferAssetFromDepositPool( address _asset, uint256 _amount ) external onlyConvertableAsset(_asset) onlyLRTOperator { address lrtDepositPoolAddress = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL); address lrtOracleAddress = lrtConfig.getContract(LRTConstants.LRT_ORACLE); ILRTOracle lrtOracle = ILRTOracle(lrtOracleAddress); ethValueInWithdrawal += (_amount * lrtOracle.getAssetPrice(_asset)) / 1e18; IERC20(_asset).safeTransferFrom(lrtDepositPoolAddress, address(this), _amount); } /// @notice raises a unstake request for steth on lido function unstakeStEth(uint256 amountToUnstake) external onlyLRTOperator { _unstakeStEth(amountToUnstake); } /// @notice claim eth from lido for steth and sends to deposit pool function claimStEth(uint256 _requestId, uint256 _hint) external onlyLRTOperator { _claimStEth(_requestId, _hint); _sendEthToDepositPool(address(this).balance); } /// @notice raises a unstake request for sweth on swell function unstakeSwEth(uint256 amountToUnstake) external onlyLRTOperator { _unstakeSwEth(amountToUnstake); } /// @notice claim eth from sweth from swell for sweth and sends to deposit pool function claimSwEth(uint256 _tokenId) external onlyLRTOperator { _claimSwEth(_tokenId); _sendEthToDepositPool(address(this).balance); } /*//////////////////////////////////////////////////////////// setters interactions //////////////////////////////////////////////////////////////*/ /// @notice Add convertable asset /// @param asset Asset address function addConvertableAsset(address asset) external onlyLRTManager { convertableAssets[asset] = true; } /// @notice Remove convertable asset /// @param asset Asset address function removeConvertableAsset(address asset) external onlyLRTManager { convertableAssets[asset] = false; } /*//////////////////////////////////////////////////////////// internal functions //////////////////////////////////////////////////////////////*/ function _sendEthToDepositPool(uint256 _amount) internal { address lrtDepositPoolAddress = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL); if (ethValueInWithdrawal > _amount) { ethValueInWithdrawal -= _amount; } else { ethValueInWithdrawal = 0; } // Send eth to deposit pool ILRTDepositPool(lrtDepositPoolAddress).receiveFromLRTConverter{ value: _amount }(); emit EthTransferred(lrtDepositPoolAddress, _amount); } }
Changed text
Open file
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.27; import { LRTConstants } from "./utils/LRTConstants.sol"; import { UtilLib } from "./utils/UtilLib.sol"; import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol"; import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol"; import { ILRTOracle } from "./interfaces/ILRTOracle.sol"; import { ILRTConverter } from "./interfaces/ILRTConverter.sol"; import { ILRTWithdrawalManager } from "./interfaces/ILRTWithdrawalManager.sol"; import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { UnstakeStETH } from "./unstaking-adapters/UnstakeStETH.sol"; /// @dev Legacy unstaking adapters for swETH are kept for upgrade compatibility import { UnstakeSwETH } from "./unstaking-adapters/UnstakeSwETH.sol"; /// @title LRTConverter - Unstakes LSTs to ETH and swaps ETH to LSTs /// @notice This contract is responsible for unstaking LSTs to ETH and swapping ETH to LSTs contract LRTConverter is ILRTConverter, LRTConfigRoleChecker, ReentrancyGuardUpgradeable, UnstakeSwETH, UnstakeStETH, IERC721Receiver { using SafeERC20 for IERC20; mapping(bytes32 => bool) public _legacyProcessedWithdrawalRoots; mapping(address => bool) public _legacyConvertibleAssets; mapping(address => uint256) public _legacyConversionLimit; // needs to be added to total assets in protocol uint256 public ethValueInWithdrawal; mapping(address => bool) private whitelistedUsers; uint256 public whitelistedUnstakeAllowance; modifier onlyWhitelistedUser() { if (!isUserWhitelisted(msg.sender)) { revert UserNotWhitelisted(); } _; } /// @dev Modifier to enforce unstaking limits and update counters /// @param amountToUnstake Amount of stETH to unstake modifier withinUnstakeLimits(uint256 amountToUnstake) { if (amountToUnstake == 0) { revert InvalidAmount(); } uint256 availableActiveETHWithdrawals = _getActiveETHUserWithdrawals(); if (amountToUnstake > whitelistedUnstakeAllowance + availableActiveETHWithdrawals) { revert UnstakeLimitExceeded(); } // Consume intended withdrawal limit if (whitelistedUnstakeAllowance > 0) { uint256 whitelistedAmountConsumed = amountToUnstake > whitelistedUnstakeAllowance ? whitelistedUnstakeAllowance : amountToUnstake; whitelistedUnstakeAllowance -= whitelistedAmountConsumed; } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @dev Initializes the contract /// @param lrtConfigAddr LRT config address function initialize(address lrtConfigAddr) external initializer { UtilLib.checkNonZeroAddress(lrtConfigAddr); __ReentrancyGuard_init(); lrtConfig = ILRTConfig(lrtConfigAddr); emit UpdatedLRTConfig(lrtConfigAddr); } /// @dev Initializes the contract /// @param _withdrawalQueueAddress Address of withdrawal queue (stETH) /// @param _stETHAddress Address of stETH /// @param _swEXITAddress Address of swEXIT (swETH) /// @param _swETHAddress Address of swETH function initialize2( address _withdrawalQueueAddress, address _stETHAddress, address _swEXITAddress, address _swETHAddress ) external reinitializer(2) onlyLRTAdmin { __ReentrancyGuard_init(); __initializeSwETH(_swEXITAddress, _swETHAddress); __initializeStETH(_withdrawalQueueAddress, _stETHAddress); } function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC721Received.selector; } /// @dev fallback to receive funds receive() external payable { } /*//////////////////////////////////////////////////////////// write interactions //////////////////////////////////////////////////////////////*/ /// @notice send asset from deposit pool to LRTConverter /// @dev Only callable by LRT Operator and asset need to be approved /// @param _asset Asset address to send /// @param _amount Asset amount to send function transferAssetFromDepositPool( address _asset, uint256 _amount ) external onlySupportedERC20Token(_asset) onlyLRTOperator { address lrtDepositPoolAddress = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL); address lrtOracleAddress = lrtConfig.getContract(LRTConstants.LRT_ORACLE); ILRTOracle lrtOracle = ILRTOracle(lrtOracleAddress); ethValueInWithdrawal += (_amount * lrtOracle.getAssetPrice(_asset)) / 1e18; IERC20(_asset).safeTransferFrom(lrtDepositPoolAddress, address(this), _amount); } /// @notice send asset from LRTConverter to deposit pool /// @dev Only callable by LRT Operator and asset need to be approved /// @param _asset Asset address to send /// @param _amount Asset amount to send function transferAssetToDepositPool( address _asset, uint256 _amount ) external onlySupportedERC20Token(_asset) onlyLRTOperator { address lrtDepositPoolAddress = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL); address lrtOracleAddress = lrtConfig.getContract(LRTConstants.LRT_ORACLE); ILRTOracle lrtOracle = ILRTOracle(lrtOracleAddress); uint256 assetValue = (_amount * lrtOracle.getAssetPrice(_asset)) / 1e18; // Set to 0 if assetValue exceeds ethValueInWithdrawal, otherwise subtract assetValue ethValueInWithdrawal = ethValueInWithdrawal > assetValue ? ethValueInWithdrawal - assetValue : 0; IERC20(_asset).safeTransfer(lrtDepositPoolAddress, _amount); } /// @notice raises a unstake request for steth on lido /// @param amountToUnstake Amount of stETH to unstake function unstakeStEth(uint256 amountToUnstake) external nonReentrant onlyLRTOperator withinUnstakeLimits(amountToUnstake) { _unstakeStEth(amountToUnstake); } /// @notice claim eth from lido for steth and sends to deposit pool function claimStEth(uint256 _requestId, uint256 _hint) external nonReentrant onlyLRTOperator { _claimStEth(_requestId, _hint); _sendEthToDepositPool(address(this).balance); } /// @notice raises a unstake request for sweth on swell function unstakeSwEth(uint256 amountToUnstake) external nonReentrant onlyLRTOperator { _unstakeSwEth(amountToUnstake); } /// @notice claim eth from sweth from swell for sweth and sends to deposit pool function claimSwEth(uint256 _tokenId) external nonReentrant onlyLRTOperator { _claimSwEth(_tokenId); _sendEthToDepositPool(address(this).balance); } /// @notice Add or remove a user from the whitelist /// @param user User address /// @param whitelisted Whether to whitelist or remove from whitelist function setUserWhitelisted(address user, bool whitelisted) external onlyLRTManager { whitelistedUsers[user] = whitelisted; emit UserWhitelisted(user, whitelisted); } /// @notice Batch add or remove users from the whitelist /// @param users Array of user addresses /// @param whitelisted Whether to whitelist or remove from whitelist function batchSetUserWhitelisted(address[] calldata users, bool whitelisted) external onlyLRTManager { for (uint256 i = 0; i < users.length; i++) { whitelistedUsers[users[i]] = whitelisted; emit UserWhitelisted(users[i], whitelisted); } } /// @notice Declare withdrawal intent (only whitelisted users) /// @param amount Amount of stETH to declare for withdrawal function declareWithdrawalIntent(uint256 amount) external nonReentrant onlyWhitelistedUser { if (amount == 0) { revert InvalidAmount(); } uint256 maxWhitelistedAllowance = 1_000_000_000 ether; if (whitelistedUnstakeAllowance + amount > maxWhitelistedAllowance) { revert WhitelistedAllowanceExceeded(); } whitelistedUnstakeAllowance = whitelistedUnstakeAllowance + amount; emit WithdrawalIntentDeclared(msg.sender, amount); } /*//////////////////////////////////////////////////////////// view functions //////////////////////////////////////////////////////////////*/ /// @notice Get the current unstaking limits and usage /// @return whitelistedAllowance Current whitelisted unstake allowance /// @return activeETHWithdrawals Current active ETH withdrawals function getUnstakeLimits() external view returns (uint256 whitelistedAllowance, uint256 activeETHWithdrawals) { whitelistedAllowance = whitelistedUnstakeAllowance; activeETHWithdrawals = _getActiveETHUserWithdrawals(); } /// @notice Check if a user is whitelisted /// @param user User address to check /// @return True if user is whitelisted function isUserWhitelisted(address user) public view returns (bool) { return whitelistedUsers[user]; } /*//////////////////////////////////////////////////////////// internal functions //////////////////////////////////////////////////////////////*/ function _sendEthToDepositPool(uint256 _amount) internal { address lrtDepositPoolAddress = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL); if (ethValueInWithdrawal > _amount) { ethValueInWithdrawal -= _amount; } else { ethValueInWithdrawal = 0; } // Send eth to deposit pool ILRTDepositPool(lrtDepositPoolAddress).receiveFromLRTConverter{ value: _amount }(); emit EthTransferred(lrtDepositPoolAddress, _amount); } /// @dev Get active user ETH withdrawals from LRTWithdrawalManager function _getActiveETHUserWithdrawals() internal view returns (uint256 activeETHWithdrawals) { ILRTWithdrawalManager lrtWithdrawalManager = ILRTWithdrawalManager(lrtConfig.getContract(LRTConstants.LRT_WITHDRAW_MANAGER)); activeETHWithdrawals = lrtWithdrawalManager.assetsCommitted(LRTConstants.ETH_TOKEN); } }
Find difference