Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 20039666 | 155 days ago | IN | 0 ETH | 0.01779995 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LRTUnstakingVault
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 10000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { UtilLib } from "./utils/UtilLib.sol"; import { LRTConstants } from "./utils/LRTConstants.sol"; import { LRTConfigRoleChecker, ILRTConfig } from "./utils/LRTConfigRoleChecker.sol"; import { INodeDelegator } from "./interfaces/INodeDelegator.sol"; import { IStrategy } from "./external/eigenlayer/interfaces/IStrategy.sol"; import { IEigenDelegationManager } from "./external/eigenlayer/interfaces/IEigenDelegationManager.sol"; import { IEigenDelayedWithdrawalRouter } from "./external/eigenlayer/interfaces/IEigenDelayedWithdrawalRouter.sol"; import { ILRTWithdrawalManager } from "./interfaces/ILRTWithdrawalManager.sol"; import { ILRTDepositPool } from "./interfaces/ILRTDepositPool.sol"; import { ILRTUnstakingVault } from "./interfaces/ILRTUnstakingVault.sol"; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title LRTUnstakingVault Contract /// @notice The contract that handles the unstaking of assets contract LRTUnstakingVault is ILRTUnstakingVault, LRTConfigRoleChecker, PausableUpgradeable, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; // Mapping from asset addresses to the total number of shares currently undergoing the unstaking process in // EigenLayer. This count is critical for accurately calculating the price of assets. mapping(address asset => uint256) public sharesUnstaking; modifier onlyLRTNodeDelegator() { ILRTDepositPool lrtDepositPool = ILRTDepositPool(lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL)); if (lrtDepositPool.isNodeDelegator(msg.sender) != 1) { revert CallerNotLRTNodeDelegator(); } _; } modifier onlyLRTWithdrawalManager() { if (msg.sender != lrtConfig.getContract(LRTConstants.LRT_WITHDRAW_MANAGER)) { revert CallerNotLRTWithdrawalManager(); } _; } /// @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); __Pausable_init(); __ReentrancyGuard_init(); lrtConfig = ILRTConfig(lrtConfigAddr); emit UpdatedLRTConfig(lrtConfigAddr); } /*////////////////////////////////////////////////////////////// receive functions //////////////////////////////////////////////////////////////*/ receive() external payable { emit EthReceived(msg.sender, msg.value); } /// @dev receive from LRTDepositPool function receiveFromLRTDepositPool() external payable { } /// @dev receive from NodeDelegator function receiveFromNodeDelegator() external payable { } /*////////////////////////////////////////////////////////////// write functions //////////////////////////////////////////////////////////////*/ /// @notice This is used by withdrawal manager when unlocking assets. The unlocked assets are pulled from the vault /// and used to pay the user. /// @param asset The asset address. /// @param amount The amount of asset to redeem. function redeem(address asset, uint256 amount) external nonReentrant onlyLRTWithdrawalManager { if (asset == LRTConstants.ETH_TOKEN) { ILRTWithdrawalManager(msg.sender).receiveFromLRTUnstakingVault{ value: amount }(); } else { IERC20(asset).safeTransfer(msg.sender, amount); } } /// @notice Adds shares that are in unstaking process. /// @param asset The asset address. /// @param amount The amount of shares added to the unstaking pool. /// @dev This function is only callable by the NodeDelegator contracts when it initiates unstaking process. function addSharesUnstaking(address asset, uint256 amount) external onlyLRTNodeDelegator { // Increase the tracking of shares currently in the process of unstaking from Eigenlayer. sharesUnstaking[asset] += amount; } /// @notice Adds shares that are in unstaking process. /// @param asset The asset address. /// @param amount The amount of shares added to the unstaking pool. /// @dev This function is only callable by the NodeDelegator contracts when it initiates unstaking process. function reduceSharesUnstaking(address asset, uint256 amount) external onlyLRTNodeDelegator { // Increase the tracking of shares currently in the process of unstaking from Eigenlayer. sharesUnstaking[asset] -= amount; } /*////////////////////////////////////////////////////////////// view functions //////////////////////////////////////////////////////////////*/ /// @notice Returns the total asset amount in unstaking process. /// @param asset The asset address. /// @return The total asset amount in unstaking process. function getAssetsUnstaking(address asset) external view onlySupportedAsset(asset) returns (uint256) { if (asset == LRTConstants.ETH_TOKEN) { return sharesUnstaking[asset]; } IStrategy strategy = IStrategy(lrtConfig.assetStrategy(asset)); return strategy.sharesToUnderlyingView(sharesUnstaking[asset]); } /// @notice Returns the the vaults balance of the asset. /// @param asset The asset address. /// @return The balance of the asset. function balanceOf(address asset) external view returns (uint256) { if (asset == LRTConstants.ETH_TOKEN) { return address(this).balance; } else { return IERC20(asset).balanceOf(address(this)); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; /// @title UtilLib - Utility library /// @notice Utility functions library UtilLib { error ZeroAddressNotAllowed(); /// @dev zero address check modifier /// @param address_ address to check function checkNonZeroAddress(address address_) internal pure { if (address_ == address(0)) revert ZeroAddressNotAllowed(); } function getMin(uint256 a, uint256 b) internal pure returns (uint256) { if (a < b) return a; return b; } function getMax(uint256 a, uint256 b) internal pure returns (uint256) { if (a > b) return a; return b; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; library LRTConstants { //tokens //rETH token bytes32 public constant R_ETH_TOKEN = keccak256("R_ETH_TOKEN"); //stETH token bytes32 public constant ST_ETH_TOKEN = keccak256("ST_ETH_TOKEN"); //cbETH token bytes32 public constant CB_ETH_TOKEN = keccak256("CB_ETH_TOKEN"); //ETHX token bytes32 public constant ETHX_TOKEN = keccak256("ETHX_TOKEN"); //sfrxETH bytes32 public constant SFRX_ETH_TOKEN = keccak256("SFRX_ETH_TOKEN"); bytes32 public constant BEACON_CHAIN_ETH_STRATEGY = keccak256("BEACON_CHAIN_ETH_STRATEGY"); //contracts bytes32 public constant LRT_ORACLE = keccak256("LRT_ORACLE"); bytes32 public constant LRT_DEPOSIT_POOL = keccak256("LRT_DEPOSIT_POOL"); bytes32 public constant LRT_WITHDRAW_MANAGER = keccak256("LRT_WITHDRAW_MANAGER"); bytes32 public constant LRT_UNSTAKING_VAULT = keccak256("LRT_UNSTAKING_VAULT"); bytes32 public constant LRT_CONVERTER = keccak256("LRT_CONVERTER"); bytes32 public constant EIGEN_STRATEGY_MANAGER = keccak256("EIGEN_STRATEGY_MANAGER"); //Roles bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; bytes32 public constant MANAGER = keccak256("MANAGER"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); // updated library variables bytes32 public constant SFRXETH_TOKEN = keccak256("SFRXETH_TOKEN"); // add new vars below bytes32 public constant EIGEN_POD_MANAGER = keccak256("EIGEN_POD_MANAGER"); // native ETH as ERC20 for ease of implementation address public constant ETH_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // Operator Role bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); // reward receiver contract bytes32 public constant REWARD_RECEIVER = keccak256("REWARD_RECEIVER"); // EigenLayer Delegation Manager bytes32 public constant EIGEN_DELEGATION_MANAGER = keccak256("EIGEN_DELEGATION_MANAGER"); uint256 public constant ONE_E_9 = 1e9; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { UtilLib } from "./UtilLib.sol"; import { LRTConstants } from "./LRTConstants.sol"; import { ILRTConfig } from "../interfaces/ILRTConfig.sol"; import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol"; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; /// @title LRTConfigRoleChecker - LRT Config Role Checker Contract /// @notice Handles LRT config role checks abstract contract LRTConfigRoleChecker { ILRTConfig public lrtConfig; // events event UpdatedLRTConfig(address indexed lrtConfig); // modifiers modifier onlyRole(bytes32 role) { if (!IAccessControl(address(lrtConfig)).hasRole(role, msg.sender)) { string memory roleStr = string(abi.encodePacked(role)); revert ILRTConfig.CallerNotLRTConfigAllowedRole(roleStr); } _; } modifier onlyLRTManager() { if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.MANAGER, msg.sender)) { revert ILRTConfig.CallerNotLRTConfigManager(); } _; } modifier onlyLRTOperator() { if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.OPERATOR_ROLE, msg.sender)) { revert ILRTConfig.CallerNotLRTConfigOperator(); } _; } modifier onlyLRTAdmin() { if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.DEFAULT_ADMIN_ROLE, msg.sender)) { revert ILRTConfig.CallerNotLRTConfigAdmin(); } _; } modifier onlySupportedAsset(address asset) { if (!lrtConfig.isSupportedAsset(asset)) { revert ILRTConfig.AssetNotSupported(); } _; } // setters /// @notice Updates the LRT config contract /// @dev only callable by LRT admin /// @param lrtConfigAddr the new LRT config contract Address function updateLRTConfig(address lrtConfigAddr) external virtual onlyLRTAdmin { if (address(lrtConfig) != address(0)) revert ILRTConfig.ValueAlreadyInUse(); UtilLib.checkNonZeroAddress(lrtConfigAddr); lrtConfig = ILRTConfig(lrtConfigAddr); emit UpdatedLRTConfig(lrtConfigAddr); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IStrategy, IERC20 } from "contracts/external/eigenlayer/interfaces/IStrategy.sol"; import { IEigenDelegationManager } from "contracts/external/eigenlayer/interfaces/IEigenDelegationManager.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface INodeDelegator { // event event AssetDepositIntoStrategy(address indexed asset, address indexed strategy, uint256 depositAmount); event ETHDepositFromDepositPool(uint256 depositAmount); event EigenPodCreated(address indexed eigenPod, address indexed podOwner); event ETHStaked(bytes valPubKey, uint256 amount); event WithdrawalQueued(uint256 nonce, address withdrawer, bytes32[] withdrawalRoots); event EthTransferred(address to, uint256 amount); event EigenLayerWithdrawalCompleted(address indexed depositor, uint256 nonce, address indexed caller); event ETHRewardsReceived(uint256 amount); event ETHExtraStakeToReceiveIncremented(uint256 amount); event ExtraStakeReceived(uint256 amount); event ETHRewardsWithdrawInitiated(uint256 amount); event ElSharesDelegated(address indexed elOperator); event RestakingActivated(); event ETHReceived(address indexed sender, uint256 amount); event Undelegated(); // errors error TokenTransferFailed(); error StrategyIsNotSetForAsset(); error InvalidETHSender(); error InvalidDepositRoot(bytes32 expectedDepositRoot, bytes32 actualDepositRoot); error StrategyMustNotBeBeaconChain(); error InsufficientStakedButUnverifiedNativeETH(); error InvalidWithdrawalData(); // getter function stakedButUnverifiedNativeETH() external view returns (uint256); // write functions function depositAssetIntoStrategy(address asset) external; function maxApproveToEigenStrategyManager(address asset) external; function initiateUnstaking( IStrategy[] calldata strategies, uint256[] calldata shares ) external returns (bytes32 withdrawalRoot); function completeUnstaking( IEigenDelegationManager.Withdrawal calldata withdrawal, IERC20[] calldata assets, uint256 middlewareTimesIndex ) external; // view functions function getAssetBalances() external view returns (address[] memory, uint256[] memory); function getAssetBalance(address asset) external view returns (uint256); function getETHEigenPodBalance() external view returns (uint256); function transferBackToLRTDepositPool(address asset, uint256 amount) external; function sendETHFromDepositPoolToNDC() external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title Minimal interface for an `Strategy` contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice Custom `Strategy` implementations may expand extensively on this interface. */ interface IStrategy { // packed struct for queued withdrawals; helps deal with stack-too-deep errors struct WithdrawerAndNonce { address withdrawer; uint96 nonce; } struct QueuedWithdrawal { IStrategy[] strategies; uint256[] shares; address depositor; WithdrawerAndNonce withdrawerAndNonce; uint32 withdrawalStartBlock; address delegatedAddress; } /** * @notice Used to deposit tokens into this Strategy * @param token is the ERC20 token being deposited * @param amount is the amount of token being deposited * @dev This function is only callable by the strategyManager contract. It is invoked inside of the * strategyManager's * `depositIntoStrategy` function, and individual share balances are recorded in the strategyManager as well. * @return newShares is the number of new shares issued at the current exchange ratio. */ function deposit(IERC20 token, uint256 amount) external returns (uint256); /** * @notice Used to withdraw tokens from this Strategy, to the `depositor`'s address * @param depositor is the address to receive the withdrawn funds * @param token is the ERC20 token being transferred out * @param amountShares is the amount of shares being withdrawn * @dev This function is only callable by the strategyManager contract. It is invoked inside of the * strategyManager's * other functions, and individual share balances are recorded in the strategyManager as well. */ function withdraw(address depositor, IERC20 token, uint256 amountShares) external; /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. * @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications * @param amountShares is the amount of shares to calculate its conversion into the underlying token * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function sharesToUnderlying(uint256 amountShares) external returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. * @notice In contrast to `underlyingToSharesView`, this function **may** make state modifications * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function underlyingToShares(uint256 amountUnderlying) external returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications */ function userUnderlying(address user) external returns (uint256); /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. * @notice In contrast to `sharesToUnderlying`, this function guarantees no state modifications * @param amountShares is the amount of shares to calculate its conversion into the underlying token * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. * @notice In contrast to `underlyingToShares`, this function guarantees no state modifications * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications */ function userUnderlyingView(address user) external view returns (uint256); /// @notice The underlying token for shares in this Strategy function underlyingToken() external view returns (IERC20); /// @notice The total number of extant shares in this Strategy function totalShares() external view returns (uint256); /// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that /// explains in more detail. function explanation() external view returns (string memory); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import "./IStrategy.sol"; /** * @title DelegationManager * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice This is the contract for delegation in EigenLayer. The main functionalities of this contract are * - enabling anyone to register as an operator in EigenLayer * - allowing operators to specify parameters related to stakers who delegate to them * - enabling any staker to delegate its stake to the operator of its choice (a given staker can only delegate to a * single operator at a time) * - enabling a staker to undelegate its assets from the operator it is delegated to (performed as part of the * withdrawal process, initiated through the StrategyManager) */ interface IEigenDelegationManager { // @notice Struct used for storing information about a single operator who has registered with EigenLayer struct OperatorDetails { // @notice address to receive the rewards that the operator earns via serving applications built on EigenLayer. address earningsReceiver; /** * @notice Address to verify signatures when a staker wishes to delegate to the operator, as well as controlling * "forced undelegations". * @dev Signature verification follows these rules: * 1) If this address is left as address(0), then any staker will be free to delegate to the operator, i.e. no * signature verification will be performed. * 2) If this address is an EOA (i.e. it has no code), then we follow standard ECDSA signature verification for * delegations to the operator. * 3) If this address is a contract (i.e. it has code) then we forward a call to the contract and verify that it * returns the correct EIP-1271 "magic value". */ address delegationApprover; /** * @notice A minimum delay -- measured in blocks -- enforced between: * 1) the operator signalling their intent to register for a service, via calling `Slasher.optIntoSlashing` * and * 2) the operator completing registration for the service, via the service ultimately calling * `Slasher.recordFirstStakeUpdate` * @dev note that for a specific operator, this value *cannot decrease*, i.e. if the operator wishes to modify * their OperatorDetails, * then they are only allowed to either increase this value or keep it the same. */ uint32 stakerOptOutWindowBlocks; } /** * @notice Abstract struct used in calculating an EIP712 signature for a staker to approve that they (the staker * themselves) delegate to a specific operator. * @dev Used in computing the `STAKER_DELEGATION_TYPEHASH` and as a reference in the computation of the * stakerDigestHash in the `delegateToBySignature` function. */ struct StakerDelegation { // the staker who is delegating address staker; // the operator being delegated to address operator; // the staker's nonce uint256 nonce; // the expiration timestamp (UTC) of the signature uint256 expiry; } /** * @notice Abstract struct used in calculating an EIP712 signature for an operator's delegationApprover to approve * that a specific staker delegate to the operator. * @dev Used in computing the `DELEGATION_APPROVAL_TYPEHASH` and as a reference in the computation of the * approverDigestHash in the `_delegate` function. */ struct DelegationApproval { // the staker who is delegating address staker; // the operator being delegated to address operator; // the operator's provided salt bytes32 salt; // the expiration timestamp (UTC) of the signature uint256 expiry; } /** * Struct type used to specify an existing queued withdrawal. Rather than storing the entire struct, only a hash is * stored. * In functions that operate on existing queued withdrawals -- e.g. completeQueuedWithdrawal`, the data is * resubmitted and the hash of the submitted * data is computed by `calculateWithdrawalRoot` and checked against the stored hash in order to confirm the * integrity of the submitted data. */ struct Withdrawal { // The address that originated the Withdrawal address staker; // The address that the staker was delegated to at the time that the Withdrawal was created address delegatedTo; // The address that can complete the Withdrawal + will receive funds when completing the withdrawal address withdrawer; // Nonce used to guarantee that otherwise identical withdrawals have unique hashes uint256 nonce; // Block number when the Withdrawal was created uint32 startBlock; // Array of strategies that the Withdrawal contains IStrategy[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; } struct QueuedWithdrawalParams { // Array of strategies that the QueuedWithdrawal contains IStrategy[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; // The address of the withdrawer address withdrawer; } // @notice Emitted when a new operator registers in EigenLayer and provides their OperatorDetails. event OperatorRegistered(address indexed operator, OperatorDetails operatorDetails); /// @notice Emitted when an operator updates their OperatorDetails to @param newOperatorDetails event OperatorDetailsModified(address indexed operator, OperatorDetails newOperatorDetails); /** * @notice Emitted when @param operator indicates that they are updating their MetadataURI string * @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain * indexing */ event OperatorMetadataURIUpdated(address indexed operator, string metadataURI); /// @notice Emitted whenever an operator's shares are increased for a given strategy. Note that shares is the delta /// in the operator's shares. event OperatorSharesIncreased(address indexed operator, address staker, IStrategy strategy, uint256 shares); /// @notice Emitted whenever an operator's shares are decreased for a given strategy. Note that shares is the delta /// in the operator's shares. event OperatorSharesDecreased(address indexed operator, address staker, IStrategy strategy, uint256 shares); /// @notice Emitted when @param staker delegates to @param operator. event StakerDelegated(address indexed staker, address indexed operator); /// @notice Emitted when @param staker undelegates from @param operator. event StakerUndelegated(address indexed staker, address indexed operator); /// @notice Emitted when @param staker is undelegated via a call not originating from the staker themself event StakerForceUndelegated(address indexed staker, address indexed operator); /** * @notice Emitted when a new withdrawal is queued. * @param withdrawalRoot Is the hash of the `withdrawal`. * @param withdrawal Is the withdrawal itself. */ event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal); /// @notice Emitted when a queued withdrawal is completed event WithdrawalCompleted(bytes32 withdrawalRoot); /// @notice Emitted when a queued withdrawal is *migrated* from the StrategyManager to the DelegationManager event WithdrawalMigrated(bytes32 oldWithdrawalRoot, bytes32 newWithdrawalRoot); /// @notice Emitted when the `minWithdrawalDelayBlocks` variable is modified from `previousValue` to `newValue`. event MinWithdrawalDelayBlocksSet(uint256 previousValue, uint256 newValue); /// @notice Emitted when the `strategyWithdrawalDelayBlocks` variable is modified from `previousValue` to /// `newValue`. event StrategyWithdrawalDelayBlocksSet(IStrategy strategy, uint256 previousValue, uint256 newValue); function pendingWithdrawals(bytes32 withdrawalRoot) external view returns (bool); /** * @notice Registers the caller as an operator in EigenLayer. * @param registeringOperatorDetails is the `OperatorDetails` for the operator. * @param metadataURI is a URI for the operator's metadata, i.e. a link providing more details on the operator. * * @dev Once an operator is registered, they cannot 'deregister' as an operator, and they will forever be considered * "delegated to themself". * @dev This function will revert if the caller attempts to set their `earningsReceiver` to address(0). * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event */ function registerAsOperator( OperatorDetails calldata registeringOperatorDetails, string calldata metadataURI ) external; /** * @notice Updates an operator's stored `OperatorDetails`. * @param newOperatorDetails is the updated `OperatorDetails` for the operator, to replace their current * OperatorDetails`. * * @dev The caller must have previously registered as an operator in EigenLayer. * @dev This function will revert if the caller attempts to set their `earningsReceiver` to address(0). */ function modifyOperatorDetails(OperatorDetails calldata newOperatorDetails) external; /** * @notice Called by an operator to emit an `OperatorMetadataURIUpdated` event indicating the information has * updated. * @param metadataURI The URI for metadata associated with an operator * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event */ function updateOperatorMetadataURI(string calldata metadataURI) external; /** * @notice Undelegates the staker from the operator who they are delegated to. Puts the staker into the * "undelegation limbo" mode of the EigenPodManager * and queues a withdrawal of all of the staker's shares in the StrategyManager (to the staker), if necessary. * @param staker The account to be undelegated. * @return withdrawalRoot The root of the newly queued withdrawal, if a withdrawal was queued. Otherwise just * bytes32(0). * * @dev Reverts if the `staker` is also an operator, since operators are not allowed to undelegate from themselves. * @dev Reverts if the caller is not the staker, nor the operator who the staker is delegated to, nor the operator's * specified "delegationApprover" * @dev Reverts if the `staker` is already undelegated. */ function undelegate(address staker) external returns (bytes32[] memory withdrawalRoot); /** * Allows a staker to withdraw some shares. Withdrawn shares/strategies are immediately removed * from the staker. If the staker is delegated, withdrawn shares/strategies are also removed from * their operator. * * All withdrawn shares/strategies are placed in a queue and can be fully withdrawn after a delay. */ function queueWithdrawals(QueuedWithdrawalParams[] calldata queuedWithdrawalParams) external returns (bytes32[] memory); /** * @notice Used to complete the specified `withdrawal`. The caller must match `withdrawal.withdrawer` * @param withdrawal The Withdrawal to complete. * @param tokens Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th * Strategy in the `withdrawal.strategies` array. * This input can be provided with zero length if `receiveAsTokens` is set to 'false' (since in that case, this * input will be unused) * @param middlewareTimesIndex is the index in the operator that the staker who triggered the withdrawal was * delegated to's middleware times array * @param receiveAsTokens If true, the shares specified in the withdrawal will be withdrawn from the specified * strategies themselves * and sent to the caller, through calls to `withdrawal.strategies[i].withdraw`. If false, then the shares in the * specified strategies * will simply be transferred to the caller directly. * @dev middlewareTimesIndex should be calculated off chain before calling this function by finding the first index * that satisfies `slasher.canWithdraw` * @dev beaconChainETHStrategy shares are non-transferrable, so if `receiveAsTokens = false` and * `withdrawal.withdrawer != withdrawal.staker`, note that * any beaconChainETHStrategy shares in the `withdrawal` will be _returned to the staker_, rather than transferred * to the withdrawer, unlike shares in * any other strategies, which will be transferred to the withdrawer. */ function completeQueuedWithdrawal( Withdrawal calldata withdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens ) external; /** * @notice Array-ified version of `completeQueuedWithdrawal`. * Used to complete the specified `withdrawals`. The function caller must match `withdrawals[...].withdrawer` * @param withdrawals The Withdrawals to complete. * @param tokens Array of tokens for each Withdrawal. See `completeQueuedWithdrawal` for the usage of a single * array. * @param middlewareTimesIndexes One index to reference per Withdrawal. See `completeQueuedWithdrawal` for the usage * of a single index. * @param receiveAsTokens Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for * the usage of a single boolean. * @dev See `completeQueuedWithdrawal` for relevant dev tags */ function completeQueuedWithdrawals( Withdrawal[] calldata withdrawals, IERC20[][] calldata tokens, uint256[] calldata middlewareTimesIndexes, bool[] calldata receiveAsTokens ) external; /** * @notice Increases a staker's delegated share balance in a strategy. * @param staker The address to increase the delegated shares for their operator. * @param strategy The strategy in which to increase the delegated shares. * @param shares The number of shares to increase. * * @dev *If the staker is actively delegated*, then increases the `staker`'s delegated shares in `strategy` by * `shares`. Otherwise does nothing. * @dev Callable only by the StrategyManager or EigenPodManager. */ function increaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external; /** * @notice Decreases a staker's delegated share balance in a strategy. * @param staker The address to increase the delegated shares for their operator. * @param strategy The strategy in which to decrease the delegated shares. * @param shares The number of shares to decrease. * * @dev *If the staker is actively delegated*, then decreases the `staker`'s delegated shares in `strategy` by * `shares`. Otherwise does nothing. * @dev Callable only by the StrategyManager or EigenPodManager. */ function decreaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external; /** * @notice returns the address of the operator that `staker` is delegated to. * @notice Mapping: staker => operator whom the staker is currently delegated to. * @dev Note that returning address(0) indicates that the staker is not actively delegated to any operator. */ function delegatedTo(address staker) external view returns (address); /** * @notice Returns the OperatorDetails struct associated with an `operator`. */ function operatorDetails(address operator) external view returns (OperatorDetails memory); /* * @notice Returns the earnings receiver address for an operator */ function earningsReceiver(address operator) external view returns (address); /** * @notice Returns the delegationApprover account for an operator */ function delegationApprover(address operator) external view returns (address); /** * @notice Returns the stakerOptOutWindowBlocks for an operator */ function stakerOptOutWindowBlocks(address operator) external view returns (uint256); /** * @notice Given array of strategies, returns array of shares for the operator */ function getOperatorShares( address operator, IStrategy[] memory strategies ) external view returns (uint256[] memory); /** * @notice Given a list of strategies, return the minimum number of blocks that must pass to withdraw * from all the inputted strategies. Return value is >= minWithdrawalDelayBlocks as this is the global min * withdrawal delay. * @param strategies The strategies to check withdrawal delays for */ function getWithdrawalDelay(IStrategy[] calldata strategies) external view returns (uint256); /** * @notice returns the total number of shares in `strategy` that are delegated to `operator`. * @notice Mapping: operator => strategy => total number of shares in the strategy delegated to the operator. * @dev By design, the following invariant should hold for each Strategy: * (operator's shares in delegation manager) = sum (shares above zero of all stakers delegated to operator) * = sum (delegateable shares of all stakers delegated to the operator) */ function operatorShares(address operator, IStrategy strategy) external view returns (uint256); /** * @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise. */ function isDelegated(address staker) external view returns (bool); /** * @notice Returns true is an operator has previously registered for delegation. */ function isOperator(address operator) external view returns (bool); /// @notice Mapping: staker => number of signed delegation nonces (used in `delegateToBySignature`) from the staker /// that the contract has already checked function stakerNonce(address staker) external view returns (uint256); /** * @notice Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the * delegationApprover. * @dev Salts are used in the `delegateTo` and `delegateToBySignature` functions. Note that these functions only * process the delegationApprover's * signature + the provided salt if the operator being delegated to has specified a nonzero address as their * `delegationApprover`. */ function delegationApproverSaltIsSpent(address _delegationApprover, bytes32 salt) external view returns (bool); /** * @notice Minimum delay enforced by this contract for completing queued withdrawals. Measured in blocks, and * adjustable by this contract's owner, * up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced). * Note that strategies each have a separate withdrawal delay, which can be greater than this value. So the minimum * number of blocks that must pass * to withdraw a strategy is MAX(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy]) */ function minWithdrawalDelayBlocks() external view returns (uint256); /** * @notice Minimum delay enforced by this contract per Strategy for completing queued withdrawals. Measured in * blocks, and adjustable by this contract's owner, * up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced). */ function strategyWithdrawalDelayBlocks(IStrategy strategy) external view returns (uint256); /** * @notice Calculates the digestHash for a `staker` to sign to delegate to an `operator` * @param staker The signing staker * @param operator The operator who is being delegated to * @param expiry The desired expiry time of the staker's signature */ function calculateCurrentStakerDelegationDigestHash( address staker, address operator, uint256 expiry ) external view returns (bytes32); /** * @notice Calculates the digest hash to be signed and used in the `delegateToBySignature` function * @param staker The signing staker * @param _stakerNonce The nonce of the staker. In practice we use the staker's current nonce, stored at * `stakerNonce[staker]` * @param operator The operator who is being delegated to * @param expiry The desired expiry time of the staker's signature */ function calculateStakerDelegationDigestHash( address staker, uint256 _stakerNonce, address operator, uint256 expiry ) external view returns (bytes32); /** * @notice Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` * and `delegateToBySignature` functions. * @param staker The account delegating their stake * @param operator The account receiving delegated stake * @param _delegationApprover the operator's `delegationApprover` who will be signing the delegationHash (in * general) * @param approverSalt A unique and single use value associated with the approver signature. * @param expiry Time after which the approver's signature becomes invalid */ function calculateDelegationApprovalDigestHash( address staker, address operator, address _delegationApprover, bytes32 approverSalt, uint256 expiry ) external view returns (bytes32); /// @notice The EIP-712 typehash for the contract's domain function DOMAIN_TYPEHASH() external view returns (bytes32); /// @notice The EIP-712 typehash for the StakerDelegation struct used by the contract function STAKER_DELEGATION_TYPEHASH() external view returns (bytes32); /// @notice The EIP-712 typehash for the DelegationApproval struct used by the contract function DELEGATION_APPROVAL_TYPEHASH() external view returns (bytes32); /** * @notice Getter function for the current EIP-712 domain separator for this contract. * * @dev The domain separator will change in the event of a fork that changes the ChainID. * @dev By introducing a domain separator the DApp developers are guaranteed that there can be no signature * collision. * for more detailed information please read EIP-712. */ function domainSeparator() external view returns (bytes32); /// @notice Mapping: staker => cumulative number of queued withdrawals they have ever initiated. /// @dev This only increments (doesn't decrement), and is used to help ensure that otherwise identical withdrawals /// have unique hashes. function cumulativeWithdrawalsQueued(address staker) external view returns (uint256); /// @notice Returns the keccak256 hash of `withdrawal`. function calculateWithdrawalRoot(Withdrawal memory withdrawal) external pure returns (bytes32); // @notice Struct that bundles together a signature and an expiration time for the signature. Used primarily for // stack management. struct SignatureWithExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the expiration timestamp (UTC) of the signature uint256 expiry; } /** * @notice Caller delegates their stake to an operator. * @param operator The account (`msg.sender`) is delegating its assets to for use in serving applications built on * EigenLayer. * @param approverSignatureAndExpiry Verifies the operator approves of this delegation * @param approverSalt A unique single use value tied to an individual signature. * @dev The approverSignatureAndExpiry is used in the event that: * 1) the operator's `delegationApprover` address is set to a non-zero value. * AND * 2) neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the * operator * or their delegationApprover is the `msg.sender`, then approval is assumed. * @dev In the event that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's * recommended to use an empty input * in this case to save on complexity + gas costs */ function delegateTo( address operator, SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt ) external; /** * @notice Delegates from `staker` to `operator`. * @dev requires that: * 1) if `staker` is an EOA, then `signature` is valid ECDSA signature from `staker`, indicating their intention for * this action * 2) if `staker` is a contract, then `signature` must will be checked according to EIP-1271 */ function delegateToBySignature(address staker, address operator, uint256 expiry, bytes memory signature) external; /** * @notice Returns the number of actively-delegatable shares a staker has across all strategies. * @dev Returns two empty arrays in the case that the Staker has no actively-delegateable shares. */ function getDelegatableShares(address staker) external view returns (IStrategy[] memory, uint256[] memory); /// @notice Returns 'true' if `staker` is *not* actively delegated, and 'false' otherwise. function isNotDelegated(address staker) external view returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; interface IEigenDelayedWithdrawalRouter { // struct used to pack data into a single storage slot struct DelayedWithdrawal { uint224 amount; uint32 blockCreated; } // struct used to store a single users delayedWithdrawal data struct UserDelayedWithdrawals { uint256 delayedWithdrawalsCompleted; DelayedWithdrawal[] delayedWithdrawals; } function getUserDelayedWithdrawals(address user) external view returns (DelayedWithdrawal[] memory); function claimDelayedWithdrawals(address recipient, uint256 maxNumberOfDelayedWithdrawalsToClaim) external; function userWithdrawals(address user) external view returns (UserDelayedWithdrawals memory); function userWithdrawalsLength(address user) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IStrategy } from "contracts/external/eigenlayer/interfaces/IStrategy.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface ILRTWithdrawalManager { //errors error TokenTransferFailed(); error EthTransferFailed(); error InvalidAmountToWithdraw(); error ExceedAmountToWithdraw(); error WithdrawalLocked(); error WithdrawalDelayNotPassed(); error WithdrawalDelayTooSmall(); error NoPendingWithdrawals(); error AmountMustBeGreaterThanZero(); error StrategyNotSupported(); error RsETHPriceMustBeGreaterMinimum(uint256 rsEthPrice); error AssetPriceMustBeGreaterMinimum(uint256 assetPrice); struct WithdrawalRequest { uint256 rsETHUnstaked; uint256 expectedAssetAmount; uint256 withdrawalStartBlock; } //events event AssetWithdrawalQueued( address indexed withdrawer, address indexed asset, uint256 rsETHUnstaked, uint256 indexed userNonce ); event AssetWithdrawalFinalized( address indexed withdrawer, address indexed asset, uint256 amountBurned, uint256 amountReceived ); event EtherReceived(address indexed depositor, uint256 ethAmount, uint256 sharesAmount); event AssetUnlocked( address indexed asset, uint256 rsEthAmount, uint256 assetAmount, uint256 rsEThPrice, uint256 assetPrice ); event MinAmountToWithdrawUpdated(address asset, uint256 minRsEthAmountToWithdraw); event WithdrawalDelayBlocksUpdated(uint256 withdrawalDelayBlocks); // methods function getExpectedAssetAmount(address asset, uint256 amount) external view returns (uint256); function getAvailableAssetAmount(address asset) external view returns (uint256 assetAmount); function getUserWithdrawalRequest( address asset, address user, uint256 index ) external view returns (uint256 rsETHAmount, uint256 expectedAssetAmount, uint256 withdrawalStartBlock, uint256 userNonce); function initiateWithdrawal(address asset, uint256 withdrawAmount) external; function completeWithdrawal(address asset) external; function unlockQueue( address asset, uint256 index, uint256 minimumAssetPrice, uint256 minimumRsEthPrice ) external returns (uint256 rsETHBurned, uint256 assetAmountUnlocked); // receive functions function receiveFromLRTUnstakingVault() external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; interface ILRTDepositPool { //errors error InvalidAmountToDeposit(); error NotEnoughAssetToTransfer(); error MaximumDepositLimitReached(); error MaximumNodeDelegatorLimitReached(); error InvalidMaximumNodeDelegatorLimit(); error MinimumAmountToReceiveNotMet(); error NodeDelegatorNotFound(); error NodeDelegatorHasAssetBalance(address assetAddress, uint256 assetBalance); error NodeDelegatorHasETH(); error EthTransferFailed(); //events event MaxNodeDelegatorLimitUpdated(uint256 maxNodeDelegatorLimit); event NodeDelegatorAddedinQueue(address[] nodeDelegatorContracts); event NodeDelegatorRemovedFromQueue(address nodeDelegatorContracts); event AssetDeposit( address indexed depositor, address indexed asset, uint256 depositAmount, uint256 rsethMintAmount, string referralId ); event ETHDeposit(address indexed depositor, uint256 depositAmount, uint256 rsethMintAmount, string referralId); event MinAmountToDepositUpdated(uint256 minAmountToDeposit); event MaxNegligibleAmountUpdated(uint256 maxNegligibleAmount); event ETHSwappedForLST(uint256 ethAmount, address indexed toAsset, uint256 returnAmount); event EthTransferred(address to, uint256 amount); // functions function depositAsset( address asset, uint256 depositAmount, uint256 minRSETHAmountExpected, string calldata referralId ) external; function getSwapETHToAssetReturnAmount( address toAsset, uint256 ethAmountToSend ) external view returns (uint256 returnAmount); function getTotalAssetDeposits(address asset) external view returns (uint256); function getAssetCurrentLimit(address asset) external view returns (uint256); function getRsETHAmountToMint(address asset, uint256 depositAmount) external view returns (uint256); function addNodeDelegatorContractToQueue(address[] calldata nodeDelegatorContract) external; function transferAssetToNodeDelegator(uint256 ndcIndex, address asset, uint256 amount) external; function updateMaxNodeDelegatorLimit(uint256 maxNodeDelegatorLimit) external; function getNodeDelegatorQueue() external view returns (address[] memory); function getAssetDistributionData(address asset) external view returns ( uint256 assetLyingInDepositPool, uint256 assetLyingInNDCs, uint256 assetStakedInEigenLayer, uint256 assetUnstakingFromEigenLayer, uint256 assetLyingInConverter, uint256 assetLyingUnstakingVault ); function getETHDistributionData() external view returns ( uint256 ethLyingInDepositPool, uint256 ethLyingInNDCs, uint256 ethStakedInEigenLayer, uint256 ethUnstakingFromEigenLayer, uint256 ethLyingInConverter, uint256 ethLyingInUnstakingVault ); function isNodeDelegator(address nodeDelegatorContract) external view returns (uint256); // receivers function receiveFromRewardReceiver() external payable; function receiveFromLRTConverter() external payable; function receiveFromNodeDelegator() external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IStrategy } from "contracts/external/eigenlayer/interfaces/IStrategy.sol"; import { IEigenDelegationManager } from "contracts/external/eigenlayer/interfaces/IEigenDelegationManager.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface ILRTUnstakingVault { error CallerNotLRTNodeDelegator(); error EthTransferFailed(); error CallerNotLRTWithdrawalManager(); event EthReceived(address sender, uint256 amount); // functions function sharesUnstaking(address asset) external view returns (uint256); function getAssetsUnstaking(address asset) external view returns (uint256); function balanceOf(address asset) external view returns (uint256); function addSharesUnstaking(address asset, uint256 amount) external; function reduceSharesUnstaking(address asset, uint256 amount) external; function redeem(address asset, uint256 amount) external; // receive functions function receiveFromLRTDepositPool() external payable; function receiveFromNodeDelegator() external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; interface ILRTConfig { // Errors error ValueAlreadyInUse(); error AssetAlreadySupported(); error AssetNotSupported(); error CallerNotLRTConfigAdmin(); error CallerNotLRTConfigManager(); error CallerNotLRTConfigOperator(); error CallerNotLRTConfigAllowedRole(string role); error CannotUpdateStrategyAsItHasFundsNDCFunds(address ndc, uint256 amount); error InvalidMaxRewardAmount(); // Events event SetToken(bytes32 key, address indexed tokenAddr); event SetContract(bytes32 key, address indexed contractAddr); event AddedNewSupportedAsset(address indexed asset, uint256 depositLimit); event RemovedSupportedAsset(address indexed asset); event AssetDepositLimitUpdate(address indexed asset, uint256 depositLimit); event AssetStrategyUpdate(address indexed asset, address indexed strategy); event SetRSETH(address indexed rsETH); event UpdateMaxRewardAmount(uint256 maxRewardAmount); // methods function rsETH() external view returns (address); function assetStrategy(address asset) external view returns (address); function isSupportedAsset(address asset) external view returns (bool); function getLSTToken(bytes32 tokenId) external view returns (address); function getContract(bytes32 contractId) external view returns (address); function getSupportedAssetList() external view returns (address[] memory); function depositLimitByAsset(address asset) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "hardhat/=node_modules/hardhat/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solidity-code-metrics/=node_modules/solidity-code-metrics/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetNotSupported","type":"error"},{"inputs":[],"name":"CallerNotLRTConfigAdmin","type":"error"},{"inputs":[],"name":"CallerNotLRTNodeDelegator","type":"error"},{"inputs":[],"name":"CallerNotLRTWithdrawalManager","type":"error"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"ValueAlreadyInUse","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EthReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lrtConfig","type":"address"}],"name":"UpdatedLRTConfig","type":"event"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addSharesUnstaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetsUnstaking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lrtConfigAddr","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lrtConfig","outputs":[{"internalType":"contract ILRTConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiveFromLRTDepositPool","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"receiveFromNodeDelegator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reduceSharesUnstaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"sharesUnstaking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lrtConfigAddr","type":"address"}],"name":"updateLRTConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561000f575f80fd5b5061001861001d565b6100e6565b5f54600160a81b900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f54600160a01b900460ff908116146100e4575f805460ff60a01b191660ff60a01b17905560405160ff81527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611856806100f35f395ff3fe6080604052600436106100c6575f3560e01c80635f3cbfd411610071578063c5bac6511161004c578063c5bac65114610225578063db43806814610128578063f1650a4614610244575f80fd5b80635f3cbfd41461012857806370a08231146101e7578063c4d66de814610206575f80fd5b80631e9a6950116100a15780631e9a695014610168578063562a9c7b146101875780635c975abb146101c5575f80fd5b80630776387f146101095780630d7d8a171461012a57806315864e0a14610149575f80fd5b3661010557604080513381523460208201527f85177f287940f2f05425a4029951af0e047a7f9c4eaa9a6e6917bcd869f86695910160405180910390a1005b5f80fd5b348015610114575f80fd5b506101286101233660046116a3565b610294565b005b348015610135575f80fd5b506101286101443660046116a3565b61044a565b348015610154575f80fd5b506101286101633660046116cd565b6105f6565b348015610173575f80fd5b506101286101823660046116a3565b610786565b348015610192575f80fd5b506101b26101a13660046116cd565b60976020525f908152604090205481565b6040519081526020015b60405180910390f35b3480156101d0575f80fd5b5060335460ff1660405190151581526020016101bc565b3480156101f2575f80fd5b506101b26102013660046116cd565b610971565b348015610211575f80fd5b506101286102203660046116cd565b610a48565b348015610230575f80fd5b506101b261023f3660046116cd565b610cbe565b34801561024f575f80fd5b505f5461026f9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b5f80546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f7a8fe1bac8d7638862c53b62ffada56d0a56c381287c35f66503b5b86fa88b85600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa158015610320573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061034491906116ef565b6040517f4f444d2500000000000000000000000000000000000000000000000000000000815233600482015290915073ffffffffffffffffffffffffffffffffffffffff821690634f444d2590602401602060405180830381865afa1580156103af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d3919061170a565b60011461040c576040517f9904aaae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f908152609760205260408120805484929061044090849061174e565b9091555050505050565b5f80546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f7a8fe1bac8d7638862c53b62ffada56d0a56c381287c35f66503b5b86fa88b85600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa1580156104d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fa91906116ef565b6040517f4f444d2500000000000000000000000000000000000000000000000000000000815233600482015290915073ffffffffffffffffffffffffffffffffffffffff821690634f444d2590602401602060405180830381865afa158015610565573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610589919061170a565b6001146105c2576040517f9904aaae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526097602052604081208054849290610440908490611761565b5f80546040517f91d14854000000000000000000000000000000000000000000000000000000008152600481019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906391d1485490604401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611774565b6106c2576040517f164931f400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5473ffffffffffffffffffffffffffffffffffffffff1615610711576040517f18e6d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61071a81610f2e565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117825560405190917f9cf19cefd9aab739c33b95716ee3f3f921f219dc6d7aae25e1f9497b3788915091a250565b61078e610f7e565b5f546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f1ffe5e31b761569011f2c9443332f6f987c9e37f8311474a33f44970a97038a0600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa158015610819573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061083d91906116ef565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108a1576040517f5b1c9b4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff831601610940573373ffffffffffffffffffffffffffffffffffffffff1663e7637288826040518263ffffffff1660e01b81526004015f604051808303818588803b158015610924575f80fd5b505af1158015610936573d5f803e3d5ffd5b5050505050610961565b61096173ffffffffffffffffffffffffffffffffffffffff83163383610ff1565b61096b6001606555565b5050565b565b5f7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8316016109b6575047919050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610a1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a42919061170a565b92915050565b5f547501000000000000000000000000000000000000000000900460ff1615808015610a9157505f5460017401000000000000000000000000000000000000000090910460ff16105b80610ac25750303b158015610ac257505f5474010000000000000000000000000000000000000000900460ff166001145b610b53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bd7575f80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610be082610f2e565b610be861108a565b610bf061113c565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117825560405190917f9cf19cefd9aab739c33b95716ee3f3f921f219dc6d7aae25e1f9497b3788915091a2801561096b575f80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f80546040517f9be918e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808516600483015284921690639be918e690602401602060405180830381865afa158015610d2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d509190611774565b610d86576040517f981a2a2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610def5773ffffffffffffffffffffffffffffffffffffffff83165f908152609760205260409020549150610f28565b5f80546040517f97ef9d9800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152909116906397ef9d9890602401602060405180830381865afa158015610e5d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8191906116ef565b73ffffffffffffffffffffffffffffffffffffffff8581165f90815260976020526040908190205490517f7a8b26370000000000000000000000000000000000000000000000000000000081526004810191909152919250821690637a8b263790602401602060405180830381865afa158015610f00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f24919061170a565b9250505b50919050565b73ffffffffffffffffffffffffffffffffffffffff8116610f7b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600260655403610fea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b4a565b6002606555565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261107e9084906111ee565b505050565b6001606555565b5f547501000000000000000000000000000000000000000000900460ff16611134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b61096f6112fb565b5f547501000000000000000000000000000000000000000000900460ff166111e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b61096f6113cf565b5f61124f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114799092919063ffffffff16565b905080515f148061126f57508080602001905181019061126f9190611774565b61107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b4a565b5f547501000000000000000000000000000000000000000000900460ff166113a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b5f547501000000000000000000000000000000000000000000900460ff16611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b606061148784845f8561148f565b949350505050565b606082471015611521576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b4a565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405161154991906117b5565b5f6040518083038185875af1925050503d805f8114611583576040519150601f19603f3d011682016040523d82523d5f602084013e611588565b606091505b5091509150611599878383876115a4565b979650505050505050565b606083156116395782515f036116325773ffffffffffffffffffffffffffffffffffffffff85163b611632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b4a565b5081611487565b611487838381511561164e5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4a91906117d0565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7b575f80fd5b5f80604083850312156116b4575f80fd5b82356116bf81611682565b946020939093013593505050565b5f602082840312156116dd575f80fd5b81356116e881611682565b9392505050565b5f602082840312156116ff575f80fd5b81516116e881611682565b5f6020828403121561171a575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610a4257610a42611721565b81810381811115610a4257610a42611721565b5f60208284031215611784575f80fd5b815180151581146116e8575f80fd5b5f5b838110156117ad578181015183820152602001611795565b50505f910152565b5f82516117c6818460208701611793565b9190910192915050565b602081525f82518060208401526117ee816040850160208701611793565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220553cd0456d7bf858c3fc42ad6ebe46847dedb7b324f259b54468c67d6e94a69c64736f6c63430008150033
Deployed Bytecode
0x6080604052600436106100c6575f3560e01c80635f3cbfd411610071578063c5bac6511161004c578063c5bac65114610225578063db43806814610128578063f1650a4614610244575f80fd5b80635f3cbfd41461012857806370a08231146101e7578063c4d66de814610206575f80fd5b80631e9a6950116100a15780631e9a695014610168578063562a9c7b146101875780635c975abb146101c5575f80fd5b80630776387f146101095780630d7d8a171461012a57806315864e0a14610149575f80fd5b3661010557604080513381523460208201527f85177f287940f2f05425a4029951af0e047a7f9c4eaa9a6e6917bcd869f86695910160405180910390a1005b5f80fd5b348015610114575f80fd5b506101286101233660046116a3565b610294565b005b348015610135575f80fd5b506101286101443660046116a3565b61044a565b348015610154575f80fd5b506101286101633660046116cd565b6105f6565b348015610173575f80fd5b506101286101823660046116a3565b610786565b348015610192575f80fd5b506101b26101a13660046116cd565b60976020525f908152604090205481565b6040519081526020015b60405180910390f35b3480156101d0575f80fd5b5060335460ff1660405190151581526020016101bc565b3480156101f2575f80fd5b506101b26102013660046116cd565b610971565b348015610211575f80fd5b506101286102203660046116cd565b610a48565b348015610230575f80fd5b506101b261023f3660046116cd565b610cbe565b34801561024f575f80fd5b505f5461026f9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b5f80546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f7a8fe1bac8d7638862c53b62ffada56d0a56c381287c35f66503b5b86fa88b85600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa158015610320573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061034491906116ef565b6040517f4f444d2500000000000000000000000000000000000000000000000000000000815233600482015290915073ffffffffffffffffffffffffffffffffffffffff821690634f444d2590602401602060405180830381865afa1580156103af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103d3919061170a565b60011461040c576040517f9904aaae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f908152609760205260408120805484929061044090849061174e565b9091555050505050565b5f80546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f7a8fe1bac8d7638862c53b62ffada56d0a56c381287c35f66503b5b86fa88b85600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa1580156104d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fa91906116ef565b6040517f4f444d2500000000000000000000000000000000000000000000000000000000815233600482015290915073ffffffffffffffffffffffffffffffffffffffff821690634f444d2590602401602060405180830381865afa158015610565573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610589919061170a565b6001146105c2576040517f9904aaae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526097602052604081208054849290610440908490611761565b5f80546040517f91d14854000000000000000000000000000000000000000000000000000000008152600481019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906391d1485490604401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611774565b6106c2576040517f164931f400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5473ffffffffffffffffffffffffffffffffffffffff1615610711576040517f18e6d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61071a81610f2e565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117825560405190917f9cf19cefd9aab739c33b95716ee3f3f921f219dc6d7aae25e1f9497b3788915091a250565b61078e610f7e565b5f546040517fe16c7d980000000000000000000000000000000000000000000000000000000081527f1ffe5e31b761569011f2c9443332f6f987c9e37f8311474a33f44970a97038a0600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e16c7d9890602401602060405180830381865afa158015610819573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061083d91906116ef565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108a1576040517f5b1c9b4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff831601610940573373ffffffffffffffffffffffffffffffffffffffff1663e7637288826040518263ffffffff1660e01b81526004015f604051808303818588803b158015610924575f80fd5b505af1158015610936573d5f803e3d5ffd5b5050505050610961565b61096173ffffffffffffffffffffffffffffffffffffffff83163383610ff1565b61096b6001606555565b5050565b565b5f7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8316016109b6575047919050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610a1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a42919061170a565b92915050565b5f547501000000000000000000000000000000000000000000900460ff1615808015610a9157505f5460017401000000000000000000000000000000000000000090910460ff16105b80610ac25750303b158015610ac257505f5474010000000000000000000000000000000000000000900460ff166001145b610b53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bd7575f80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610be082610f2e565b610be861108a565b610bf061113c565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117825560405190917f9cf19cefd9aab739c33b95716ee3f3f921f219dc6d7aae25e1f9497b3788915091a2801561096b575f80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f80546040517f9be918e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808516600483015284921690639be918e690602401602060405180830381865afa158015610d2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d509190611774565b610d86576040517f981a2a2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610def5773ffffffffffffffffffffffffffffffffffffffff83165f908152609760205260409020549150610f28565b5f80546040517f97ef9d9800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152909116906397ef9d9890602401602060405180830381865afa158015610e5d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8191906116ef565b73ffffffffffffffffffffffffffffffffffffffff8581165f90815260976020526040908190205490517f7a8b26370000000000000000000000000000000000000000000000000000000081526004810191909152919250821690637a8b263790602401602060405180830381865afa158015610f00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f24919061170a565b9250505b50919050565b73ffffffffffffffffffffffffffffffffffffffff8116610f7b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600260655403610fea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b4a565b6002606555565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261107e9084906111ee565b505050565b6001606555565b5f547501000000000000000000000000000000000000000000900460ff16611134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b61096f6112fb565b5f547501000000000000000000000000000000000000000000900460ff166111e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b61096f6113cf565b5f61124f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114799092919063ffffffff16565b905080515f148061126f57508080602001905181019061126f9190611774565b61107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b4a565b5f547501000000000000000000000000000000000000000000900460ff166113a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b5f547501000000000000000000000000000000000000000000900460ff16611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b4a565b606061148784845f8561148f565b949350505050565b606082471015611521576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b4a565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405161154991906117b5565b5f6040518083038185875af1925050503d805f8114611583576040519150601f19603f3d011682016040523d82523d5f602084013e611588565b606091505b5091509150611599878383876115a4565b979650505050505050565b606083156116395782515f036116325773ffffffffffffffffffffffffffffffffffffffff85163b611632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b4a565b5081611487565b611487838381511561164e5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4a91906117d0565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7b575f80fd5b5f80604083850312156116b4575f80fd5b82356116bf81611682565b946020939093013593505050565b5f602082840312156116dd575f80fd5b81356116e881611682565b9392505050565b5f602082840312156116ff575f80fd5b81516116e881611682565b5f6020828403121561171a575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115610a4257610a42611721565b81810381811115610a4257610a42611721565b5f60208284031215611784575f80fd5b815180151581146116e8575f80fd5b5f5b838110156117ad578181015183820152602001611795565b50505f910152565b5f82516117c6818460208701611793565b9190910192915050565b602081525f82518060208401526117ee816040850160208701611793565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220553cd0456d7bf858c3fc42ad6ebe46847dedb7b324f259b54468c67d6e94a69c64736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.