Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EigenpieWithdrawManager
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: GPL-3.0-or-later pragma solidity 0.8.21; import { UtilLib } from "./utils/UtilLib.sol"; import { EigenpieConstants } from "./utils/EigenpieConstants.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { EigenpieConfigRoleChecker, IEigenpieConfig } from "./utils/EigenpieConfigRoleChecker.sol"; import { IMintableERC20 } from "./interfaces/IMintableERC20.sol"; import { INodeDelegator } from "./interfaces/INodeDelegator.sol"; import { IEigenpieStaking } from "./interfaces/IEigenpieStaking.sol"; import { IMLRT } from "./interfaces/IMLRT.sol"; import { IEigenpiePreDepositHelper } from "./interfaces/IEigenpiePreDepositHelper.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { IEigenpieWithdrawManager } from "./interfaces/IEigenpieWithdrawManager.sol"; import { TransferHelper } from "./utils/TransferHelper.sol"; /// @title EigenpieWithdrawManager - Withdraw Pool Contract for LSTs /// @notice Handles LST asset deposits contract EigenpieWithdrawManager is IEigenpieWithdrawManager, EigenpieConfigRoleChecker, PausableUpgradeable, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; uint256 public lstWithdrawalDelay; // a buffer time period making sure user able to withdraw the LST unstake by // Eigenpie uint256 public startTimestamp; // the start timestamp counting epoch uint256 public constant EPOCH_DURATION = 7 days; uint256 public withdrawalscheduleCleanUp; // the threshold to clean up withdra queue length mapping(bytes32 => UserWithdrawalSchedule[]) public withdrawalSchedules; //bytes32 = user + asset mapping(bytes32 => WithdrawalSum) public withdrawalSums; // aggregated withdrawal information // bytes32 = asset + // epoch //1st upgrade /// @dev mapping of queued withdrawRequest, indexed by withdrawRequest hash mapping(bytes32 => WithdrawQueueStatus) public withdrawQueued; mapping(address => uint256[]) public userNonces; mapping(uint256 => UserWithdrawalSchedule) public nonceToSchedule; EthWithdrawQueue public ethWithdrawQueue; uint256 public withdrawalBufferTarget; uint256 public ethClaimReserve; uint256 public withdrawRequestNonce; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @dev Initializes the contract /// @param eigenpieConfigAddr eigenpieConfig address function initialize( address eigenpieConfigAddr, uint256 _lstWithdrawalDelay, uint256 _startTimestamp ) external initializer { UtilLib.checkNonZeroAddress(eigenpieConfigAddr); __Pausable_init(); __ReentrancyGuard_init(); eigenpieConfig = IEigenpieConfig(eigenpieConfigAddr); lstWithdrawalDelay = _lstWithdrawalDelay; startTimestamp = _startTimestamp; withdrawalscheduleCleanUp = 5; emit UpdatedEigenpieConfig(eigenpieConfigAddr); } /*////////////////////////////////////////////////////////////// view functions //////////////////////////////////////////////////////////////*/ // to get timestamp user able to unstake LST from Eigenpie if they queue withdraw now function nextUserWithdrawalTime() public view returns (uint256) { return startTimestamp + (currentEpoch() + 1) * EPOCH_DURATION + lstWithdrawalDelay; } // to get current epoch number function currentEpoch() public view returns (uint256) { return (block.timestamp - startTimestamp) / EPOCH_DURATION + 1; } function getUserQueuedWithdraw( address _user, address[] memory _assets ) external view returns (uint256[] memory queuedAmounts, uint256[] memory claimableAmounts, uint256[] memory claimedAmounts) { return _calculateAmounts(_user, _assets); } function userToAssetKey(address _user, address _asset) public pure returns (bytes32) { return _getKey(_user, _asset, 0, true); } function assetEpochKey(address _asset, uint256 _epochTime) public pure returns (bytes32) { return _getKey(address(0), _asset, _epochTime, false); } function getUserWithdrawalSchedulesETH(address user) external view returns (uint256[] memory nonces, UserWithdrawalSchedule[] memory schedules) { // Retrieve the user's nonces uint256[] memory userNonceArray = userNonces[user]; uint256 length = userNonceArray.length; // Create a schedules array of the same length UserWithdrawalSchedule[] memory scheduleArray = new UserWithdrawalSchedule[](length); // Populate the schedules array for (uint256 i = 0; i < length; i++) { uint256 nonce = userNonceArray[i]; scheduleArray[i] = nonceToSchedule[nonce]; } return (userNonceArray, scheduleArray); } function getUserWithdrawalSchedules( address user, address[] memory assets ) external view returns (uint256[][] memory queuedLstAmounts, uint256[][] memory endTimes) { queuedLstAmounts = new uint256[][](assets.length); endTimes = new uint256[][](assets.length); for (uint256 i = 0; i < assets.length; i++) { bytes32 key = userToAssetKey(user, assets[i]); UserWithdrawalSchedule[] memory schedules = withdrawalSchedules[key]; // Initialize arrays to store schedules for the current asset uint256[] memory assetQueuedAmounts = new uint256[](schedules.length); uint256[] memory assetEndTimes = new uint256[](schedules.length); // Iterate through all schedules for the current asset for (uint256 j = 0; j < schedules.length; j++) { UserWithdrawalSchedule memory schedule = schedules[j]; assetQueuedAmounts[j] = schedule.queuedWithdrawLSTAmt; assetEndTimes[j] = schedule.endTime; } // Assign arrays to the corresponding row in queuedAmounts and endTimes queuedLstAmounts[i] = assetQueuedAmounts; endTimes[i] = assetEndTimes; } } /** * @notice returns available to withdraw for ETH * @return uint256 amount available to withdraw from buffer */ function getAvailableToWithdraw() public view returns (uint256) { return address(this).balance - ethClaimReserve; } /** * @notice returns empty withdraw buffer for eth * @dev returns 0 is buffer is full * @return uint256 amount of buffer to be filled */ function getWithdrawDeficit() public view returns (uint256) { uint256 availableToWithdraw = getAvailableToWithdraw(); uint256 bufferDeficit = withdrawalBufferTarget > availableToWithdraw ? withdrawalBufferTarget - availableToWithdraw : 0; // Only allow queueDeficit for ETH uint256 queueDeficit = (ethWithdrawQueue.queuedWithdrawToFill > ethWithdrawQueue.queuedWithdrawFilled) ? (ethWithdrawQueue.queuedWithdrawToFill - ethWithdrawQueue.queuedWithdrawFilled) : 0; return bufferDeficit + queueDeficit; } /*////////////////////////////////////////////////////////////// Write functions //////////////////////////////////////////////////////////////*/ /** * @dev Allows a user to queue for withdrawal of a specific asset. * @param asset The address of the asset to withdraw. * @param mLRTamount The amount of the mLRT Token respective of LST token to withdraw. */ function userQueuingForWithdraw( address asset, uint256 mLRTamount ) external whenNotPaused nonReentrant onlySupportedAsset(asset) { address receipt = eigenpieConfig.mLRTReceiptByAsset(asset); uint256 userReceiptBal = IERC20(receipt).balanceOf(msg.sender); if (mLRTamount > userReceiptBal) revert InvalidAmount(); uint256 epochCurr = currentEpoch(); bytes32 userToAsset = userToAssetKey(msg.sender, asset); bytes32 assetToEpoch = assetEpochKey(asset, epochCurr); uint256 rate = IMLRT(receipt).exchangeRateToLST(); uint256 withdrawLSTAmt = (rate * mLRTamount) / 1 ether; uint256 userWithdrawableTime = nextUserWithdrawalTime(); UserWithdrawalSchedule memory schedule = UserWithdrawalSchedule(mLRTamount, withdrawLSTAmt, 0, userWithdrawableTime); if (asset == EigenpieConstants.PLATFORM_TOKEN_ADDRESS) { uint256 availableToWithdraw = getAvailableToWithdraw(); withdrawRequestNonce++; uint256 nonce = withdrawRequestNonce; userNonces[msg.sender].push(nonce); nonceToSchedule[nonce] = schedule; if (withdrawLSTAmt > availableToWithdraw) { // increase the claim reserve to partially fill withdrawRequest with max available in buffer ethClaimReserve += availableToWithdraw; // fill the queue with availableToWithdraw ethWithdrawQueue.queuedWithdrawFilled += availableToWithdraw; // update the queue to fill ethWithdrawQueue.queuedWithdrawToFill += withdrawLSTAmt; // calculate withdrawRequest hash bytes32 withdrawHash = keccak256(abi.encode(nonce, msg.sender)); withdrawQueued[withdrawHash].queued = true; withdrawQueued[withdrawHash].fillAt = ethWithdrawQueue.queuedWithdrawToFill; } else { // add redeem amount to claimReserve of claim asset ethClaimReserve += withdrawLSTAmt; } } else { WithdrawalSum storage withdrawalSum = withdrawalSums[assetToEpoch]; withdrawalSum.assetTotalToWithdrawAmt += withdrawLSTAmt; withdrawalSum.mLRTTotalToBurn += mLRTamount; withdrawalSchedules[userToAsset].push(schedule); } IERC20(receipt).safeTransferFrom(msg.sender, address(this), mLRTamount); emit UserQueuingForWithdrawal(msg.sender, asset, mLRTamount, withdrawLSTAmt, epochCurr, userWithdrawableTime); } function userWithdrawAsset(address[] memory assets) external whenNotPaused nonReentrant { uint256[] memory claimedWithdrawalSchedules = new uint256[](assets.length); // check if there are no duplicate entries in input data for (uint256 i = 0; i < assets.length; i++) { for (uint256 j = i + 1; j < assets.length; j++) { if (assets[i] == assets[j]) { revert InvalidInput(); } } } for (uint256 i = 0; i < assets.length;) { if (assets[i] == EigenpieConstants.PLATFORM_TOKEN_ADDRESS) revert PlatformTokenNotSupported(); bytes32 userToAsset = userToAssetKey(msg.sender, assets[i]); UserWithdrawalSchedule[] storage schedules = withdrawalSchedules[userToAsset]; uint256 totalClaimedAmount; uint256 claimedWithdrawalSchedulesPerAsset; for (uint256 j = 0; j < schedules.length;) { UserWithdrawalSchedule storage schedule = schedules[j]; // if claimmable if (block.timestamp >= schedule.endTime && schedule.claimedAmt == 0) { claimedWithdrawalSchedulesPerAsset++; schedule.claimedAmt = schedule.queuedWithdrawLSTAmt; totalClaimedAmount += schedule.queuedWithdrawLSTAmt; } else if (block.timestamp >= schedule.endTime && schedule.claimedAmt == schedule.queuedWithdrawLSTAmt) { claimedWithdrawalSchedulesPerAsset++; } unchecked { ++j; } } claimedWithdrawalSchedules[i] = claimedWithdrawalSchedulesPerAsset; if (totalClaimedAmount > IERC20(assets[i]).balanceOf(address(this))) { totalClaimedAmount = IERC20(assets[i]).balanceOf(address(this)); } if (totalClaimedAmount > 0) { IERC20(assets[i]).safeTransfer(msg.sender, totalClaimedAmount); emit AssetWithdrawn(msg.sender, assets[i], totalClaimedAmount); } unchecked { ++i; } } _cleanUpWithdrawalSchedules(assets, claimedWithdrawalSchedules); } function userWithdrawETH(uint256 nonce) external whenNotPaused nonReentrant { // Validate the nonce belongs to the user uint256[] storage userNoncesArray = userNonces[msg.sender]; bool validNonce = false; uint256 nonceIndex; for (uint256 i = 0; i < userNoncesArray.length; i++) { if (userNoncesArray[i] == nonce) { validNonce = true; nonceIndex = i; break; } } if (!validNonce) revert InvalidNonce(); // Fetch the schedule UserWithdrawalSchedule storage schedule = nonceToSchedule[nonce]; if (block.timestamp < schedule.endTime) revert WithdrawalNotYetClaimable(); bytes32 withdrawHash = keccak256(abi.encode(nonce, msg.sender)); if ( withdrawQueued[withdrawHash].queued && withdrawQueued[withdrawHash].fillAt > ethWithdrawQueue.queuedWithdrawFilled ) revert QueuedWithdrawalNotFilled(); // Calculate withdrawal amount uint256 withdrawAmount = schedule.queuedWithdrawLSTAmt; ethClaimReserve -= withdrawAmount; // Burn mLRT tokens address receipt = eigenpieConfig.mLRTReceiptByAsset(EigenpieConstants.PLATFORM_TOKEN_ADDRESS); IMintableERC20(receipt).burnFrom(address(this), schedule.receiptMLRTAmt); TransferHelper.safeTransferETH(msg.sender, withdrawAmount); // Clean up: Remove nonce and schedule _removeNonceAndSchedule(msg.sender, nonceIndex, nonce); emit ETHWithdrawn(msg.sender, nonce, withdrawAmount); } function _removeNonceAndSchedule(address user, uint256 index, uint256 nonce) internal { uint256[] storage userNoncesArray = userNonces[user]; uint256 lastNonceIndex = userNoncesArray.length - 1; if (index < lastNonceIndex) { userNoncesArray[index] = userNoncesArray[lastNonceIndex]; } userNoncesArray.pop(); delete nonceToSchedule[nonce]; } /*////////////////////////////////////////////////////////////// Admin functions //////////////////////////////////////////////////////////////*/ /** * @notice fill Eth WithdrawBuffer from node delegator deposits * @dev permissioned call (onlyNodeDelegator) */ function fillEthWithdrawBuffer() external payable whenNotPaused nonReentrant onlyAllowedBot { uint256 queueFilled = _checkAndFillEthWithdrawQueue(msg.value); emit EthBufferFilled(msg.value - queueFilled); } // admin to queue Withdraw for aggregated user withdraw reqeust // Huge Assumption!! Admin should always fully queue withdraw all aggregated assets in that epoch function queuingWithdraw( address[] memory nodeDelegators, address[][] memory nodeToAssets, uint256[][] memory nodeToAmounts, uint256 epochNumber ) external whenNotPaused nonReentrant onlyAllowedBot { if (nodeDelegators.length != nodeToAssets.length || nodeDelegators.length != nodeToAmounts.length) { revert LengthMismatch(); } for (uint256 i = 0; i < nodeDelegators.length;) { if (nodeToAssets[i].length != nodeToAmounts[i].length) { revert LengthMismatch(); } unchecked { ++i; } } if (epochNumber >= currentEpoch()) { revert EpochNotYetReached(); } for (uint256 i = 0; i < nodeDelegators.length;) { uint256 assetsLength = nodeToAssets[i].length; for (uint256 j = 0; j < assetsLength;) { if (nodeToAssets[i][j] == EigenpieConstants.PLATFORM_TOKEN_ADDRESS) revert PlatformTokenNotSupported(); bytes32 assetToEpochKey = keccak256(abi.encodePacked(nodeToAssets[i][j], epochNumber)); WithdrawalSum storage withdrawalSum = withdrawalSums[assetToEpochKey]; withdrawalSum.assetTotalWithdrawQueued += nodeToAmounts[i][j]; unchecked { ++j; } } INodeDelegator(nodeDelegators[i]).queueWithdrawalToEigenLayer(nodeToAssets[i], nodeToAmounts[i]); unchecked { ++i; } } address[] memory supportedAssets = eigenpieConfig.getSupportedAssetList(); for (uint256 i = 0; i < supportedAssets.length;) { if (supportedAssets[i] != EigenpieConstants.PLATFORM_TOKEN_ADDRESS) { bytes32 assetToEpochKey = keccak256(abi.encodePacked(supportedAssets[i], epochNumber)); WithdrawalSum storage withdrawalSum = withdrawalSums[assetToEpochKey]; if (withdrawalSum.assetTotalToWithdrawAmt != withdrawalSum.assetTotalWithdrawQueued) { revert NotWithdrawAllQueuedRequest(); } withdrawalSum.mLRTburnt = true; if (withdrawalSum.assetTotalWithdrawQueued > 0) { address receipt = eigenpieConfig.mLRTReceiptByAsset(supportedAssets[i]); IMintableERC20(receipt).burnFrom(address(this), withdrawalSum.mLRTTotalToBurn); } } unchecked { ++i; } } } /// @dev Triggers stopped state. Contract must not be paused. function pause() external onlyEigenpieManager { _pause(); } /// @dev Returns to normal state. Contract must be paused function unpause() external onlyDefaultAdmin { _unpause(); } function updateWithdrawalScheduleCleanUpThreshold(uint256 _newThreshold) external onlyDefaultAdmin { require(_newThreshold > 0, "New threshold must be greater than zero"); withdrawalscheduleCleanUp = _newThreshold; emit VestingWithdrawalCleanUpThresholdUpdated(_newThreshold); } /** * @notice Updates the WithdrawBufferTarget for max withdraw available * @dev Permissioned call * @param _newBufferTarget new max buffer target available to withdraw */ function updateWithdrawBufferTarget(uint256 _newBufferTarget) external onlyDefaultAdmin { uint256 oldWithdrawalBufferTarget = withdrawalBufferTarget; withdrawalBufferTarget = _newBufferTarget; emit WithdrawBufferTargetUpdated(oldWithdrawalBufferTarget, _newBufferTarget); } /*////////////////////////////////////////////////////////////// Internal functions //////////////////////////////////////////////////////////////*/ function _cleanUpWithdrawalSchedules( address[] memory assets, uint256[] memory claimedWithdrawalSchedules ) internal { for (uint256 i = 0; i < assets.length;) { bytes32 userToAsset = userToAssetKey(msg.sender, assets[i]); UserWithdrawalSchedule[] storage schedules = withdrawalSchedules[userToAsset]; if (claimedWithdrawalSchedules[i] >= withdrawalscheduleCleanUp) { for (uint256 j = 0; j < schedules.length - claimedWithdrawalSchedules[i];) { schedules[j] = schedules[j + claimedWithdrawalSchedules[i]]; unchecked { ++j; } } while (claimedWithdrawalSchedules[i] > 0) { schedules.pop(); claimedWithdrawalSchedules[i]--; } } unchecked { ++i; } } } function _calculateAmounts( address _user, address[] memory _assets ) internal view returns (uint256[] memory queuedAmounts, uint256[] memory claimableAmounts, uint256[] memory claimedAmounts) { queuedAmounts = new uint256[](_assets.length); claimableAmounts = new uint256[](_assets.length); claimedAmounts = new uint256[](_assets.length); for (uint256 i = 0; i < _assets.length;) { bytes32 key = userToAssetKey(_user, _assets[i]); uint256 totalAmount = 0; uint256 totalClaimed = 0; uint256 totalClaimable = 0; UserWithdrawalSchedule[] memory schedules = withdrawalSchedules[key]; for (uint256 j = 0; j < schedules.length;) { UserWithdrawalSchedule memory schedule = schedules[j]; bool claimable = (schedule.endTime <= block.timestamp) && schedule.claimedAmt == 0; if (claimable) totalClaimable += schedule.queuedWithdrawLSTAmt; totalAmount += schedule.queuedWithdrawLSTAmt; totalClaimed += schedule.claimedAmt; unchecked { ++j; } } queuedAmounts[i] = totalAmount; claimableAmounts[i] = totalClaimable; claimedAmounts[i] = totalClaimed; unchecked { ++i; } } return (queuedAmounts, claimableAmounts, claimedAmounts); } function _getKey(address _user, address _asset, uint256 _epochTime, bool _isUser) internal pure returns (bytes32) { if (_isUser) { return keccak256(abi.encodePacked(_user, _asset)); } else { return keccak256(abi.encodePacked(_asset, _epochTime)); } } function _checkAndFillEthWithdrawQueue(uint256 amount) internal returns (uint256) { uint256 queueDeficit = (ethWithdrawQueue.queuedWithdrawToFill > ethWithdrawQueue.queuedWithdrawFilled) ? (ethWithdrawQueue.queuedWithdrawToFill - ethWithdrawQueue.queuedWithdrawFilled) : 0; uint256 queueFilled = 0; if (queueDeficit > 0) { queueFilled = queueDeficit > amount ? amount : queueDeficit; // Increase claimReserve ethClaimReserve += queueFilled; // Increase the queueFilled ethWithdrawQueue.queuedWithdrawFilled += queueFilled; emit QueueFilledForETH(queueFilled); } return queueFilled; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; import { EigenpieConstants } from "./EigenpieConstants.sol"; /// @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 isNativeToken(address addr) internal pure returns (bool) { return addr == EigenpieConstants.PLATFORM_TOKEN_ADDRESS; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; library EigenpieConstants { //contracts bytes32 public constant EIGENPIE_STAKING = keccak256("EIGENPIE_STAKING"); bytes32 public constant EIGEN_STRATEGY_MANAGER = keccak256("EIGEN_STRATEGY_MANAGER"); bytes32 public constant EIGEN_DELEGATION_MANAGER = keccak256("EIGEN_DELEGATION_MANAGER"); bytes32 public constant PRICE_PROVIDER = keccak256("PRICE_PROVIDER"); bytes32 public constant BEACON_DEPOSIT = keccak256("BEACON_DEPOSIT"); bytes32 public constant EIGENPOD_MANAGER = keccak256("EIGENPOD_MANAGER"); bytes32 public constant EIGENPIE_PREDEPOSITHELPER = keccak256("EIGENPIE_PREDEPOSITHELPER"); bytes32 public constant EIGENPIE_REWADR_DISTRIBUTOR = keccak256("EIGENPIE_REWADR_DISTRIBUTOR"); bytes32 public constant EIGENPIE_DWR = keccak256("EIGENPIE_DWR"); bytes32 public constant MLRT_ADAPTER = keccak256("MLRT_ADAPTER"); bytes32 public constant SSVNETWORK_ENTRY = keccak256("SSVNETWORK_ENTRY"); bytes32 public constant SSV_TOKEN = keccak256("SSV_TOKEN"); bytes32 public constant REWARD_COORDINATOR = keccak256("REWARD_COORDINATOR"); bytes32 public constant VAULT_LRT_SQUARED = keccak256("VAULT_LRT_SQUARED"); //Roles bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; bytes32 public constant MANAGER = keccak256("MANAGER"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); bytes32 public constant EGP_MINTER_ROLE = keccak256("EGP_MINTER_ROLE"); bytes32 public constant EGP_BURNER_ROLE = keccak256("EGP_BURNER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE"); bytes32 public constant ORACLE_ADMIN_ROLE = keccak256("ORACLE_ADMIN_ROLE"); bytes32 public constant PRICE_PROVIDER_ROLE = keccak256("PRICE_PROVIDER_ROLE"); bytes32 public constant ALLOWED_BOT_ROLE = keccak256("ALLOWED_BOT_ROLE"); // For Native Restaking uint256 constant PUBKEY_LENGTH = 48; uint256 constant SIGNATURE_LENGTH = 96; uint256 constant MAX_VALIDATORS = 100; uint256 constant DEPOSIT_AMOUNT = 32 ether; uint256 constant GWEI_TO_WEI = 1e9; // For layerzero bridging uint32 constant LZ_ZIRCUIT_DESTINATION_ID = 30_303; uint32 constant LZ_ETHEREUM_DESTINATION_ID = 30_101; uint256 public constant DENOMINATOR = 10_000; address public constant PLATFORM_TOKEN_ADDRESS = 0xeFEfeFEfeFeFEFEFEfefeFeFefEfEfEfeFEFEFEf; bytes32 public constant EIGENPIE_WITHDRAW_MANAGER = keccak256("EIGENPIE_WITHDRAW_MANAGER"); // External Defi bytes32 public constant ZIRCUIT_ZSTAKIGPOOL = keccak256("ZIRCUIT_ZSTAKIGPOOL"); bytes32 public constant SWELL_SIMPLE_STAKING = keccak256("SWELL_SIMPLE_STAKING"); bytes32 public constant ZSTAKIGPOOL_ZIRCUIT_CHAIN = keccak256("ZSTAKIGPOOL_ZIRCUIT_CHAIN"); bytes public constant BeaconProxyBytecode = hex"608060405260405161090e38038061090e83398101604081905261002291610460565b61002e82826000610035565b505061058a565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610520565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610520565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108e7602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053b565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c65782516103bf576001600160a01b0385163b6103bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d0565b6103d083836103d8565b949350505050565b8151156103e85781518083602001fd5b8060405162461bcd60e51b81526004016101699190610557565b80516001600160a01b038116811461041957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561044f578181015183820152602001610437565b838111156100f95750506000910152565b6000806040838503121561047357600080fd5b61047c83610402565b60208401519092506001600160401b038082111561049957600080fd5b818501915085601f8301126104ad57600080fd5b8151818111156104bf576104bf61041e565b604051601f8201601f19908116603f011681019083821181831017156104e7576104e761041e565b8160405282815288602084870101111561050057600080fd5b610511836020830160208801610434565b80955050505050509250929050565b60006020828403121561053257600080fd5b6102c882610402565b6000825161054d818460208701610434565b9190910192915050565b6020815260008251806020840152610576816040850160208701610434565b601f01601f19169190910160400192915050565b61034e806105996000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f260279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb9190610249565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a2565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020d578251610206576001600160a01b0385163b6102065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610217565b610217838361021f565b949350505050565b81511561022f5781518083602001fd5b8060405162461bcd60e51b81526004016101fd91906102be565b60006020828403121561025b57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028d578181015183820152602001610275565b8381111561029c576000848401525b50505050565b600082516102b4818460208701610272565b9190910192915050565b60208152600082518060208401526102dd816040850160208701610272565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d51e81d3bc5ed20a26aeb05dce7e825c503b2061aa78628027300c8d65b9d89a64736f6c634300080c0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564"; }
// 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: GPL-3.0-or-later pragma solidity 0.8.21; import { UtilLib } from "./UtilLib.sol"; import { EigenpieConstants } from "./EigenpieConstants.sol"; import { IEigenpieConfig } from "../interfaces/IEigenpieConfig.sol"; import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol"; /// @title EigenpieConfigRoleChecker - Eigenpie Config Role Checker Contract /// @notice Handles Eigenpie config role checks abstract contract EigenpieConfigRoleChecker { IEigenpieConfig public eigenpieConfig; uint256[49] private __gap; // reserve for upgrade // events event UpdatedEigenpieConfig(address indexed eigenpieConfig); // modifiers modifier onlyRole(bytes32 role) { if (!IAccessControl(address(eigenpieConfig)).hasRole(role, msg.sender)) { string memory roleStr = string(abi.encodePacked(role)); revert IEigenpieConfig.CallerNotEigenpieConfigAllowedRole(roleStr); } _; } modifier onlyEigenpieManager() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.MANAGER, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigManager(); } _; } modifier onlyPriceProvider() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.PRICE_PROVIDER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigPriceProvider(); } _; } modifier onlyDefaultAdmin() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.DEFAULT_ADMIN_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigAdmin(); } _; } modifier onlyOracleAdmin() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.ORACLE_ADMIN_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigOracleAdmin(); } _; } modifier onlyOracle() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.ORACLE_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigOracle(); } _; } modifier onlyMinter() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.MINTER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigMinter(); } _; } modifier onlyEGPMinter() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.EGP_MINTER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigMinter(); } _; } modifier onlyBurner() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.BURNER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigBurner(); } _; } modifier onlyEGPBurner() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.EGP_BURNER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigBurner(); } _; } modifier onlyPauser() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.PAUSER_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpiePauser(); } _; } modifier onlySupportedAsset(address asset) { if (!eigenpieConfig.isSupportedAsset(asset)) { revert IEigenpieConfig.AssetNotSupported(); } _; } modifier onlyAllowedBot() { if (!IAccessControl(address(eigenpieConfig)).hasRole(EigenpieConstants.ALLOWED_BOT_ROLE, msg.sender)) { revert IEigenpieConfig.CallerNotEigenpieConfigAllowedBot(); } _; } // setters /// @notice Updates the Eigenpie config contract /// @dev only callable by Eigenpie default /// @param eigenpieConfigAddr the new Eigenpie config contract Address function updateEigenpieConfig(address eigenpieConfigAddr) external virtual onlyDefaultAdmin { UtilLib.checkNonZeroAddress(eigenpieConfigAddr); eigenpieConfig = IEigenpieConfig(eigenpieConfigAddr); emit UpdatedEigenpieConfig(eigenpieConfigAddr); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity 0.8.21; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IMintableERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool); function mint(address, uint256) external; function faucet(uint256) external; function burnFrom(address account, uint256 amount) external; /** * @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); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; import "./eigenlayer/IStrategy.sol"; import "./ssvNetwork/ISSVNetworkCore.sol"; interface INodeDelegator { // struct struct DepositData { bytes[] publicKeys; bytes[] signatures; bytes32[] depositDataRoots; } struct SSVPayload { uint64[] operatorIds; bytes[] sharesData; uint256 amount; ISSVNetworkCore.Cluster cluster; } // event event AssetDepositIntoStrategy(address indexed asset, address indexed strategy, uint256 depositAmount); event EigenPodCreated(address indexed createdEigenPod); event RewardsForwarded(address indexed destinatino, uint256 amount); event WithdrawalQueuedToEigenLayer( bytes32[] withdrawalRoot, IStrategy[] strategies, address[] assets, uint256[] withdrawalAmounts, uint256 startBlock ); event DelegationAddressUpdated(address delegate); event GasSpent(address indexed spender, uint256 gasUsed); event GasRefunded(address indexed receiver, uint256 gasRefund); event NewProofSubmitter(address indexed oldProofSubmitter, address indexed _newProofSubmitter); event AVSRewardClaimerUpdated(address indexed _prevClaimer, address indexed _newClaimer); event BufferFilled(uint256 amount); // errors error TokenTransferFailed(); error StrategyIsNotSetForAsset(); error NoPubKeysProvided(); error EigenPodExisted(); error EigenPodDoesNotExist(); error InvalidCall(); error InvalidCaller(); error AtLeastOneValidator(); error MaxValidatorsInput(); error PublicKeyNotMatch(); error SignaturesNotMatch(); error DelegateAddressAlreadySet(); error InvalidAmount(); // methods function depositAssetIntoStrategy(address asset) external; function maxApproveToEigenStrategyManager(address asset) external; function getAssetBalances() external view returns (address[] memory, uint256[] memory); function getAssetBalance(address asset) external view returns (uint256); function getEthBalance() external view returns (uint256); function createEigenPod() external; function queueWithdrawalToEigenLayer(address[] memory assets, uint256[] memory amount) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; interface IEigenpieStaking { //errors error TokenTransferFailed(); error InvalidAmountToDeposit(); error NotEnoughAssetToTransfer(); error MaximumDepositLimitReached(); error MaximumNodeDelegatorLimitReached(); error InvalidMaximumNodeDelegatorLimit(); error MinimumAmountToReceiveNotMet(); error InvalidIndex(); error NativeTokenTransferFailed(); error InvalidCaller(); error LengthMismatch(); error OnlyWhenPredeposit(); error IncorrectAssetForNativeToken(); error InvalidCycle(); //events event MaxNodeDelegatorLimitUpdated(uint256 maxNodeDelegatorLimit); event NodeDelegatorAddedinQueue(address[] nodeDelegatorContracts); event AssetDeposit( address indexed depositor, address indexed asset, uint256 depositAmount, address indexed referral, uint256 mintedAmount, bool isPreDepsoit ); event MinAmountToDepositUpdated(uint256 minAmountToDeposit); event PreDepositHelperChanged(address oldPreDepositHelper, address newPreDepositHelper); event PreDepositStatusChanged(bool newIsPreDeposit); struct PoolInfo { address mlrtReceipt; } function depositAsset(address asset, uint256 depositAmount, uint256 minRec, address referral) external payable; function getTotalAssetDeposits(address asset) external view returns (uint256); function getAssetCurrentLimit(address asset) 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 assetLyingInEWD ); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IMLRT is IERC20 { function updateExchangeRateToLST(uint256 _newRate) external; function exchangeRateToLST() external view returns (uint256); function underlyingAsset() external view returns (address); function mint(address to, uint256 amount) external; function burnFrom(address account, uint256 amount) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.21; interface IEigenpiePreDepositHelper { function feedUserDeposit(address user, address asset, uint256 mintedAmount) external; function withdraw(uint256 _cycle, address _user, address _asset, address _receipt, uint256 _mlrtAmount) external; function claimableCycles(uint256 cycle) external returns (bool isClaimmable); }
// 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 (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: GPL-3.0-or-later pragma solidity 0.8.21; import { IDelegationManager } from "./eigenlayer/IDelegationManager.sol"; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; interface IEigenpieWithdrawManager { struct UserWithdrawalSchedule { uint256 receiptMLRTAmt; uint256 queuedWithdrawLSTAmt; uint256 claimedAmt; uint256 endTime; } struct WithdrawalSum { uint256 assetTotalToWithdrawAmt; uint256 assetTotalWithdrawQueued; uint256 mLRTTotalToBurn; bool mLRTburnt; } struct EthWithdrawQueue { uint256 queuedWithdrawToFill; uint256 queuedWithdrawFilled; } /// @dev Struct for WithdrawRequest queue status with expected to be filled struct WithdrawQueueStatus { bool queued; uint256 fillAt; } //errors error InvalidAmount(); error LengthMismatch(); error EpochNotYetReached(); error NotWithdrawAllQueuedRequest(); error NativeWithdrawNotSupported(); error QueuedWithdrawalNotFilled(); error InvalidInput(); error WithdrawalNotYetClaimable(); error InvalidNonce(); error PlatformTokenNotSupported(); //events event UserQueuingForWithdrawal( address indexed user, address indexed asset, uint256 mLRTAmount, uint256 LSTAmt, uint256 currentEpoch, uint256 endTime ); event ETHWithdrawn(address indexed user, uint256 nonce, uint256 ethAmt); event WithdrawBufferTargetUpdated(uint256 oldBufferTarget, uint256 newBufferTarget); event EthBufferFilled(uint256 amount); event QueueFilledForETH(uint256 amount); event AssetWithdrawn(address indexed user, address indexed asset, uint256 LSTAmt); event EpochUpdated(uint256 newEpochTime); event VestingWithdrawalCleanUpThresholdUpdated(uint256 newThreshold); function getWithdrawDeficit() external returns (uint256 bufferToFill); function fillEthWithdrawBuffer() external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./UtilLib.sol"; library TransferHelper { using UtilLib for address; function safeTransferToken(address token, address to, uint256 value) internal { if (token.isNativeToken()) { safeTransferETH(to, value); } else { safeTransfer(IERC20(token), to, value); } } function safeTransferETH(address to, uint256 value) internal { (bool success,) = address(to).call{ value: value }(""); require(success, "TransferHelper: Sending ETH failed"); } function balanceOf(address token, address addr) internal view returns (uint256) { if (token.isNativeToken()) { return addr.balance; } else { return IERC20(token).balanceOf(addr); } } function safeTransfer(IERC20 token, address to, uint256 value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))) -> 0xa9059cbb (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed" ); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))) -> 0x23b872dd (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransferFrom: transfer failed" ); } }
// 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: GPL-3.0-or-later pragma solidity 0.8.21; interface IEigenpieConfig { // Errors error ValueAlreadyInUse(); error AssetAlreadySupported(); error AssetNotSupported(); error CallerNotEigenpieConfigAdmin(); error CallerNotEigenpieConfigManager(); error CallerNotEigenpieConfigOracle(); error CallerNotEigenpieConfigOracleAdmin(); error CallerNotEigenpieConfigPriceProvider(); error CallerNotEigenpieConfigMinter(); error CallerNotEigenpieConfigBurner(); error CallerNotEigenpiePauser(); error CallerNotEigenpieConfigAllowedRole(string role); error CallerNotEigenpieConfigAllowedBot(); // Events event SetContract(bytes32 key, address indexed contractAddr); event AddedNewSupportedAsset(address indexed asset, address indexed receipt, uint256 depositLimit); event ReceiptTokenUpdated(address indexed asset, address indexed receipt); event RemovedSupportedAsset(address indexed asset); event AssetDepositLimitUpdate(address indexed asset, uint256 depositLimit); event AssetStrategyUpdate(address indexed asset, address indexed strategy); event AssetBoostUpdate(address indexed asset, uint256 newBoost); event ReferralUpdate(address indexed me, address indexed myReferral); event MLRTBridgeUpdated(address indexed receipt, address indexed mlrtBridge); event BaseGasAmountSpentUpdated(uint256 newBaseGasAmountSpent); // methods function baseGasAmountSpent() external returns (uint256); function assetStrategy(address asset) external view returns (address); function boostByAsset(address) external view returns (uint256); function mLRTReceiptByAsset(address) external view returns (address); function isSupportedAsset(address asset) external view returns (bool); function getContract(bytes32 contractId) external view returns (address); function getSupportedAssetList() external view returns (address[] memory); function depositLimitByAsset(address asset) external view returns (uint256); function getMLRTBridgeByReceipt(address receipt) external view returns (address); }
// 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: BUSL-1.1 pragma solidity 0.8.21; 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 { /** * @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 `recipient`'s address * @param recipient 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 recipient, 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 convenience function for fetching the current total shares of `user` in this strategy, by * querying the `strategyManager` contract */ function shares(address user) external view 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: GPL-3.0-or-later pragma solidity 0.8.21; interface ISSVNetworkCore { /** * */ /* Structs */ /** * */ /// @notice Represents a snapshot of an operator's or a DAO's state at a certain block struct Snapshot { /// @dev The block number when the snapshot was taken uint32 block; /// @dev The last index calculated by the formula index += (currentBlock - block) * fee uint64 index; /// @dev Total accumulated earnings calculated by the formula accumulated + lastIndex * validatorCount uint64 balance; } /// @notice Represents an SSV operator struct Operator { /// @dev The number of validators associated with this operator uint32 validatorCount; /// @dev The fee charged by the operator, set to zero for private operators and cannot be increased once set uint64 fee; /// @dev The address of the operator's owner address owner; /// @dev Whitelisted flag for this operator bool whitelisted; /// @dev The state snapshot of the operator Snapshot snapshot; } /// @notice Represents a request to change an operator's fee struct OperatorFeeChangeRequest { /// @dev The new fee proposed by the operator uint64 fee; /// @dev The time when the approval period for the fee change begins uint64 approvalBeginTime; /// @dev The time when the approval period for the fee change ends uint64 approvalEndTime; } /// @notice Represents a cluster of validators struct Cluster { /// @dev The number of validators in the cluster uint32 validatorCount; /// @dev The index of network fees related to this cluster uint64 networkFeeIndex; /// @dev The last index calculated for the cluster uint64 index; /// @dev Flag indicating whether the cluster is active bool active; /// @dev The balance of the cluster uint256 balance; } /** * */ /* Errors */ /** * */ error CallerNotOwner(); // 0x5cd83192 error CallerNotWhitelisted(); // 0x8c6e5d71 error FeeTooLow(); // 0x732f9413 error FeeExceedsIncreaseLimit(); // 0x958065d9 error NoFeeDeclared(); // 0x1d226c30 error ApprovalNotWithinTimeframe(); // 0x97e4b518 error OperatorDoesNotExist(); // 0x961e3e8c error InsufficientBalance(); // 0xf4d678b8 error ValidatorDoesNotExist(); // 0xe51315d2 error ClusterNotLiquidatable(); // 0x60300a8d error InvalidPublicKeyLength(); // 0x637297a4 error InvalidOperatorIdsLength(); // 0x38186224 error ClusterAlreadyEnabled(); // 0x3babafd2 error ClusterIsLiquidated(); // 0x95a0cf33 error ClusterDoesNotExists(); // 0x185e2b16 error IncorrectClusterState(); // 0x12e04c87 error UnsortedOperatorsList(); // 0xdd020e25 error NewBlockPeriodIsBelowMinimum(); // 0x6e6c9cac error ExceedValidatorLimit(); // 0x6df5ab76 error TokenTransferFailed(); // 0x045c4b02 error SameFeeChangeNotAllowed(); // 0xc81272f8 error FeeIncreaseNotAllowed(); // 0x410a2b6c error NotAuthorized(); // 0xea8e4eb5 error OperatorsListNotUnique(); // 0xa5a1ff5d error OperatorAlreadyExists(); // 0x289c9494 error TargetModuleDoesNotExist(); // 0x8f9195fb error MaxValueExceeded(); // 0x91aa3017 error FeeTooHigh(); // 0xcd4e6167 error PublicKeysSharesLengthMismatch(); // 0x9ad467b8 error IncorrectValidatorStateWithData(bytes publicKey); // 0x89307938 error ValidatorAlreadyExistsWithData(bytes publicKey); // 0x388e7999 // legacy errors error ValidatorAlreadyExists(); // 0x8d09a73e error IncorrectValidatorState(); // 0x2feda3c1 }
// 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: BUSL-1.1 pragma solidity 0.8.21; import "./IStrategy.sol"; import "./ISignatureUtils.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 IDelegationManager is ISignatureUtils { // @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); /** * @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 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 Caller delegates a staker's stake to an operator with valid signatures from both parties. * @param staker The account delegating stake to an `operator` account * @param operator The account (`staker`) is delegating its assets to for use in serving applications built on * EigenLayer. * @param stakerSignatureAndExpiry Signed data from the staker authorizing delegating stake to an operator * @param approverSignatureAndExpiry is a parameter that will be used for verifying that the operator approves of * this delegation action in the event that: * @param approverSalt Is a salt used to help guarantee signature uniqueness. Each salt can only be used once by a * given approver. * * @dev If `staker` is an EOA, then `stakerSignature` is verified to be a valid ECDSA stakerSignature from `staker`, * indicating their intention for this action. * @dev If `staker` is a contract, then `stakerSignature` will be checked according to EIP-1271. * @dev the operator's `delegationApprover` address is set to a non-zero value. * @dev 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 This function will revert if the current `block.timestamp` is equal to or exceeds the expiry * @dev In the case 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 delegateToBySignature( address staker, address operator, SignatureWithExpiry memory stakerSignatureAndExpiry, SignatureWithExpiry memory approverSignatureAndExpiry, bytes32 approverSalt ) 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); function getDelegatableShares(address staker) external view returns (IStrategy[] memory, uint256[] memory); function pendingWithdrawals(bytes32 withdrawalRoot) external view; }
// 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.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); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; /** * @title The interface for common signature utilities. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface ISignatureUtils { // @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 Struct that bundles together a signature, a salt for uniqueness, and an expiration time for the // signature. Used primarily for stack management. struct SignatureWithSaltAndExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the salt used to generate the signature bytes32 salt; // the expiration timestamp (UTC) of the signature uint256 expiry; } }
{ "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/", "@arbitrum/=node_modules/@arbitrum/", "@axelar-network/=node_modules/@axelar-network/", "@chainlink/=node_modules/@chainlink/", "@eth-optimism/=node_modules/@eth-optimism/", "@layerzerolabs/=node_modules/@layerzerolabs/", "@offchainlabs/=node_modules/@offchainlabs/", "@scroll-tech/=node_modules/@scroll-tech/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "hardhat-deploy/=node_modules/hardhat-deploy/", "hardhat/=node_modules/hardhat/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solidity-bytes-utils/=node_modules/solidity-bytes-utils/", "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", "libraries": { "contracts/libraries/AssetManagementLib.sol": { "AssetManagementLib": "0x70d11a9d02f329ddcde30f5381f04262450758fd" }, "contracts/libraries/ValidatorLib.sol": { "ValidatorLib": "0x98b00a422005aaee4faa2c6dc3b7322e4a4988c3" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetNotSupported","type":"error"},{"inputs":[],"name":"CallerNotEigenpieConfigAdmin","type":"error"},{"inputs":[],"name":"CallerNotEigenpieConfigAllowedBot","type":"error"},{"inputs":[],"name":"CallerNotEigenpieConfigManager","type":"error"},{"inputs":[],"name":"EpochNotYetReached","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"NativeWithdrawNotSupported","type":"error"},{"inputs":[],"name":"NotWithdrawAllQueuedRequest","type":"error"},{"inputs":[],"name":"PlatformTokenNotSupported","type":"error"},{"inputs":[],"name":"QueuedWithdrawalNotFilled","type":"error"},{"inputs":[],"name":"WithdrawalNotYetClaimable","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"LSTAmt","type":"uint256"}],"name":"AssetWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmt","type":"uint256"}],"name":"ETHWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newEpochTime","type":"uint256"}],"name":"EpochUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EthBufferFilled","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":"uint256","name":"amount","type":"uint256"}],"name":"QueueFilledForETH","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":"eigenpieConfig","type":"address"}],"name":"UpdatedEigenpieConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"mLRTAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"LSTAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"UserQueuingForWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"VestingWithdrawalCleanUpThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldBufferTarget","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBufferTarget","type":"uint256"}],"name":"WithdrawBufferTargetUpdated","type":"event"},{"inputs":[],"name":"EPOCH_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_epochTime","type":"uint256"}],"name":"assetEpochKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eigenpieConfig","outputs":[{"internalType":"contract IEigenpieConfig","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethClaimReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethWithdrawQueue","outputs":[{"internalType":"uint256","name":"queuedWithdrawToFill","type":"uint256"},{"internalType":"uint256","name":"queuedWithdrawFilled","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fillEthWithdrawBuffer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAvailableToWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"getUserQueuedWithdraw","outputs":[{"internalType":"uint256[]","name":"queuedAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"claimableAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"claimedAmounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address[]","name":"assets","type":"address[]"}],"name":"getUserWithdrawalSchedules","outputs":[{"internalType":"uint256[][]","name":"queuedLstAmounts","type":"uint256[][]"},{"internalType":"uint256[][]","name":"endTimes","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserWithdrawalSchedulesETH","outputs":[{"internalType":"uint256[]","name":"nonces","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"receiptMLRTAmt","type":"uint256"},{"internalType":"uint256","name":"queuedWithdrawLSTAmt","type":"uint256"},{"internalType":"uint256","name":"claimedAmt","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"internalType":"struct IEigenpieWithdrawManager.UserWithdrawalSchedule[]","name":"schedules","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawDeficit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"eigenpieConfigAddr","type":"address"},{"internalType":"uint256","name":"_lstWithdrawalDelay","type":"uint256"},{"internalType":"uint256","name":"_startTimestamp","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lstWithdrawalDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextUserWithdrawalTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonceToSchedule","outputs":[{"internalType":"uint256","name":"receiptMLRTAmt","type":"uint256"},{"internalType":"uint256","name":"queuedWithdrawLSTAmt","type":"uint256"},{"internalType":"uint256","name":"claimedAmt","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"nodeDelegators","type":"address[]"},{"internalType":"address[][]","name":"nodeToAssets","type":"address[][]"},{"internalType":"uint256[][]","name":"nodeToAmounts","type":"uint256[][]"},{"internalType":"uint256","name":"epochNumber","type":"uint256"}],"name":"queuingWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"eigenpieConfigAddr","type":"address"}],"name":"updateEigenpieConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newBufferTarget","type":"uint256"}],"name":"updateWithdrawBufferTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newThreshold","type":"uint256"}],"name":"updateWithdrawalScheduleCleanUpThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"mLRTamount","type":"uint256"}],"name":"userQueuingForWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_asset","type":"address"}],"name":"userToAssetKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"}],"name":"userWithdrawAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"userWithdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawQueued","outputs":[{"internalType":"bool","name":"queued","type":"bool"},{"internalType":"uint256","name":"fillAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawRequestNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalBufferTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalSchedules","outputs":[{"internalType":"uint256","name":"receiptMLRTAmt","type":"uint256"},{"internalType":"uint256","name":"queuedWithdrawLSTAmt","type":"uint256"},{"internalType":"uint256","name":"claimedAmt","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawalSums","outputs":[{"internalType":"uint256","name":"assetTotalToWithdrawAmt","type":"uint256"},{"internalType":"uint256","name":"assetTotalWithdrawQueued","type":"uint256"},{"internalType":"uint256","name":"mLRTTotalToBurn","type":"uint256"},{"internalType":"bool","name":"mLRTburnt","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalscheduleCleanUp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801562000010575f80fd5b506200001b62000021565b620000e2565b603254610100900460ff16156200008e5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60325460ff90811614620000e0576032805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6140b080620000f05f395ff3fe608060405260043610610229575f3560e01c80637a1ac61e11610131578063a914e193116100ac578063e5ac5fb81161007c578063f39e75a611610062578063f39e75a6146106af578063f682d572146106c3578063f6d55c33146106d8575f80fd5b8063e5ac5fb814610635578063e6fd48bc1461069a575f80fd5b8063a914e193146105ab578063b0729762146105ca578063c669fbff146105f7578063e320e0ed14610616575f80fd5b80638d9cb2491161010157806391a3fdd3116100e757806391a3fdd3146105615780639848b83414610576578063a70b9f0c14610595575f80fd5b80638d9cb2491461051757806390fa64a01461052b575f80fd5b80637a1ac61e146104a65780637bdd88f0146104c55780638456cb59146104e457806388b856c7146104f8575f80fd5b8063532db4f8116101c15780636794bab2116101915780636bc5efbf116101775780636bc5efbf146104055780636f5766aa146104325780637667180814610492575f80fd5b80636794bab2146103de5780636a6015ba146103fd575f80fd5b8063532db4f8146103505780635c975abb1461036f5780635f8f4e9d1461039157806362a35c00146103b0575f80fd5b806312ee14a8116101fc57806312ee14a8146102d75780632c5867c9146102f85780633f4ba83a14610327578063418b40541461033b575f80fd5b806309c022031461022d5780630a1cf78214610254578063102108e61461026957806310f7f5e8146102b8575b5f80fd5b348015610238575f80fd5b506102416106ed565b6040519081526020015b60405180910390f35b34801561025f575f80fd5b5061024160d35481565b348015610274575f80fd5b506102a16102833660046137a3565b60ce6020525f90815260409020805460019091015460ff9091169082565b60408051921515835260208301919091520161024b565b3480156102c3575f80fd5b506102416102d23660046137ce565b610751565b3480156102e2575f80fd5b506102f66102f13660046137a3565b610767565b005b348015610303575f80fd5b5060d15460d254610312919082565b6040805192835260208301919091520161024b565b348015610332575f80fd5b506102f66108db565b348015610346575f80fd5b5061024160d45481565b34801561035b575f80fd5b506102f661036a3660046138ea565b6109a4565b34801561037a575f80fd5b5060655460ff16604051901515815260200161024b565b34801561039c575f80fd5b506102416103ab3660046137ce565b610e52565b3480156103bb575f80fd5b506103cf6103ca36600461391c565b610e7d565b60405161024b939291906139a2565b3480156103e9575f80fd5b506102f66103f83660046139e4565b610e99565b6102f6610fc0565b348015610410575f80fd5b5061042461041f36600461391c565b611101565b60405161024b929190613a79565b34801561043d575f80fd5b5061047261044c3660046137a3565b60d06020525f908152604090208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161024b565b34801561049d575f80fd5b506102416113c0565b3480156104b1575f80fd5b506102f66104c0366004613aa6565b6113ed565b3480156104d0575f80fd5b506102f66104df3660046137a3565b6115c6565b3480156104ef575f80fd5b506102f66118d1565b348015610503575f80fd5b50610472610512366004613ad8565b6119b7565b348015610522575f80fd5b506102416119f9565b348015610536575f80fd5b505f54610549906001600160a01b031681565b6040516001600160a01b03909116815260200161024b565b34801561056c575f80fd5b5061024160c95481565b348015610581575f80fd5b506102f6610590366004613bd3565b611a35565b3480156105a0575f80fd5b5061024162093a8081565b3480156105b6575f80fd5b506102f66105c53660046137a3565b612174565b3480156105d5575f80fd5b506105e96105e43660046139e4565b612278565b60405161024b929190613cc9565b348015610602575f80fd5b50610241610611366004613d3d565b612403565b348015610621575f80fd5b506102f66106303660046137ce565b612411565b348015610640575f80fd5b5061067861064f3660046137a3565b60cd6020525f908152604090208054600182015460028301546003909301549192909160ff1684565b604080519485526020850193909352918301521515606082015260800161024b565b3480156106a5575f80fd5b5061024160ca5481565b3480156106ba575f80fd5b5061024161295f565b3480156106ce575f80fd5b5061024160d55481565b3480156106e3575f80fd5b5061024160cb5481565b5f806106f761295f565b90505f8160d35411610709575f610717565b8160d3546107179190613da1565b60d25460d1549192505f911161072d575f61073d565b60d25460d15461073d9190613da1565b90506107498183613db4565b935050505090565b5f61075e5f84845f61296e565b90505b92915050565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa1580156107cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f09190613dc7565b610826576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81116108a05760405162461bcd60e51b815260206004820152602760248201527f4e6577207468726573686f6c64206d757374206265206772656174657220746860448201527f616e207a65726f0000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b60cb8190556040518181527fe5a006de9c2205acdf7ab8a9c1011f7cd0e6274c27ca1ee5e06adaa642661ebe9060200160405180910390a150565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa158015610940573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109649190613dc7565b61099a576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a2612a15565b565b6109ac612a67565b6109b4612aba565b5f815167ffffffffffffffff8111156109cf576109cf6137f8565b6040519080825280602002602001820160405280156109f8578160200160208202803683370190505b5090505f5b8251811015610ac0575f610a12826001613db4565b90505b8351811015610aad57838181518110610a3057610a30613de6565b60200260200101516001600160a01b0316848381518110610a5357610a53613de6565b60200260200101516001600160a01b031603610a9b576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610aa581613e13565b915050610a15565b5080610ab881613e13565b9150506109fd565b505f5b8251811015610e395773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316838281518110610afc57610afc613de6565b60200260200101516001600160a01b031603610b44576040517f4390561100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610b6833858481518110610b5b57610b5b613de6565b6020026020010151612403565b5f81815260cc6020526040812091925080805b8354811015610c22575f848281548110610b9757610b97613de6565b905f5260205f209060040201905080600301544210158015610bbb57506002810154155b15610beb5782610bca81613e13565b600183015460028401819055909450610be4915085613db4565b9350610c19565b80600301544210158015610c06575080600101548160020154145b15610c195782610c1581613e13565b9350505b50600101610b7b565b5080868681518110610c3657610c36613de6565b602002602001018181525050868581518110610c5457610c54613de6565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdf9190613e4a565b821115610d8657868581518110610cf857610cf8613de6565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610d5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d839190613e4a565b91505b8115610e2a57610dc33383898881518110610da357610da3613de6565b60200260200101516001600160a01b0316612b139092919063ffffffff16565b868581518110610dd557610dd5613de6565b60200260200101516001600160a01b0316336001600160a01b03167f6f9cbac839b826cc524f53d10416c053fce34ec15fd1001720e777cc49720e7684604051610e2191815260200190565b60405180910390a35b84600101945050505050610ac3565b50610e448282612bc1565b50610e4f6001609755565b50565b60cf602052815f5260405f208181548110610e6b575f80fd5b905f5260205f20015f91509150505481565b6060806060610e8c8585612d9d565b9250925092509250925092565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa158015610efe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f229190613dc7565b610f58576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f6181613028565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038316908117825560405190917f2efdefb1c59d8a7dfe9f3c23f4f98ebc2d088d8ffb45f79d70535c43db1e013a91a250565b610fc8612a67565b610fd0612aba565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527f6a2a6c613a4ff62d7649e286480ba498a446d8f822e2432a3fd8ffcbcb26b4cd60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611054573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110789190613dc7565b6110ae576040517fa615882000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6110b834613068565b90507fdaaff7644a104b05650ed8d2c1c7b17d856e8f2fc89e4c159a1b0700d96d7b306110e58234613da1565b60405190815260200160405180910390a1506109a26001609755565b606080825167ffffffffffffffff81111561111e5761111e6137f8565b60405190808252806020026020018201604052801561115157816020015b606081526020019060019003908161113c5790505b509150825167ffffffffffffffff81111561116e5761116e6137f8565b6040519080825280602002602001820160405280156111a157816020015b606081526020019060019003908161118c5790505b5090505f5b83518110156113b8575f6111c686868481518110610b5b57610b5b613de6565b90505f60cc5f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020015f905b82821015611250578382905f5260205f2090600402016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050815260200190600101906111f9565b5050505090505f815167ffffffffffffffff811115611271576112716137f8565b60405190808252806020026020018201604052801561129a578160200160208202803683370190505b5090505f825167ffffffffffffffff8111156112b8576112b86137f8565b6040519080825280602002602001820160405280156112e1578160200160208202803683370190505b5090505f5b8351811015611364575f84828151811061130257611302613de6565b60200260200101519050806020015184838151811061132357611323613de6565b602002602001018181525050806060015183838151811061134657611346613de6565b6020908102919091010152508061135c81613e13565b9150506112e6565b508187868151811061137857611378613de6565b60200260200101819052508086868151811061139657611396613de6565b60200260200101819052505050505080806113b090613e13565b9150506111a6565b509250929050565b5f62093a8060ca54426113d39190613da1565b6113dd9190613e61565b6113e8906001613db4565b905090565b603254610100900460ff161580801561140d5750603254600160ff909116105b806114275750303b158015611427575060325460ff166001145b6114995760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610897565b6032805460ff1916600117905580156114d957603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6114e284613028565b6114ea613111565b6114f2613196565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038616908117825560c985905560ca849055600560cb5560405190917f2efdefb1c59d8a7dfe9f3c23f4f98ebc2d088d8ffb45f79d70535c43db1e013a91a280156115c057603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6115ce612a67565b6115d6612aba565b335f90815260cf602052604081209080805b8354811015611630578484828154811061160457611604613de6565b905f5260205f2001540361161e5760019250809150611630565b8061162881613e13565b9150506115e8565b5081611668576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84815260d06020526040902060038101544210156116b3576040517fc7b5fe8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208082018890523382840152825180830384018152606090920183528151918101919091205f81815260ce9092529190205460ff16801561170a575060d2545f82815260ce6020526040902060010154115b15611741576040517f38f06c7800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f826001015490508060d45f82825461175a9190613da1565b90915550505f80546040517fe046dd2b00000000000000000000000000000000000000000000000000000000815273efefefefefefefefefefefefefefefefefefefef60048201526001600160a01b039091169063e046dd2b90602401602060405180830381865afa1580156117d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f69190613e99565b84546040517f79cc679000000000000000000000000000000000000000000000000000000000815230600482015260248101919091529091506001600160a01b038216906379cc6790906044015f604051808303815f87803b15801561185a575f80fd5b505af115801561186c573d5f803e3d5ffd5b5050505061187a338361321b565b61188533868a6132e0565b604080518981526020810184905233917fd3605746397fcbe273096353855da8c40c332aa45d2d97a5e19130a238e9e3bc910160405180910390a250505050505050610e4f6001609755565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527faf290d8680820aad922855f39b306097b20e28774d6c1ad35a20325630c3a02c60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611955573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119799190613dc7565b6119af576040517fd519ed8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a26133ba565b60cc602052815f5260405f2081815481106119d0575f80fd5b5f9182526020909120600490910201805460018201546002830154600390930154919450925084565b5f60c95462093a80611a096113c0565b611a14906001613db4565b611a1e9190613eb4565b60ca54611a2b9190613db4565b6113e89190613db4565b611a3d612a67565b611a45612aba565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527f6a2a6c613a4ff62d7649e286480ba498a446d8f822e2432a3fd8ffcbcb26b4cd60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611ac9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aed9190613dc7565b611b23576040517fa615882000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82518451141580611b3657508151845114155b15611b6d576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8451811015611bed57828181518110611b8a57611b8a613de6565b602002602001015151848281518110611ba557611ba5613de6565b60200260200101515114611be5576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101611b6f565b50611bf66113c0565b8110611c2e576040517f1617d71c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8451811015611e9c575f848281518110611c4c57611c4c613de6565b60200260200101515190505f5b81811015611de95773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316868481518110611c9157611c91613de6565b60200260200101518281518110611caa57611caa613de6565b60200260200101516001600160a01b031603611cf2576040517f4390561100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f868481518110611d0557611d05613de6565b60200260200101518281518110611d1e57611d1e613de6565b602002602001015185604051602001611d6892919060609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b60408051601f1981840301815291815281516020928301205f81815260cd9093529120875191925090879086908110611da357611da3613de6565b60200260200101518381518110611dbc57611dbc613de6565b6020026020010151816001015f828254611dd69190613db4565b909155505060019092019150611c599050565b50858281518110611dfc57611dfc613de6565b60200260200101516001600160a01b031663176b8b26868481518110611e2457611e24613de6565b6020026020010151868581518110611e3e57611e3e613de6565b60200260200101516040518363ffffffff1660e01b8152600401611e63929190613ecb565b5f604051808303815f87803b158015611e7a575f80fd5b505af1158015611e8c573d5f803e3d5ffd5b5050505081600101915050611c30565b505f805f9054906101000a90046001600160a01b03166001600160a01b031663770672a66040518163ffffffff1660e01b81526004015f60405180830381865afa158015611eec573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611f139190810190613f20565b90505f5b81518110156121685773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316828281518110611f5057611f50613de6565b60200260200101516001600160a01b031614612160575f828281518110611f7957611f79613de6565b602002602001015184604051602001611fc392919060609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b60408051601f1981840301815291815281516020928301205f81815260cd909352912060018101548154929350909114612029576040517f1cb7066f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038101805460ff191660019081179091558101541561215d575f805485516001600160a01b039091169063e046dd2b9087908790811061206c5761206c613de6565b60200260200101516040518263ffffffff1660e01b815260040161209f91906001600160a01b0391909116815260200190565b602060405180830381865afa1580156120ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120de9190613e99565b60028301546040517f79cc679000000000000000000000000000000000000000000000000000000000815230600482015260248101919091529091506001600160a01b038216906379cc6790906044015f604051808303815f87803b158015612145575f80fd5b505af1158015612157573d5f803e3d5ffd5b50505050505b50505b600101611f17565b50506115c06001609755565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa1580156121d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fd9190613dc7565b612233576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d380549082905560408051828152602081018490527f0884f0006f038c6e064ae7dcb5c147db5430e3152ecae73e6d72ab913e4d6d58910160405180910390a15050565b6001600160a01b0381165f90815260cf602090815260408083208054825181850281018501909352808352606094859490939291908301828280156122da57602002820191905f5260205f20905b8154815260200190600101908083116122c6575b505050505090505f815190505f8167ffffffffffffffff811115612300576123006137f8565b60405190808252806020026020018201604052801561235857816020015b61234560405180608001604052805f81526020015f81526020015f81526020015f81525090565b81526020019060019003908161231e5790505b5090505f5b828110156123f6575f84828151811061237857612378613de6565b6020026020010151905060d05f8281526020019081526020015f206040518060800160405290815f820154815260200160018201548152602001600282015481526020016003820154815250508383815181106123d7576123d7613de6565b60200260200101819052505080806123ee90613e13565b91505061235d565b5091959194509092505050565b5f61075e83835f600161296e565b612419612a67565b612421612aba565b5f546040517f9be918e60000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015284921690639be918e690602401602060405180830381865afa158015612481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124a59190613dc7565b6124db576040517f981a2a2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fe046dd2b0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063e046dd2b90602401602060405180830381865afa15801561253c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125609190613e99565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523360048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125e49190613e4a565b905080841115612620576040517f2c5211c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6126296113c0565b90505f6126363388612403565b90505f6126438884610751565b90505f856001600160a01b031663b38362146040518163ffffffff1660e01b8152600401602060405180830381865afa158015612682573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a69190613e4a565b90505f670de0b6b3a76400006126bc8a84613eb4565b6126c69190613e61565b90505f6126d16119f9565b90505f60405180608001604052808c81526020018481526020015f815260200183815250905073efefefefefefefefefefefefefefefefefefefef6001600160a01b03168c6001600160a01b031603612852575f61272d61295f565b60d580549192505f61273e83613e13565b909155505060d554335f90815260cf602090815260408083208054600181810183559185528385200185905584845260d0835292819020865181559186015192820192909255908401516002820155606084015160039091015581851115612834578160d45f8282546127b19190613db4565b909155505060d280548391905f906127ca908490613db4565b909155505060d180548691905f906127e3908490613db4565b90915550506040805160208082018490523382840152825180830384018152606090920183528151918101919091205f90815260ce90915220805460ff19166001908117825560d15491015561284b565b8460d45f8282546128459190613db4565b90915550505b50506128dd565b5f85815260cd60205260408120805490918591839190612873908490613db4565b925050819055508b816002015f82825461288d9190613db4565b9091555050505f86815260cc602090815260408083208054600181810183559185529383902085516004909502019384559184015191830191909155820151600282015560608201516003909101555b6128f26001600160a01b038a1633308e6133f7565b604080518c815260208101859052908101889052606081018390526001600160a01b038d169033907fe3d373fc0d45b583082ab11e27c1fc455bb6811ae97c1b7c62ab25c9c0559d219060800160405180910390a35050505050505050505061295b6001609755565b5050565b5f60d454476113e89190613da1565b5f81156129cf576040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087811b8216602084015286901b1660348201526048015b604051602081830303815290604052805190602001209050612a0d565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b166020820152603481018490526054016129b2565b949350505050565b612a1d613448565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff16156109a25760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610897565b600260975403612b0c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610897565b6002609755565b6040516001600160a01b038316602482015260448101829052612bbc9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261349a565b505050565b5f5b8251811015612bbc575f612be333858481518110610b5b57610b5b613de6565b5f81815260cc6020526040902060cb5485519293509091859085908110612c0c57612c0c613de6565b602002602001015110612d8c575f5b848481518110612c2d57612c2d613de6565b60200260200101518280549050612c449190613da1565b811015612cdf5781858581518110612c5e57612c5e613de6565b602002602001015182612c719190613db4565b81548110612c8157612c81613de6565b905f5260205f209060040201828281548110612c9f57612c9f613de6565b905f5260205f2090600402015f820154815f0155600182015481600101556002820154816002015560038201548160030155905050806001019050612c1b565b505b5f848481518110612cf457612cf4613de6565b60200260200101511115612d8c5780805480612d1257612d12613faa565b5f8281526020812060047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020181815560018101829055600281018290556003015590558351849084908110612d6f57612d6f613de6565b602002602001018051809190612d8490613fd7565b905250612ce1565b5050600101612bc3565b6001609755565b6060806060835167ffffffffffffffff811115612dbc57612dbc6137f8565b604051908082528060200260200182016040528015612de5578160200160208202803683370190505b509250835167ffffffffffffffff811115612e0257612e026137f8565b604051908082528060200260200182016040528015612e2b578160200160208202803683370190505b509150835167ffffffffffffffff811115612e4857612e486137f8565b604051908082528060200260200182016040528015612e71578160200160208202803683370190505b5090505f5b8451811015613020575f612e9687878481518110610b5b57610b5b613de6565b90505f805f8060cc5f8681526020019081526020015f20805480602002602001604051908101604052809291908181526020015f905b82821015612f23578382905f5260205f2090600402016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505081526020019060010190612ecc565b5050505090505f5b8151811015612fb2575f828281518110612f4757612f47613de6565b602002602001015190505f42826060015111158015612f6857506040820151155b90508015612f82576020820151612f7f9086613db4565b94505b6020820151612f919088613db4565b9650816040015186612fa39190613db4565b95508260010192505050612f2b565b5083898781518110612fc657612fc6613de6565b60200260200101818152505081888781518110612fe557612fe5613de6565b6020026020010181815250508287878151811061300457613004613de6565b6020026020010181815250508560010195505050505050612e76565b509250925092565b6001600160a01b038116610e4f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25460d1545f9182911161307d575f61308d565b60d25460d15461308d9190613da1565b90505f811561310a578382116130a357816130a5565b835b90508060d45f8282546130b89190613db4565b909155505060d280548291905f906130d1908490613db4565b90915550506040518181527f6b5402b61625e0a38ade9f6f6e6f1860ceac27b746de0d8997ea8cee72be40669060200160405180910390a15b9392505050565b603254610100900460ff1661318e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6109a2613580565b603254610100900460ff166132135760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6109a2613609565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613264576040519150601f19603f3d011682016040523d82523d5f602084013e613269565b606091505b5050905080612bbc5760405162461bcd60e51b815260206004820152602260248201527f5472616e7366657248656c7065723a2053656e64696e6720455448206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610897565b6001600160a01b0383165f90815260cf60205260408120805490919061330890600190613da1565b90508084101561334b5781818154811061332457613324613de6565b905f5260205f20015482858154811061333f5761333f613de6565b5f918252602090912001555b8180548061335b5761335b613faa565b5f828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810183905590920190925593815260d09093525050604081208181556001810182905560028101829055600301555050565b6133c2612a67565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a4a3390565b6040516001600160a01b03808516602483015283166044820152606481018290526115c09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612b58565b60655460ff166109a25760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610897565b5f6134ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136869092919063ffffffff16565b905080515f148061350e57508080602001905181019061350e9190613dc7565b612bbc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610897565b603254610100900460ff166135fd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6065805460ff19169055565b603254610100900460ff16612d965760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6060612a0d84845f85855f80866001600160a01b031685876040516136ab919061402d565b5f6040518083038185875af1925050503d805f81146136e5576040519150601f19603f3d011682016040523d82523d5f602084013e6136ea565b606091505b50915091506136fb87838387613706565b979650505050505050565b606083156137745782515f0361376d576001600160a01b0385163b61376d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610897565b5081612a0d565b612a0d83838151156137895781518083602001fd5b8060405162461bcd60e51b81526004016108979190614048565b5f602082840312156137b3575f80fd5b5035919050565b6001600160a01b0381168114610e4f575f80fd5b5f80604083850312156137df575f80fd5b82356137ea816137ba565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561384e5761384e6137f8565b604052919050565b5f67ffffffffffffffff82111561386f5761386f6137f8565b5060051b60200190565b5f82601f830112613888575f80fd5b8135602061389d61389883613856565b613825565b82815260059290921b840181019181810190868411156138bb575f80fd5b8286015b848110156138df5780356138d2816137ba565b83529183019183016138bf565b509695505050505050565b5f602082840312156138fa575f80fd5b813567ffffffffffffffff811115613910575f80fd5b612a0d84828501613879565b5f806040838503121561392d575f80fd5b8235613938816137ba565b9150602083013567ffffffffffffffff811115613953575f80fd5b61395f85828601613879565b9150509250929050565b5f8151808452602080850194508084015f5b838110156139975781518752958201959082019060010161397b565b509495945050505050565b606081525f6139b46060830186613969565b82810360208401526139c68186613969565b905082810360408401526139da8185613969565b9695505050505050565b5f602082840312156139f4575f80fd5b813561310a816137ba565b5f81518084526020808501808196508360051b810191508286015f805b86811015613a6b578385038a52825180518087529087019087870190845b81811015613a5657835183529289019291890191600101613a3a565b50509a87019a95505091850191600101613a1c565b509298975050505050505050565b604081525f613a8b60408301856139ff565b8281036020840152613a9d81856139ff565b95945050505050565b5f805f60608486031215613ab8575f80fd5b8335613ac3816137ba565b95602085013595506040909401359392505050565b5f8060408385031215613ae9575f80fd5b50508035926020909101359150565b5f82601f830112613b07575f80fd5b81356020613b1761389883613856565b828152600592831b8501820192828201919087851115613b35575f80fd5b8387015b85811015613bc657803567ffffffffffffffff811115613b58575f8081fd5b8801603f81018a13613b69575f8081fd5b858101356040613b7b61389883613856565b82815291851b8301810191888101908d841115613b97575f8081fd5b938201935b83851015613bb557843582529389019390890190613b9c565b885250505093850193508401613b39565b5090979650505050505050565b5f805f8060808587031215613be6575f80fd5b843567ffffffffffffffff80821115613bfd575f80fd5b613c0988838901613879565b9550602091508187013581811115613c1f575f80fd5b8701601f81018913613c2f575f80fd5b8035613c3d61389882613856565b81815260059190911b8201840190848101908b831115613c5b575f80fd5b8584015b83811015613c9257803586811115613c76575f8081fd5b613c848e8983890101613879565b845250918601918601613c5f565b5097505050506040870135915080821115613cab575f80fd5b50613cb887828801613af8565b949793965093946060013593505050565b5f6040808352613cdb81840186613969565b8381036020858101919091528551808352868201928201905f5b81811015613d2f57845180518452848101518585015286810151878501526060908101519084015293830193608090920191600101613cf5565b509098975050505050505050565b5f8060408385031215613d4e575f80fd5b8235613d59816137ba565b91506020830135613d69816137ba565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561076157610761613d74565b8082018082111561076157610761613d74565b5f60208284031215613dd7575f80fd5b8151801515811461310a575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613e4357613e43613d74565b5060010190565b5f60208284031215613e5a575f80fd5b5051919050565b5f82613e94577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f60208284031215613ea9575f80fd5b815161310a816137ba565b808202811582820484141761076157610761613d74565b604080825283519082018190525f906020906060840190828701845b82811015613f0c5781516001600160a01b031684529284019290840190600101613ee7565b505050838103828501526139da8186613969565b5f6020808385031215613f31575f80fd5b825167ffffffffffffffff811115613f47575f80fd5b8301601f81018513613f57575f80fd5b8051613f6561389882613856565b81815260059190911b82018301908381019087831115613f83575f80fd5b928401925b828410156136fb578351613f9b816137ba565b82529284019290840190613f88565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81613fe557613fe5613d74565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f5b8381101561402557818101518382015260200161400d565b50505f910152565b5f825161403e81846020870161400b565b9190910192915050565b602081525f825180602084015261406681604085016020870161400b565b601f01601f1916919091016040019291505056fea26469706673582212207c74a4dcb64c887a07963dc13f1e4bf63a1102249f051dfe1722a1cb984d032c64736f6c63430008150033
Deployed Bytecode
0x608060405260043610610229575f3560e01c80637a1ac61e11610131578063a914e193116100ac578063e5ac5fb81161007c578063f39e75a611610062578063f39e75a6146106af578063f682d572146106c3578063f6d55c33146106d8575f80fd5b8063e5ac5fb814610635578063e6fd48bc1461069a575f80fd5b8063a914e193146105ab578063b0729762146105ca578063c669fbff146105f7578063e320e0ed14610616575f80fd5b80638d9cb2491161010157806391a3fdd3116100e757806391a3fdd3146105615780639848b83414610576578063a70b9f0c14610595575f80fd5b80638d9cb2491461051757806390fa64a01461052b575f80fd5b80637a1ac61e146104a65780637bdd88f0146104c55780638456cb59146104e457806388b856c7146104f8575f80fd5b8063532db4f8116101c15780636794bab2116101915780636bc5efbf116101775780636bc5efbf146104055780636f5766aa146104325780637667180814610492575f80fd5b80636794bab2146103de5780636a6015ba146103fd575f80fd5b8063532db4f8146103505780635c975abb1461036f5780635f8f4e9d1461039157806362a35c00146103b0575f80fd5b806312ee14a8116101fc57806312ee14a8146102d75780632c5867c9146102f85780633f4ba83a14610327578063418b40541461033b575f80fd5b806309c022031461022d5780630a1cf78214610254578063102108e61461026957806310f7f5e8146102b8575b5f80fd5b348015610238575f80fd5b506102416106ed565b6040519081526020015b60405180910390f35b34801561025f575f80fd5b5061024160d35481565b348015610274575f80fd5b506102a16102833660046137a3565b60ce6020525f90815260409020805460019091015460ff9091169082565b60408051921515835260208301919091520161024b565b3480156102c3575f80fd5b506102416102d23660046137ce565b610751565b3480156102e2575f80fd5b506102f66102f13660046137a3565b610767565b005b348015610303575f80fd5b5060d15460d254610312919082565b6040805192835260208301919091520161024b565b348015610332575f80fd5b506102f66108db565b348015610346575f80fd5b5061024160d45481565b34801561035b575f80fd5b506102f661036a3660046138ea565b6109a4565b34801561037a575f80fd5b5060655460ff16604051901515815260200161024b565b34801561039c575f80fd5b506102416103ab3660046137ce565b610e52565b3480156103bb575f80fd5b506103cf6103ca36600461391c565b610e7d565b60405161024b939291906139a2565b3480156103e9575f80fd5b506102f66103f83660046139e4565b610e99565b6102f6610fc0565b348015610410575f80fd5b5061042461041f36600461391c565b611101565b60405161024b929190613a79565b34801561043d575f80fd5b5061047261044c3660046137a3565b60d06020525f908152604090208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161024b565b34801561049d575f80fd5b506102416113c0565b3480156104b1575f80fd5b506102f66104c0366004613aa6565b6113ed565b3480156104d0575f80fd5b506102f66104df3660046137a3565b6115c6565b3480156104ef575f80fd5b506102f66118d1565b348015610503575f80fd5b50610472610512366004613ad8565b6119b7565b348015610522575f80fd5b506102416119f9565b348015610536575f80fd5b505f54610549906001600160a01b031681565b6040516001600160a01b03909116815260200161024b565b34801561056c575f80fd5b5061024160c95481565b348015610581575f80fd5b506102f6610590366004613bd3565b611a35565b3480156105a0575f80fd5b5061024162093a8081565b3480156105b6575f80fd5b506102f66105c53660046137a3565b612174565b3480156105d5575f80fd5b506105e96105e43660046139e4565b612278565b60405161024b929190613cc9565b348015610602575f80fd5b50610241610611366004613d3d565b612403565b348015610621575f80fd5b506102f66106303660046137ce565b612411565b348015610640575f80fd5b5061067861064f3660046137a3565b60cd6020525f908152604090208054600182015460028301546003909301549192909160ff1684565b604080519485526020850193909352918301521515606082015260800161024b565b3480156106a5575f80fd5b5061024160ca5481565b3480156106ba575f80fd5b5061024161295f565b3480156106ce575f80fd5b5061024160d55481565b3480156106e3575f80fd5b5061024160cb5481565b5f806106f761295f565b90505f8160d35411610709575f610717565b8160d3546107179190613da1565b60d25460d1549192505f911161072d575f61073d565b60d25460d15461073d9190613da1565b90506107498183613db4565b935050505090565b5f61075e5f84845f61296e565b90505b92915050565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa1580156107cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f09190613dc7565b610826576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81116108a05760405162461bcd60e51b815260206004820152602760248201527f4e6577207468726573686f6c64206d757374206265206772656174657220746860448201527f616e207a65726f0000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b60cb8190556040518181527fe5a006de9c2205acdf7ab8a9c1011f7cd0e6274c27ca1ee5e06adaa642661ebe9060200160405180910390a150565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa158015610940573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109649190613dc7565b61099a576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a2612a15565b565b6109ac612a67565b6109b4612aba565b5f815167ffffffffffffffff8111156109cf576109cf6137f8565b6040519080825280602002602001820160405280156109f8578160200160208202803683370190505b5090505f5b8251811015610ac0575f610a12826001613db4565b90505b8351811015610aad57838181518110610a3057610a30613de6565b60200260200101516001600160a01b0316848381518110610a5357610a53613de6565b60200260200101516001600160a01b031603610a9b576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610aa581613e13565b915050610a15565b5080610ab881613e13565b9150506109fd565b505f5b8251811015610e395773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316838281518110610afc57610afc613de6565b60200260200101516001600160a01b031603610b44576040517f4390561100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610b6833858481518110610b5b57610b5b613de6565b6020026020010151612403565b5f81815260cc6020526040812091925080805b8354811015610c22575f848281548110610b9757610b97613de6565b905f5260205f209060040201905080600301544210158015610bbb57506002810154155b15610beb5782610bca81613e13565b600183015460028401819055909450610be4915085613db4565b9350610c19565b80600301544210158015610c06575080600101548160020154145b15610c195782610c1581613e13565b9350505b50600101610b7b565b5080868681518110610c3657610c36613de6565b602002602001018181525050868581518110610c5457610c54613de6565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdf9190613e4a565b821115610d8657868581518110610cf857610cf8613de6565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610d5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d839190613e4a565b91505b8115610e2a57610dc33383898881518110610da357610da3613de6565b60200260200101516001600160a01b0316612b139092919063ffffffff16565b868581518110610dd557610dd5613de6565b60200260200101516001600160a01b0316336001600160a01b03167f6f9cbac839b826cc524f53d10416c053fce34ec15fd1001720e777cc49720e7684604051610e2191815260200190565b60405180910390a35b84600101945050505050610ac3565b50610e448282612bc1565b50610e4f6001609755565b50565b60cf602052815f5260405f208181548110610e6b575f80fd5b905f5260205f20015f91509150505481565b6060806060610e8c8585612d9d565b9250925092509250925092565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa158015610efe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f229190613dc7565b610f58576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f6181613028565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038316908117825560405190917f2efdefb1c59d8a7dfe9f3c23f4f98ebc2d088d8ffb45f79d70535c43db1e013a91a250565b610fc8612a67565b610fd0612aba565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527f6a2a6c613a4ff62d7649e286480ba498a446d8f822e2432a3fd8ffcbcb26b4cd60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611054573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110789190613dc7565b6110ae576040517fa615882000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6110b834613068565b90507fdaaff7644a104b05650ed8d2c1c7b17d856e8f2fc89e4c159a1b0700d96d7b306110e58234613da1565b60405190815260200160405180910390a1506109a26001609755565b606080825167ffffffffffffffff81111561111e5761111e6137f8565b60405190808252806020026020018201604052801561115157816020015b606081526020019060019003908161113c5790505b509150825167ffffffffffffffff81111561116e5761116e6137f8565b6040519080825280602002602001820160405280156111a157816020015b606081526020019060019003908161118c5790505b5090505f5b83518110156113b8575f6111c686868481518110610b5b57610b5b613de6565b90505f60cc5f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020015f905b82821015611250578382905f5260205f2090600402016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050815260200190600101906111f9565b5050505090505f815167ffffffffffffffff811115611271576112716137f8565b60405190808252806020026020018201604052801561129a578160200160208202803683370190505b5090505f825167ffffffffffffffff8111156112b8576112b86137f8565b6040519080825280602002602001820160405280156112e1578160200160208202803683370190505b5090505f5b8351811015611364575f84828151811061130257611302613de6565b60200260200101519050806020015184838151811061132357611323613de6565b602002602001018181525050806060015183838151811061134657611346613de6565b6020908102919091010152508061135c81613e13565b9150506112e6565b508187868151811061137857611378613de6565b60200260200101819052508086868151811061139657611396613de6565b60200260200101819052505050505080806113b090613e13565b9150506111a6565b509250929050565b5f62093a8060ca54426113d39190613da1565b6113dd9190613e61565b6113e8906001613db4565b905090565b603254610100900460ff161580801561140d5750603254600160ff909116105b806114275750303b158015611427575060325460ff166001145b6114995760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610897565b6032805460ff1916600117905580156114d957603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6114e284613028565b6114ea613111565b6114f2613196565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038616908117825560c985905560ca849055600560cb5560405190917f2efdefb1c59d8a7dfe9f3c23f4f98ebc2d088d8ffb45f79d70535c43db1e013a91a280156115c057603280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6115ce612a67565b6115d6612aba565b335f90815260cf602052604081209080805b8354811015611630578484828154811061160457611604613de6565b905f5260205f2001540361161e5760019250809150611630565b8061162881613e13565b9150506115e8565b5081611668576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f84815260d06020526040902060038101544210156116b3576040517fc7b5fe8f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208082018890523382840152825180830384018152606090920183528151918101919091205f81815260ce9092529190205460ff16801561170a575060d2545f82815260ce6020526040902060010154115b15611741576040517f38f06c7800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f826001015490508060d45f82825461175a9190613da1565b90915550505f80546040517fe046dd2b00000000000000000000000000000000000000000000000000000000815273efefefefefefefefefefefefefefefefefefefef60048201526001600160a01b039091169063e046dd2b90602401602060405180830381865afa1580156117d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f69190613e99565b84546040517f79cc679000000000000000000000000000000000000000000000000000000000815230600482015260248101919091529091506001600160a01b038216906379cc6790906044015f604051808303815f87803b15801561185a575f80fd5b505af115801561186c573d5f803e3d5ffd5b5050505061187a338361321b565b61188533868a6132e0565b604080518981526020810184905233917fd3605746397fcbe273096353855da8c40c332aa45d2d97a5e19130a238e9e3bc910160405180910390a250505050505050610e4f6001609755565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527faf290d8680820aad922855f39b306097b20e28774d6c1ad35a20325630c3a02c60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611955573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119799190613dc7565b6119af576040517fd519ed8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a26133ba565b60cc602052815f5260405f2081815481106119d0575f80fd5b5f9182526020909120600490910201805460018201546002830154600390930154919450925084565b5f60c95462093a80611a096113c0565b611a14906001613db4565b611a1e9190613eb4565b60ca54611a2b9190613db4565b6113e89190613db4565b611a3d612a67565b611a45612aba565b5f546040517f91d148540000000000000000000000000000000000000000000000000000000081527f6a2a6c613a4ff62d7649e286480ba498a446d8f822e2432a3fd8ffcbcb26b4cd60048201523360248201526001600160a01b03909116906391d1485490604401602060405180830381865afa158015611ac9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aed9190613dc7565b611b23576040517fa615882000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82518451141580611b3657508151845114155b15611b6d576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8451811015611bed57828181518110611b8a57611b8a613de6565b602002602001015151848281518110611ba557611ba5613de6565b60200260200101515114611be5576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101611b6f565b50611bf66113c0565b8110611c2e576040517f1617d71c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b8451811015611e9c575f848281518110611c4c57611c4c613de6565b60200260200101515190505f5b81811015611de95773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316868481518110611c9157611c91613de6565b60200260200101518281518110611caa57611caa613de6565b60200260200101516001600160a01b031603611cf2576040517f4390561100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f868481518110611d0557611d05613de6565b60200260200101518281518110611d1e57611d1e613de6565b602002602001015185604051602001611d6892919060609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b60408051601f1981840301815291815281516020928301205f81815260cd9093529120875191925090879086908110611da357611da3613de6565b60200260200101518381518110611dbc57611dbc613de6565b6020026020010151816001015f828254611dd69190613db4565b909155505060019092019150611c599050565b50858281518110611dfc57611dfc613de6565b60200260200101516001600160a01b031663176b8b26868481518110611e2457611e24613de6565b6020026020010151868581518110611e3e57611e3e613de6565b60200260200101516040518363ffffffff1660e01b8152600401611e63929190613ecb565b5f604051808303815f87803b158015611e7a575f80fd5b505af1158015611e8c573d5f803e3d5ffd5b5050505081600101915050611c30565b505f805f9054906101000a90046001600160a01b03166001600160a01b031663770672a66040518163ffffffff1660e01b81526004015f60405180830381865afa158015611eec573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611f139190810190613f20565b90505f5b81518110156121685773efefefefefefefefefefefefefefefefefefefef6001600160a01b0316828281518110611f5057611f50613de6565b60200260200101516001600160a01b031614612160575f828281518110611f7957611f79613de6565b602002602001015184604051602001611fc392919060609290921b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000168252601482015260340190565b60408051601f1981840301815291815281516020928301205f81815260cd909352912060018101548154929350909114612029576040517f1cb7066f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038101805460ff191660019081179091558101541561215d575f805485516001600160a01b039091169063e046dd2b9087908790811061206c5761206c613de6565b60200260200101516040518263ffffffff1660e01b815260040161209f91906001600160a01b0391909116815260200190565b602060405180830381865afa1580156120ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120de9190613e99565b60028301546040517f79cc679000000000000000000000000000000000000000000000000000000000815230600482015260248101919091529091506001600160a01b038216906379cc6790906044015f604051808303815f87803b158015612145575f80fd5b505af1158015612157573d5f803e3d5ffd5b50505050505b50505b600101611f17565b50506115c06001609755565b5f80546040517f91d1485400000000000000000000000000000000000000000000000000000000815260048101929092523360248301526001600160a01b0316906391d1485490604401602060405180830381865afa1580156121d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fd9190613dc7565b612233576040517fbda7a53b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d380549082905560408051828152602081018490527f0884f0006f038c6e064ae7dcb5c147db5430e3152ecae73e6d72ab913e4d6d58910160405180910390a15050565b6001600160a01b0381165f90815260cf602090815260408083208054825181850281018501909352808352606094859490939291908301828280156122da57602002820191905f5260205f20905b8154815260200190600101908083116122c6575b505050505090505f815190505f8167ffffffffffffffff811115612300576123006137f8565b60405190808252806020026020018201604052801561235857816020015b61234560405180608001604052805f81526020015f81526020015f81526020015f81525090565b81526020019060019003908161231e5790505b5090505f5b828110156123f6575f84828151811061237857612378613de6565b6020026020010151905060d05f8281526020019081526020015f206040518060800160405290815f820154815260200160018201548152602001600282015481526020016003820154815250508383815181106123d7576123d7613de6565b60200260200101819052505080806123ee90613e13565b91505061235d565b5091959194509092505050565b5f61075e83835f600161296e565b612419612a67565b612421612aba565b5f546040517f9be918e60000000000000000000000000000000000000000000000000000000081526001600160a01b03808516600483015284921690639be918e690602401602060405180830381865afa158015612481573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124a59190613dc7565b6124db576040517f981a2a2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80546040517fe046dd2b0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063e046dd2b90602401602060405180830381865afa15801561253c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125609190613e99565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523360048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156125c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125e49190613e4a565b905080841115612620576040517f2c5211c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6126296113c0565b90505f6126363388612403565b90505f6126438884610751565b90505f856001600160a01b031663b38362146040518163ffffffff1660e01b8152600401602060405180830381865afa158015612682573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a69190613e4a565b90505f670de0b6b3a76400006126bc8a84613eb4565b6126c69190613e61565b90505f6126d16119f9565b90505f60405180608001604052808c81526020018481526020015f815260200183815250905073efefefefefefefefefefefefefefefefefefefef6001600160a01b03168c6001600160a01b031603612852575f61272d61295f565b60d580549192505f61273e83613e13565b909155505060d554335f90815260cf602090815260408083208054600181810183559185528385200185905584845260d0835292819020865181559186015192820192909255908401516002820155606084015160039091015581851115612834578160d45f8282546127b19190613db4565b909155505060d280548391905f906127ca908490613db4565b909155505060d180548691905f906127e3908490613db4565b90915550506040805160208082018490523382840152825180830384018152606090920183528151918101919091205f90815260ce90915220805460ff19166001908117825560d15491015561284b565b8460d45f8282546128459190613db4565b90915550505b50506128dd565b5f85815260cd60205260408120805490918591839190612873908490613db4565b925050819055508b816002015f82825461288d9190613db4565b9091555050505f86815260cc602090815260408083208054600181810183559185529383902085516004909502019384559184015191830191909155820151600282015560608201516003909101555b6128f26001600160a01b038a1633308e6133f7565b604080518c815260208101859052908101889052606081018390526001600160a01b038d169033907fe3d373fc0d45b583082ab11e27c1fc455bb6811ae97c1b7c62ab25c9c0559d219060800160405180910390a35050505050505050505061295b6001609755565b5050565b5f60d454476113e89190613da1565b5f81156129cf576040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087811b8216602084015286901b1660348201526048015b604051602081830303815290604052805190602001209050612a0d565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b166020820152603481018490526054016129b2565b949350505050565b612a1d613448565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60655460ff16156109a25760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610897565b600260975403612b0c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610897565b6002609755565b6040516001600160a01b038316602482015260448101829052612bbc9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261349a565b505050565b5f5b8251811015612bbc575f612be333858481518110610b5b57610b5b613de6565b5f81815260cc6020526040902060cb5485519293509091859085908110612c0c57612c0c613de6565b602002602001015110612d8c575f5b848481518110612c2d57612c2d613de6565b60200260200101518280549050612c449190613da1565b811015612cdf5781858581518110612c5e57612c5e613de6565b602002602001015182612c719190613db4565b81548110612c8157612c81613de6565b905f5260205f209060040201828281548110612c9f57612c9f613de6565b905f5260205f2090600402015f820154815f0155600182015481600101556002820154816002015560038201548160030155905050806001019050612c1b565b505b5f848481518110612cf457612cf4613de6565b60200260200101511115612d8c5780805480612d1257612d12613faa565b5f8281526020812060047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020181815560018101829055600281018290556003015590558351849084908110612d6f57612d6f613de6565b602002602001018051809190612d8490613fd7565b905250612ce1565b5050600101612bc3565b6001609755565b6060806060835167ffffffffffffffff811115612dbc57612dbc6137f8565b604051908082528060200260200182016040528015612de5578160200160208202803683370190505b509250835167ffffffffffffffff811115612e0257612e026137f8565b604051908082528060200260200182016040528015612e2b578160200160208202803683370190505b509150835167ffffffffffffffff811115612e4857612e486137f8565b604051908082528060200260200182016040528015612e71578160200160208202803683370190505b5090505f5b8451811015613020575f612e9687878481518110610b5b57610b5b613de6565b90505f805f8060cc5f8681526020019081526020015f20805480602002602001604051908101604052809291908181526020015f905b82821015612f23578382905f5260205f2090600402016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505081526020019060010190612ecc565b5050505090505f5b8151811015612fb2575f828281518110612f4757612f47613de6565b602002602001015190505f42826060015111158015612f6857506040820151155b90508015612f82576020820151612f7f9086613db4565b94505b6020820151612f919088613db4565b9650816040015186612fa39190613db4565b95508260010192505050612f2b565b5083898781518110612fc657612fc6613de6565b60200260200101818152505081888781518110612fe557612fe5613de6565b6020026020010181815250508287878151811061300457613004613de6565b6020026020010181815250508560010195505050505050612e76565b509250925092565b6001600160a01b038116610e4f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25460d1545f9182911161307d575f61308d565b60d25460d15461308d9190613da1565b90505f811561310a578382116130a357816130a5565b835b90508060d45f8282546130b89190613db4565b909155505060d280548291905f906130d1908490613db4565b90915550506040518181527f6b5402b61625e0a38ade9f6f6e6f1860ceac27b746de0d8997ea8cee72be40669060200160405180910390a15b9392505050565b603254610100900460ff1661318e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6109a2613580565b603254610100900460ff166132135760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6109a2613609565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114613264576040519150601f19603f3d011682016040523d82523d5f602084013e613269565b606091505b5050905080612bbc5760405162461bcd60e51b815260206004820152602260248201527f5472616e7366657248656c7065723a2053656e64696e6720455448206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610897565b6001600160a01b0383165f90815260cf60205260408120805490919061330890600190613da1565b90508084101561334b5781818154811061332457613324613de6565b905f5260205f20015482858154811061333f5761333f613de6565b5f918252602090912001555b8180548061335b5761335b613faa565b5f828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810183905590920190925593815260d09093525050604081208181556001810182905560028101829055600301555050565b6133c2612a67565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a4a3390565b6040516001600160a01b03808516602483015283166044820152606481018290526115c09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612b58565b60655460ff166109a25760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610897565b5f6134ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136869092919063ffffffff16565b905080515f148061350e57508080602001905181019061350e9190613dc7565b612bbc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610897565b603254610100900460ff166135fd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6065805460ff19169055565b603254610100900460ff16612d965760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610897565b6060612a0d84845f85855f80866001600160a01b031685876040516136ab919061402d565b5f6040518083038185875af1925050503d805f81146136e5576040519150601f19603f3d011682016040523d82523d5f602084013e6136ea565b606091505b50915091506136fb87838387613706565b979650505050505050565b606083156137745782515f0361376d576001600160a01b0385163b61376d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610897565b5081612a0d565b612a0d83838151156137895781518083602001fd5b8060405162461bcd60e51b81526004016108979190614048565b5f602082840312156137b3575f80fd5b5035919050565b6001600160a01b0381168114610e4f575f80fd5b5f80604083850312156137df575f80fd5b82356137ea816137ba565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561384e5761384e6137f8565b604052919050565b5f67ffffffffffffffff82111561386f5761386f6137f8565b5060051b60200190565b5f82601f830112613888575f80fd5b8135602061389d61389883613856565b613825565b82815260059290921b840181019181810190868411156138bb575f80fd5b8286015b848110156138df5780356138d2816137ba565b83529183019183016138bf565b509695505050505050565b5f602082840312156138fa575f80fd5b813567ffffffffffffffff811115613910575f80fd5b612a0d84828501613879565b5f806040838503121561392d575f80fd5b8235613938816137ba565b9150602083013567ffffffffffffffff811115613953575f80fd5b61395f85828601613879565b9150509250929050565b5f8151808452602080850194508084015f5b838110156139975781518752958201959082019060010161397b565b509495945050505050565b606081525f6139b46060830186613969565b82810360208401526139c68186613969565b905082810360408401526139da8185613969565b9695505050505050565b5f602082840312156139f4575f80fd5b813561310a816137ba565b5f81518084526020808501808196508360051b810191508286015f805b86811015613a6b578385038a52825180518087529087019087870190845b81811015613a5657835183529289019291890191600101613a3a565b50509a87019a95505091850191600101613a1c565b509298975050505050505050565b604081525f613a8b60408301856139ff565b8281036020840152613a9d81856139ff565b95945050505050565b5f805f60608486031215613ab8575f80fd5b8335613ac3816137ba565b95602085013595506040909401359392505050565b5f8060408385031215613ae9575f80fd5b50508035926020909101359150565b5f82601f830112613b07575f80fd5b81356020613b1761389883613856565b828152600592831b8501820192828201919087851115613b35575f80fd5b8387015b85811015613bc657803567ffffffffffffffff811115613b58575f8081fd5b8801603f81018a13613b69575f8081fd5b858101356040613b7b61389883613856565b82815291851b8301810191888101908d841115613b97575f8081fd5b938201935b83851015613bb557843582529389019390890190613b9c565b885250505093850193508401613b39565b5090979650505050505050565b5f805f8060808587031215613be6575f80fd5b843567ffffffffffffffff80821115613bfd575f80fd5b613c0988838901613879565b9550602091508187013581811115613c1f575f80fd5b8701601f81018913613c2f575f80fd5b8035613c3d61389882613856565b81815260059190911b8201840190848101908b831115613c5b575f80fd5b8584015b83811015613c9257803586811115613c76575f8081fd5b613c848e8983890101613879565b845250918601918601613c5f565b5097505050506040870135915080821115613cab575f80fd5b50613cb887828801613af8565b949793965093946060013593505050565b5f6040808352613cdb81840186613969565b8381036020858101919091528551808352868201928201905f5b81811015613d2f57845180518452848101518585015286810151878501526060908101519084015293830193608090920191600101613cf5565b509098975050505050505050565b5f8060408385031215613d4e575f80fd5b8235613d59816137ba565b91506020830135613d69816137ba565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561076157610761613d74565b8082018082111561076157610761613d74565b5f60208284031215613dd7575f80fd5b8151801515811461310a575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613e4357613e43613d74565b5060010190565b5f60208284031215613e5a575f80fd5b5051919050565b5f82613e94577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f60208284031215613ea9575f80fd5b815161310a816137ba565b808202811582820484141761076157610761613d74565b604080825283519082018190525f906020906060840190828701845b82811015613f0c5781516001600160a01b031684529284019290840190600101613ee7565b505050838103828501526139da8186613969565b5f6020808385031215613f31575f80fd5b825167ffffffffffffffff811115613f47575f80fd5b8301601f81018513613f57575f80fd5b8051613f6561389882613856565b81815260059190911b82018301908381019087831115613f83575f80fd5b928401925b828410156136fb578351613f9b816137ba565b82529284019290840190613f88565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f81613fe557613fe5613d74565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f5b8381101561402557818101518382015260200161400d565b50505f910152565b5f825161403e81846020870161400b565b9190910192915050565b602081525f825180602084015261406681604085016020870161400b565b601f01601f1916919091016040019291505056fea26469706673582212207c74a4dcb64c887a07963dc13f1e4bf63a1102249f051dfe1722a1cb984d032c64736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.