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
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
NodeManager
Compiler Version
v0.8.18+commit.87f61d96
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-05-13 */ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.18; // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol) // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } // OpenZeppelin Contracts (last updated v4.8.3) (proxy/ERC1967/ERC1967Upgrade.sol) // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } // OpenZeppelin Contracts (last updated v4.8.3) (interfaces/IERC1967.sol) /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.9._ */ interface IERC1967Upgradeable { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); } // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) /** * @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 * ==== * * [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://diligence.consensys.net/posts/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.5.11/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 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); } } } // OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } } // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.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] * ``` * 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; } } /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @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; } /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @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; } // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) // OpenZeppelin Contracts v4.4.1 (utils/Context.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; } /** * @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; } // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.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 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; } // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } } /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } } /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSAUpgradeable { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } interface IRoleManager { /// @dev Returns a boolean value indicating whether `_account` has role `_roleName` or not. function checkRole(bytes32 _roleName, address _account) external view returns (bool); } interface INodeManager { /// @notice Event for Oracle reporting. /// @param reportBlockNumber : block number of report. /// @param amountRewards : Amounts of rewards. /// @param amountExited : Amounts exited on report. /// @param amountLiquid : Amounts liquid on report. event LogLiquidityTransfer( uint256 indexed reportBlockNumber, uint256 amountRewards, uint256 amountExited, uint256 amountLiquid ); /// @notice Event for Oracle reporting. /// @param reportBlockNumber : block number of report. /// @param validatorsCount : Number of validators. /// @param validatorsBalance : Total balance of validators. /// @param validatorsExited : Number of validators exited. event LogOracleReport( uint256 reportBlockNumber, uint256 validatorsCount, uint256 validatorsBalance, uint256 validatorsExited ); /// @notice Event for record of oracle participation /// @param reportBlockNumber : block number of report. /// @param oracle : Oracle address. event LogOracleVote(uint256 indexed reportBlockNumber, address indexed oracle); /// @notice Event for updating oracle whitelist. /// @param oracle : Oracle address. /// @param flag : boolean for addition or removal. event LogSetOracleWhitelist(address indexed oracle, bool indexed flag); /// @notice Event for updating autobalance registration whitelist. /// @param caller : autobalance caller address. /// @param flag : boolean for addition or removal. event LogSetAutoBalanceWhitelist(address indexed caller, bool indexed flag); /// @notice Event for validator deposit. /// @param validatorId : ID of the validator in Node Manager. /// @param publicKey : Public key of validator. /// @param validatorType : Type of validator. event LogDeposit(uint256 indexed validatorId, bytes indexed publicKey, uint256 validatorType); /// @notice Event for validator deposit. /// @param publicKey : Public key of validator. /// @param owner : Node operator address. event LogPreDeposit(bytes indexed publicKey, address indexed owner); /// @notice Event for validator deposit. /// @param validatorId : ID of the validator in Node Manager. /// @param publicKey : Public key of validator. /// @param owner : Node operator address. event LogPreDepositRefund(uint256 indexed validatorId, bytes indexed publicKey, address indexed owner); /// @notice Event for validator exit request. /// @param batchId : ID of the batch in Node Manager. /// @param withdrawCount : Number of validators exited. event LogWithdraw(uint256 indexed batchId, uint256 withdrawCount); /// @notice Event for new quorum. /// @param oldQuorum : Old oracle quorum. /// @param newQuorum : New oracle quorum. event LogSetOracleQuorum(uint256 oldQuorum, uint256 newQuorum); /// @notice Event for new node operator fee. /// @param oldFee : Old fee. /// @param newFee : New fee. event LogSetNodeOperatorFees(uint256 oldFee, uint256 newFee); /// @notice Event for setting claymain. /// @param newClaymain : Address of clayMain. event LogSetClayMain(address indexed newClaymain); /// @notice Event for setting nodeOperator. /// @param newNodeOperator : Address of nodeOperator. event LogSetNodeOperator(address indexed newNodeOperator); /// @notice Event for setting EigenLayer. /// @param eigenPodManager : Address of EigenPodManager. /// @param delayedWithdrawalRouter : Address of DelayedWithdrawalRouter. event LogSetEigenLayer(address indexed eigenPodManager, address indexed delayedWithdrawalRouter); /// @notice Event for unstaking from eigen layer. /// @param delayedWithdrawalIndex : Index of withdraw order. event LogWithdrawBeforeRestaking(uint256 indexed delayedWithdrawalIndex); /// @notice Event for claiming tokens from eigen layer. /// @param claimedAmount : Amount of tokens claimed. event LogClaimEigenLayer(uint256 claimedAmount); /// @notice Struct for validator data struct Validator { bytes publicKey; bytes signature; uint256 validatorType; } /// @notice Struct for validator view struct ValidatorView { uint256 id; bytes publicKey; uint256 validatorType; } /// @notice Deposits / Withdraws while registering validators with the specified parameters. /// @dev Anyone can call the function as long as no registration occurs ir order to close NetStaking batches. /// @param _publicKey The public key(s) of the validator. /// @param _signature The signature(s) of the validator. /// @param _deposit_data_root The deposit data root(s) of the validator. /// @param _validatorType The type of the validator code internally used. /// @return A boolean indicating whether the registration was successful. function autoBalance( bytes[] memory _publicKey, bytes[] memory _signature, bytes32[] memory _deposit_data_root, uint256[] memory _validatorType ) external returns (bool); /// @notice Returns the balance of the contract accounting for pending staking. function getBalance() external view returns (uint256); /// @notice Returns whether the address is a whitelisted autobalancer. function autobalanceWhitelist(address _caller) external view returns (bool); } interface ICSToken { /// @notice Returns the amount of tokens in existence. function totalSupply() external view returns (uint256); /// @notice Returns the amount of tokens owned by `_account`. function balanceOf(address _account) external view returns (uint256); /// @notice Mints `_amount` of tokens `_to` user. function mint(address _to, uint256 _amount) external returns (bool); /// @notice Burns `_amount` of tokens `_from` user. function burn(address _from, uint256 _amount) external returns (bool); /// @notice Transfers `_amount` of tokens `_to` user. function transfer(address _to, uint256 _amount) external returns (bool); } interface IClayMain { /// @notice Supported fee types. Matches fees ordering. enum SetFee { DepositFee, WithdrawFee, InstantWithdrawFee } /// @notice Struct used on ClayMatic fees struct Fees { uint256 depositFee; uint256 withdrawFee; uint256 instantWithdrawFee; } /// @notice Struct used on ClayMatic for returning user withdraw order struct UserWithdrawOrderInfo { uint256 orderId; uint256 amount; uint256 fee; uint256 claimableAt; bool isClaimable; } /// @notice Struct to track internal funds accounting /// @param currentDeposit : Total user deposits backing csETH /// @param withdrawQueue : Current amount of ETH waiting in the queue to be withdrawn by users /// @param stakedDeposit : Amount of ETH currently staked with validators without including exit requests /// @param unstakeExternal : Amount of ETH staked, yet in the process to be withdrawn due user withdraw requests /// @param unstakeInternal : Amount of ETH staked, yet in the process to be withdrawn due to protocol balancing /// @param withdrawQueueOpen : Amount of ETH to be claimed from withdrawals on open batches /// @param claimablePool : ETH balance reserved on contract for claims. struct Funds { uint256 currentDeposit; uint256 withdrawQueue; uint256 stakedDeposit; uint256 unstakeExternal; uint256 unstakeInternal; uint256 withdrawQueueOpen; uint256 claimablePool; } /// @notice WithdrawOrder struct /// @param amount : Total amount unstaked from from ethereum. /// @param fee : Fee percentage to be paid by the user at claim time. /// @param claimableAt timestamp when batch claims can be processed /// @param batchId : Id of the batch process to be sent to ethereum. struct WithdrawOrder { uint256 amount; uint256 fee; uint256 claimableAt; uint256 batchId; } /// @notice Information on batches for withdraws /// @param claimableAt timestamp when batch claims can be processed /// @param amount : Total amount unstaked from from ethereum. /// @param amountCs : Total amount of csToken burned on batch. /// @param multiplier : Multiplier for batch accounting for slashing struct BatchWithdraw { uint256 claimableAt; uint256 amount; uint256 amountCs; uint256 multiplier; } /// @notice Exchange rate allowed percentage deviation. /// @param exchangeDecreaseLimit - Max allowed rate decrease percentage based on last valid exchange rate /// @param exchangeIncreaseLimit - Max allowed rate increase percentage based on last valid exchange rate struct ExchangeDeviation { uint256 exchangeDecreaseLimit; uint256 exchangeIncreaseLimit; } /// @notice Event for new deposit. /// @param user : Address of depositor. /// @param amount : Amount of Token deposited. /// @param amountCs : Amount of csToken minted. /// @param fee : Fee paid by user on deposit in Token event LogDeposit(address indexed user, uint256 amount, uint256 amountCs, uint256 fee); /// @notice Event for new withdraw request. /// @param user : Address of user withdrawing. /// @param orderId : Withdraw order id. /// @param amountCs : Amount of csToken burned. /// @param amount : Amount of Token withdrawn. /// @param fee : Fee percentage to be paid by the user /// @param timestamp : Epoch at the moment of request event LogWithdraw( address indexed user, uint256 orderId, uint256 amountCs, uint256 amount, uint256 fee, uint256 timestamp ); /// @notice Event for withdraw claims by user. /// @param user : Address of user. /// @param orderId : Withdraw order id. /// @param amount : Amount of Token unstaked in order. /// @param received : Amount of Token received in order. /// @param fee : Fee paid by user. event LogClaim(address indexed user, uint256 orderId, uint256 amount, uint256 received, uint256 fee); /// @notice Event for instant withdraw. /// @param user : Address of user. /// @param amountCs : Amount of csToken burned. /// @param amount : Amount of Token withdrawn. /// @param fee : Fee paid by user on instant withdraw in Token event LogInstantWithdraw(address indexed user, uint256 amountCs, uint256 amount, uint256 fee); /// @notice Event for new deposit. /// @param updatedBy : Address of Updating entity. /// @param feeType : Fee type being updated. /// @param oldFee : Existing fee percent for given fee type. /// @param newFee : New fee percent for given fee type. event LogFeeUpdate(address indexed updatedBy, SetFee feeType, uint256 oldFee, uint256 newFee); /// @notice Event emitted when AutoBalance is run. /// @param batchId : Id of the current processed batch. /// @param isNetStaking : Flag denoting net tx type of batch. /// @param amount : Amount of Token to be deposited or expected at claim. event LogAutoBalance(uint256 indexed batchId, bool indexed isNetStaking, uint256 amount); /// @notice Event for rewards recognized. /// @param rewards : Amount of rewards recognized. event LogRewards(uint256 rewards); /// @notice Event for Donations recognized. /// @param amount : Amount of donations recognized. event LogDonation(uint256 amount); /// @notice Event for batch closed. /// @param batchId : Id of the current processed batch. /// @param amount : Amount of Token to be deposited or expected at claim. /// @param amountCs : Amount of csToken burned on batch. /// @param multiplier : Multiplier for batch accounting for slashing event LogBatchClosed(uint256 indexed batchId, uint256 amount, uint256 amountCs, uint256 multiplier); /// @notice Event for imposed penalties. /// @param penaltiesToHolders : Amount of penalties to cs holders. /// @param penaltiesToClaims : Amount of penalties to be claimed. event LogPenalties(uint256 indexed penaltiesToHolders, uint256 indexed penaltiesToClaims); /// @notice Event for updated value of exchange rate /// @param rate : Updated rate value. /// @param time : Timestamp on which info is updated. event LogUpdateExchangeRate(uint256 rate, uint256 time); /// @notice Event for updating minimum claim delay. /// @param newMinClaimSeconds : New claim delay. event LogSetMinClaimTime(uint256 indexed newMinClaimSeconds); /// @notice Event for updating withdrawals. /// @param flag : bool for enabling/disabling withdrawals. event LogSetWithdrawalsDisabled(bool indexed flag); /// @notice Event for updating change update limits. /// @param newDecreaseLimit : New fx change limit floor. /// @param newIncreaseLimit : New fx change limit ceil. event LogSetExchangeDeviation(uint256 indexed newDecreaseLimit, uint256 indexed newIncreaseLimit); /// @notice Sends msg.value Token to ClayMain contract and mints csToken to msg.sender. function deposit() external payable returns (uint256); /// @notice Sends msg.value Token to ClayMain contract and mints csToken to `_delegatedTo`. function depositDelegate(address _delegatedTo) external payable returns (uint256); /// @notice Burns `_amountCs` csToken tokens from user and unstake respective amounts of Token tokens from node. function withdraw(uint256 _amountCs) external returns (uint256); /// @notice Allows user to claim unstaked tokens. function claim(uint256[] calldata _orderIds) external returns (bool); /// @notice Performs claiming of rewards & staking of Token tokens for ClayStack. function autoBalance( uint256 validatorCapacity ) external returns (uint256 currentBatchId, bool netStaking, uint256 validatorCount); /// @notice Exchange rate from csETH to ETH. function getExchangeRate() external view returns (uint256); /// @notice Returns amount of csTokens for given `_amountToken`. function exchangeToken(uint256 _amountToken) external view returns (uint256); /// @notice Returns amount of Tokens for given `_amountCsToken`. function exchangeCsToken(uint256 amountCsToken) external view returns (uint256); /// @notice Receives confirmation from NodeManager on batch finalization function closeBatches(uint256[] calldata _batchIds) external; /// @notice Receives liquidity from NodeManager for exits and rewards function receiveLiquidity(uint256 rewards, uint256 exited) external payable; /// @notice Returns instance of csToken function csToken() external returns (ICSToken); /// @notice enforceAndUpdateBalance public call function updateBalances() external; /// @notice Whether withdrawals & claims are disabled given slashing protection or other reasons function withdrawalsDisabled() external view returns (bool); /// @notice Disables withdrawals and claims function setWithdrawalsDisabled(bool _disabled) external; } // This interface is designed to be compatible with the Vyper version. /// @notice This is the Ethereum 2.0 deposit contract interface. /// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs interface IDepositContract { /// @notice A processed deposit event. event DepositEvent(bytes pubkey, bytes withdrawal_credentials, bytes amount, bytes signature, bytes index); /// @notice Submit a Phase 0 DepositData object. /// @param pubkey A BLS12-381 public key. /// @param withdrawal_credentials Commitment to a public key for withdrawals. /// @param signature A BLS12-381 signature. /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. /// Used as a protection against malformed input. function deposit( bytes calldata pubkey, bytes calldata withdrawal_credentials, bytes calldata signature, bytes32 deposit_data_root ) external payable; /// @notice Query the current deposit root hash. /// @return The deposit root hash. function get_deposit_root() external view returns (bytes32); /// @notice Query the current deposit count. /// @return The deposit count encoded as a little endian 64-bit number. function get_deposit_count() external view returns (bytes memory); } // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) /** * @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); } /** * @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 `depositor`'s address * @param depositor is the address to receive the withdrawn funds * @param token is the ERC20 token being transferred out * @param amountShares is the amount of shares being withdrawn * @dev This function is only callable by the strategyManager contract. It is invoked inside of the strategyManager's * other functions, and individual share balances are recorded in the strategyManager as well. */ function withdraw(address depositor, IERC20 token, uint256 amountShares) external; /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. * @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications * @param amountShares is the amount of shares to calculate its conversion into the underlying token * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function sharesToUnderlying(uint256 amountShares) external returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. * @notice In contrast to `underlyingToSharesView`, this function **may** make state modifications * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares * @return The amount of underlying tokens corresponding to the input `amountShares` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function underlyingToShares(uint256 amountUnderlying) external returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications */ function userUnderlying(address user) external returns (uint256); /** * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy. * @notice In contrast to `sharesToUnderlying`, this function guarantees no state modifications * @param amountShares is the amount of shares to calculate its conversion into the underlying token * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256); /** * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy. * @notice In contrast to `underlyingToShares`, this function guarantees no state modifications * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares * @return The amount of shares corresponding to the input `amountUnderlying` * @dev Implementation for these functions in particular may vary significantly for different strategies */ function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256); /** * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications */ function userUnderlyingView(address user) external view returns (uint256); /// @notice The underlying token for shares in this Strategy function underlyingToken() external view returns (IERC20); /// @notice The total number of extant shares in this Strategy function totalShares() external view returns (uint256); /// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that explains in more detail. function explanation() external view returns (string memory); } /** * @title Interface for the primary 'slashing' contract for EigenLayer. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice See the `Slasher` contract itself for implementation details. */ interface ISlasher { // struct used to store information about the current state of an operator's obligations to middlewares they are serving struct MiddlewareTimes { // The update block for the middleware whose most recent update was earliest, i.e. the 'stalest' update out of all middlewares the operator is serving uint32 stalestUpdateBlock; // The latest 'serveUntilBlock' from all of the middleware that the operator is serving uint32 latestServeUntilBlock; } // struct used to store details relevant to a single middleware that an operator has opted-in to serving struct MiddlewareDetails { // the block before which the contract is allowed to slash the user uint32 contractCanSlashOperatorUntilBlock; // the block at which the middleware's view of the operator's stake was most recently updated uint32 latestUpdateBlock; } /** * @notice Gives the `contractAddress` permission to slash the funds of the caller. * @dev Typically, this function must be called prior to registering for a middleware. */ function optIntoSlashing(address contractAddress) external; /** * @notice Used for 'slashing' a certain operator. * @param toBeFrozen The operator to be frozen. * @dev Technically the operator is 'frozen' (hence the name of this function), and then subject to slashing pending a decision by a human-in-the-loop. * @dev The operator must have previously given the caller (which should be a contract) the ability to slash them, through a call to `optIntoSlashing`. */ function freezeOperator(address toBeFrozen) external; /** * @notice Removes the 'frozen' status from each of the `frozenAddresses` * @dev Callable only by the contract owner (i.e. governance). */ function resetFrozenStatus(address[] calldata frozenAddresses) external; /** * @notice this function is a called by middlewares during an operator's registration to make sure the operator's stake at registration * is slashable until serveUntil * @param operator the operator whose stake update is being recorded * @param serveUntilBlock the block until which the operator's stake at the current block is slashable * @dev adds the middleware's slashing contract to the operator's linked list */ function recordFirstStakeUpdate(address operator, uint32 serveUntilBlock) external; /** * @notice this function is a called by middlewares during a stake update for an operator (perhaps to free pending withdrawals) * to make sure the operator's stake at updateBlock is slashable until serveUntil * @param operator the operator whose stake update is being recorded * @param updateBlock the block for which the stake update is being recorded * @param serveUntilBlock the block until which the operator's stake at updateBlock is slashable * @param insertAfter the element of the operators linked list that the currently updating middleware should be inserted after * @dev insertAfter should be calculated offchain before making the transaction that calls this. this is subject to race conditions, * but it is anticipated to be rare and not detrimental. */ function recordStakeUpdate( address operator, uint32 updateBlock, uint32 serveUntilBlock, uint256 insertAfter ) external; /** * @notice this function is a called by middlewares during an operator's deregistration to make sure the operator's stake at deregistration * is slashable until serveUntil * @param operator the operator whose stake update is being recorded * @param serveUntilBlock the block until which the operator's stake at the current block is slashable * @dev removes the middleware's slashing contract to the operator's linked list and revokes the middleware's (i.e. caller's) ability to * slash `operator` once `serveUntil` is reached */ function recordLastStakeUpdateAndRevokeSlashingAbility(address operator, uint32 serveUntilBlock) external; /** * @notice Used to determine whether `staker` is actively 'frozen'. If a staker is frozen, then they are potentially subject to * slashing of their funds, and cannot cannot deposit or withdraw from the strategyManager until the slashing process is completed * and the staker's status is reset (to 'unfrozen'). * @param staker The staker of interest. * @return Returns 'true' if `staker` themselves has their status set to frozen, OR if the staker is delegated * to an operator who has their status set to frozen. Otherwise returns 'false'. */ function isFrozen(address staker) external view returns (bool); /// @notice Returns true if `slashingContract` is currently allowed to slash `toBeSlashed`. function canSlash(address toBeSlashed, address slashingContract) external view returns (bool); /// @notice Returns the block until which `serviceContract` is allowed to slash the `operator`. function contractCanSlashOperatorUntilBlock( address operator, address serviceContract ) external view returns (uint32); /// @notice Returns the block at which the `serviceContract` last updated its view of the `operator`'s stake function latestUpdateBlock(address operator, address serviceContract) external view returns (uint32); /// @notice A search routine for finding the correct input value of `insertAfter` to `recordStakeUpdate` / `_updateMiddlewareList`. function getCorrectValueForInsertAfter(address operator, uint32 updateBlock) external view returns (uint256); /** * @notice Returns 'true' if `operator` can currently complete a withdrawal started at the `withdrawalStartBlock`, with `middlewareTimesIndex` used * to specify the index of a `MiddlewareTimes` struct in the operator's list (i.e. an index in `operatorToMiddlewareTimes[operator]`). The specified * struct is consulted as proof of the `operator`'s ability (or lack thereof) to complete the withdrawal. * This function will return 'false' if the operator cannot currently complete a withdrawal started at the `withdrawalStartBlock`, *or* in the event * that an incorrect `middlewareTimesIndex` is supplied, even if one or more correct inputs exist. * @param operator Either the operator who queued the withdrawal themselves, or if the withdrawing party is a staker who delegated to an operator, * this address is the operator *who the staker was delegated to* at the time of the `withdrawalStartBlock`. * @param withdrawalStartBlock The block number at which the withdrawal was initiated. * @param middlewareTimesIndex Indicates an index in `operatorToMiddlewareTimes[operator]` to consult as proof of the `operator`'s ability to withdraw * @dev The correct `middlewareTimesIndex` input should be computable off-chain. */ function canWithdraw( address operator, uint32 withdrawalStartBlock, uint256 middlewareTimesIndex ) external returns (bool); /** * operator => * [ * ( * the least recent update block of all of the middlewares it's serving/served, * latest time that the stake bonded at that update needed to serve until * ) * ] */ function operatorToMiddlewareTimes( address operator, uint256 arrayIndex ) external view returns (MiddlewareTimes memory); /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator].length` function middlewareTimesLength(address operator) external view returns (uint256); /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].stalestUpdateBlock`. function getMiddlewareTimesIndexBlock(address operator, uint32 index) external view returns (uint32); /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].latestServeUntil`. function getMiddlewareTimesIndexServeUntilBlock(address operator, uint32 index) external view returns (uint32); /// @notice Getter function for fetching `_operatorToWhitelistedContractsByUpdate[operator].size`. function operatorWhitelistedContractsLinkedListSize(address operator) external view returns (uint256); /// @notice Getter function for fetching a single node in the operator's linked list (`_operatorToWhitelistedContractsByUpdate[operator]`). function operatorWhitelistedContractsLinkedListEntry( address operator, address node ) external view returns (bool, uint256, uint256); } /** * @title Abstract interface for a contract that helps structure the delegation relationship. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice The gas budget provided to this contract in calls from EigenLayer contracts is limited. */ interface IDelegationTerms { function payForService(IERC20 token, uint256 amount) external payable; function onDelegationWithdrawn( address delegator, IStrategy[] memory stakerStrategyList, uint256[] memory stakerShares ) external returns (bytes memory); function onDelegationReceived( address delegator, IStrategy[] memory stakerStrategyList, uint256[] memory stakerShares ) external returns (bytes memory); } /** * @title The interface for the primary delegation contract for EigenLayer. * @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 new operators to provide a DelegationTerms-type contract, which may mediate their interactions with stakers who delegate to them * - enabling any staker to delegate its stake to the operator of its choice * - enabling a staker to undelegate its assets from an operator (performed as part of the withdrawal process, initiated through the StrategyManager) */ interface IDelegationManager { /** * @notice This will be called by an operator to register itself as an operator that stakers can choose to delegate to. * @param dt is the `DelegationTerms` contract that the operator has for those who delegate to them. * @dev An operator can set `dt` equal to their own address (or another EOA address), in the event that they want to split payments * in a more 'trustful' manner. * @dev In the present design, once set, there is no way for an operator to ever modify the address of their DelegationTerms contract. */ function registerAsOperator(IDelegationTerms dt) external; /** * @notice This will be called by a staker to delegate its assets to some operator. * @param operator is the operator to whom staker (msg.sender) is delegating its assets */ function delegateTo(address operator) external; /** * @notice Delegates from `staker` to `operator`. * @dev requires that: * 1) if `staker` is an EOA, then `signature` is valid ECDSA signature from `staker`, indicating their intention for this action * 2) if `staker` is a contract, then `signature` must will be checked according to EIP-1271 */ function delegateToBySignature(address staker, address operator, uint256 expiry, bytes memory signature) external; /** * @notice Undelegates `staker` from the operator who they are delegated to. * @notice Callable only by the StrategyManager * @dev Should only ever be called in the event that the `staker` has no active deposits in EigenLayer. */ function undelegate(address staker) external; /// @notice returns the address of the operator that `staker` is delegated to. function delegatedTo(address staker) external view returns (address); /// @notice returns the DelegationTerms of the `operator`, which may mediate their interactions with stakers who delegate to them. function delegationTerms(address operator) external view returns (IDelegationTerms); /// @notice returns the total number of shares in `strategy` that are delegated to `operator`. function operatorShares(address operator, IStrategy strategy) external view returns (uint256); /** * @notice Increases the `staker`'s delegated shares in `strategy` by `shares, typically called when the staker has further deposits into EigenLayer * @dev Callable only by the StrategyManager */ function increaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external; /** * @notice Decreases the `staker`'s delegated shares in each entry of `strategies` by its respective `shares[i]`, typically called when the staker withdraws from EigenLayer * @dev Callable only by the StrategyManager */ function decreaseDelegatedShares( address staker, IStrategy[] calldata strategies, uint256[] calldata shares ) external; /// @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise. function isDelegated(address staker) external view returns (bool); /// @notice Returns 'true' if `staker` is *not* actively delegated, and 'false' otherwise. function isNotDelegated(address staker) external view returns (bool); /// @notice Returns if an operator can be delegated to, i.e. it has called `registerAsOperator`. function isOperator(address operator) external view returns (bool); } /** * @title Interface for the primary entrypoint for funds into EigenLayer. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice See the `StrategyManager` contract itself for implementation details. */ interface IStrategyManager { // packed struct for queued withdrawals; helps deal with stack-too-deep errors struct WithdrawerAndNonce { address withdrawer; uint96 nonce; } /** * 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. `startQueuedWithdrawalWaitingPeriod` or `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 QueuedWithdrawal { IStrategy[] strategies; uint256[] shares; address depositor; WithdrawerAndNonce withdrawerAndNonce; uint32 withdrawalStartBlock; address delegatedAddress; } /** * @notice Deposits `amount` of `token` into the specified `strategy`, with the resultant shares credited to `msg.sender` * @param strategy is the specified strategy where deposit is to be made, * @param token is the denomination in which the deposit is to be made, * @param amount is the amount of token to be deposited in the strategy by the depositor * @return shares The amount of new shares in the `strategy` created as part of the action. * @dev The `msg.sender` must have previously approved this contract to transfer at least `amount` of `token` on their behalf. * @dev Cannot be called by an address that is 'frozen' (this function will revert if the `msg.sender` is frozen). * * WARNING: Depositing tokens that allow reentrancy (eg. ERC-777) into a strategy is not recommended. This can lead to attack vectors * where the token balance and corresponding strategy shares are not in sync upon reentrancy. */ function depositIntoStrategy( IStrategy strategy, IERC20 token, uint256 amount ) external returns (uint256 shares); /** * @notice Deposits `amount` of beaconchain ETH into this contract on behalf of `staker` * @param staker is the entity that is restaking in eigenlayer, * @param amount is the amount of beaconchain ETH being restaked, * @dev Only callable by EigenPodManager. */ function depositBeaconChainETH(address staker, uint256 amount) external; /** * @notice Records an overcommitment event on behalf of a staker. The staker's beaconChainETH shares are decremented by `amount`. * @param overcommittedPodOwner is the pod owner to be slashed * @param beaconChainETHStrategyIndex is the index of the beaconChainETHStrategy in case it must be removed, * @param amount is the amount to decrement the slashedAddress's beaconChainETHStrategy shares * @dev Only callable by EigenPodManager. */ function recordOvercommittedBeaconChainETH( address overcommittedPodOwner, uint256 beaconChainETHStrategyIndex, uint256 amount ) external; /** * @notice Used for depositing an asset into the specified strategy with the resultant shares credited to `staker`, * who must sign off on the action. * Note that the assets are transferred out/from the `msg.sender`, not from the `staker`; this function is explicitly designed * purely to help one address deposit 'for' another. * @param strategy is the specified strategy where deposit is to be made, * @param token is the denomination in which the deposit is to be made, * @param amount is the amount of token to be deposited in the strategy by the depositor * @param staker the staker that the deposited assets will be credited to * @param expiry the timestamp at which the signature expires * @param signature is a valid signature from the `staker`. either an ECDSA signature if the `staker` is an EOA, or data to forward * following EIP-1271 if the `staker` is a contract * @return shares The amount of new shares in the `strategy` created as part of the action. * @dev The `msg.sender` must have previously approved this contract to transfer at least `amount` of `token` on their behalf. * @dev A signature is required for this function to eliminate the possibility of griefing attacks, specifically those * targeting stakers who may be attempting to undelegate. * @dev Cannot be called on behalf of a staker that is 'frozen' (this function will revert if the `staker` is frozen). * * WARNING: Depositing tokens that allow reentrancy (eg. ERC-777) into a strategy is not recommended. This can lead to attack vectors * where the token balance and corresponding strategy shares are not in sync upon reentrancy */ function depositIntoStrategyWithSignature( IStrategy strategy, IERC20 token, uint256 amount, address staker, uint256 expiry, bytes memory signature ) external returns (uint256 shares); /// @notice Returns the current shares of `user` in `strategy` function stakerStrategyShares(address user, IStrategy strategy) external view returns (uint256 shares); /** * @notice Get all details on the depositor's deposits and corresponding shares * @return (depositor's strategies, shares in these strategies) */ function getDeposits(address depositor) external view returns (IStrategy[] memory, uint256[] memory); /// @notice Simple getter function that returns `stakerStrategyList[staker].length`. function stakerStrategyListLength(address staker) external view returns (uint256); /** * @notice Called by a staker to queue a withdrawal of the given amount of `shares` from each of the respective given `strategies`. * @dev Stakers will complete their withdrawal by calling the 'completeQueuedWithdrawal' function. * User shares are decreased in this function, but the total number of shares in each strategy remains the same. * The total number of shares is decremented in the 'completeQueuedWithdrawal' function instead, which is where * the funds are actually sent to the user through use of the strategies' 'withdrawal' function. This ensures * that the value per share reported by each strategy will remain consistent, and that the shares will continue * to accrue gains during the enforced withdrawal waiting period. * @param strategyIndexes is a list of the indices in `stakerStrategyList[msg.sender]` that correspond to the strategies * for which `msg.sender` is withdrawing 100% of their shares * @param strategies The Strategies to withdraw from * @param shares The amount of shares to withdraw from each of the respective Strategies in the `strategies` array * @param withdrawer The address that can complete the withdrawal and will receive any withdrawn funds or shares upon completing the withdrawal * @param undelegateIfPossible If this param is marked as 'true' *and the withdrawal will result in `msg.sender` having no shares in any Strategy,* * then this function will also make an internal call to `undelegate(msg.sender)` to undelegate the `msg.sender`. * @return The 'withdrawalRoot' of the newly created Queued Withdrawal * @dev Strategies are removed from `stakerStrategyList` by swapping the last entry with the entry to be removed, then * popping off the last entry in `stakerStrategyList`. The simplest way to calculate the correct `strategyIndexes` to input * is to order the strategies *for which `msg.sender` is withdrawing 100% of their shares* from highest index in * `stakerStrategyList` to lowest index * @dev Note that if the withdrawal includes shares in the enshrined 'beaconChainETH' strategy, then it must *only* include shares in this strategy, and * `withdrawer` must match the caller's address. The first condition is because slashing of queued withdrawals cannot be guaranteed * for Beacon Chain ETH (since we cannot trigger a withdrawal from the beacon chain through a smart contract) and the second condition is because shares in * the enshrined 'beaconChainETH' strategy technically represent non-fungible positions (deposits to the Beacon Chain, each pointed at a specific EigenPod). */ function queueWithdrawal( uint256[] calldata strategyIndexes, IStrategy[] calldata strategies, uint256[] calldata shares, address withdrawer, bool undelegateIfPossible ) external returns (bytes32); /** * @notice Used to complete the specified `queuedWithdrawal`. The function caller must match `queuedWithdrawal.withdrawer` * @param queuedWithdrawal The QueuedWithdrawal 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 `strategies` array * of the `queuedWithdrawal`. 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 queued withdrawal will be withdrawn from the specified strategies themselves * and sent to the caller, through calls to `queuedWithdrawal.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` */ function completeQueuedWithdrawal( QueuedWithdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256 middlewareTimesIndex, bool receiveAsTokens ) external; /** * @notice Used to complete the specified `queuedWithdrawals`. The function caller must match `queuedWithdrawals[...].withdrawer` * @param queuedWithdrawals The QueuedWithdrawals to complete. * @param tokens Array of tokens for each QueuedWithdrawal. See `completeQueuedWithdrawal` for the usage of a single array. * @param middlewareTimesIndexes One index to reference per QueuedWithdrawal. See `completeQueuedWithdrawal` for the usage of a single index. * @param receiveAsTokens If true, the shares specified in the queued withdrawal will be withdrawn from the specified strategies themselves * and sent to the caller, through calls to `queuedWithdrawal.strategies[i].withdraw`. If false, then the shares in the specified strategies * will simply be transferred to the caller directly. * @dev Array-ified version of `completeQueuedWithdrawal` * @dev middlewareTimesIndex should be calculated off chain before calling this function by finding the first index that satisfies `slasher.canWithdraw` */ function completeQueuedWithdrawals( QueuedWithdrawal[] calldata queuedWithdrawals, IERC20[][] calldata tokens, uint256[] calldata middlewareTimesIndexes, bool[] calldata receiveAsTokens ) external; /** * @notice Slashes the shares of a 'frozen' operator (or a staker delegated to one) * @param slashedAddress is the frozen address that is having its shares slashed * @param recipient is the address that will receive the slashed funds, which could e.g. be a harmed party themself, * or a MerkleDistributor-type contract that further sub-divides the slashed funds. * @param strategies Strategies to slash * @param shareAmounts The amount of shares to slash in each of the provided `strategies` * @param tokens The tokens to use as input to the `withdraw` function of each of the provided `strategies` * @param strategyIndexes is a list of the indices in `stakerStrategyList[msg.sender]` that correspond to the strategies * for which `msg.sender` is withdrawing 100% of their shares * @param recipient The slashed funds are withdrawn as tokens to this address. * @dev strategies are removed from `stakerStrategyList` by swapping the last entry with the entry to be removed, then * popping off the last entry in `stakerStrategyList`. The simplest way to calculate the correct `strategyIndexes` to input * is to order the strategies *for which `msg.sender` is withdrawing 100% of their shares* from highest index in * `stakerStrategyList` to lowest index */ function slashShares( address slashedAddress, address recipient, IStrategy[] calldata strategies, IERC20[] calldata tokens, uint256[] calldata strategyIndexes, uint256[] calldata shareAmounts ) external; /** * @notice Slashes an existing queued withdrawal that was created by a 'frozen' operator (or a staker delegated to one) * @param recipient The funds in the slashed withdrawal are withdrawn as tokens to this address. * @param queuedWithdrawal The previously queued withdrawal to be slashed * @param tokens Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th Strategy in the `strategies` * array of the `queuedWithdrawal`. * @param indicesToSkip Optional input parameter -- indices in the `strategies` array to skip (i.e. not call the 'withdraw' function on). This input exists * so that, e.g., if the slashed QueuedWithdrawal contains a malicious strategy in the `strategies` array which always reverts on calls to its 'withdraw' function, * then the malicious strategy can be skipped (with the shares in effect "burned"), while the non-malicious strategies are still called as normal. */ function slashQueuedWithdrawal( address recipient, QueuedWithdrawal calldata queuedWithdrawal, IERC20[] calldata tokens, uint256[] calldata indicesToSkip ) external; /// @notice Returns the keccak256 hash of `queuedWithdrawal`. function calculateWithdrawalRoot(QueuedWithdrawal memory queuedWithdrawal) external pure returns (bytes32); /** * @notice Owner-only function that adds the provided Strategies to the 'whitelist' of strategies that stakers can deposit into * @param strategiesToWhitelist Strategies that will be added to the `strategyIsWhitelistedForDeposit` mapping (if they aren't in it already) */ function addStrategiesToDepositWhitelist(IStrategy[] calldata strategiesToWhitelist) external; /** * @notice Owner-only function that removes the provided Strategies from the 'whitelist' of strategies that stakers can deposit into * @param strategiesToRemoveFromWhitelist Strategies that will be removed to the `strategyIsWhitelistedForDeposit` mapping (if they are in it) */ function removeStrategiesFromDepositWhitelist(IStrategy[] calldata strategiesToRemoveFromWhitelist) external; /// @notice Returns the single, central Delegation contract of EigenLayer function delegation() external view returns (IDelegationManager); /// @notice Returns the single, central Slasher contract of EigenLayer function slasher() external view returns (ISlasher); /// @notice returns the enshrined, virtual 'beaconChainETH' Strategy function beaconChainETHStrategy() external view returns (IStrategy); /// @notice Returns the number of blocks that must pass between the time a withdrawal is queued and the time it can be completed function withdrawalDelayBlocks() external view returns (uint256); } // Adapted from OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol) /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library Merkle { /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. The tree is built assuming `leaf` is * the 0 indexed `index`'th leaf from the bottom left of the tree. * * Note this is for a Merkle tree using the keccak/sha3 hash function */ function verifyInclusionKeccak( bytes memory proof, bytes32 root, bytes32 leaf, uint256 index ) internal pure returns (bool) { return processInclusionProofKeccak(proof, leaf, index) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. The tree is built assuming `leaf` is * the 0 indexed `index`'th leaf from the bottom left of the tree. * * _Available since v4.4._ * * Note this is for a Merkle tree using the keccak/sha3 hash function */ function processInclusionProofKeccak( bytes memory proof, bytes32 leaf, uint256 index ) internal pure returns (bytes32) { require( proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32" ); bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { // if ith bit of index is 0, then computedHash is a left sibling assembly { mstore(0x00, computedHash) mstore(0x20, mload(add(proof, i))) computedHash := keccak256(0x00, 0x40) index := div(index, 2) } } else { // if ith bit of index is 1, then computedHash is a right sibling assembly { mstore(0x00, mload(add(proof, i))) mstore(0x20, computedHash) computedHash := keccak256(0x00, 0x40) index := div(index, 2) } } } return computedHash; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. The tree is built assuming `leaf` is * the 0 indexed `index`'th leaf from the bottom left of the tree. * * Note this is for a Merkle tree using the sha256 hash function */ function verifyInclusionSha256( bytes memory proof, bytes32 root, bytes32 leaf, uint256 index ) internal view returns (bool) { return processInclusionProofSha256(proof, leaf, index) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. The tree is built assuming `leaf` is * the 0 indexed `index`'th leaf from the bottom left of the tree. * * _Available since v4.4._ * * Note this is for a Merkle tree using the sha256 hash function */ function processInclusionProofSha256( bytes memory proof, bytes32 leaf, uint256 index ) internal view returns (bytes32) { require( proof.length != 0 && proof.length % 32 == 0, "Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32" ); bytes32[1] memory computedHash = [leaf]; for (uint256 i = 32; i <= proof.length; i += 32) { if (index % 2 == 0) { // if ith bit of index is 0, then computedHash is a left sibling assembly { mstore(0x00, mload(computedHash)) mstore(0x20, mload(add(proof, i))) if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } else { // if ith bit of index is 1, then computedHash is a right sibling assembly { mstore(0x00, mload(add(proof, i))) mstore(0x20, mload(computedHash)) if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) } index := div(index, 2) } } } return computedHash[0]; } /** @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash function @param leaves the leaves of the merkle tree @return The computed Merkle root of the tree. @dev A pre-condition to this function is that leaves.length is a power of two. If not, the function will merkleize the inputs incorrectly. */ function merkleizeSha256(bytes32[] memory leaves) internal pure returns (bytes32) { //there are half as many nodes in the layer above the leaves uint256 numNodesInLayer = leaves.length / 2; //create a layer to store the internal nodes bytes32[] memory layer = new bytes32[](numNodesInLayer); //fill the layer with the pairwise hashes of the leaves for (uint i = 0; i < numNodesInLayer; i++) { layer[i] = sha256(abi.encodePacked(leaves[2 * i], leaves[2 * i + 1])); } //the next layer above has half as many nodes numNodesInLayer /= 2; //while we haven't computed the root while (numNodesInLayer != 0) { //overwrite the first numNodesInLayer nodes in layer with the pairwise hashes of their children for (uint i = 0; i < numNodesInLayer; i++) { layer[i] = sha256(abi.encodePacked(layer[2 * i], layer[2 * i + 1])); } //the next layer above has half as many nodes numNodesInLayer /= 2; } //the first node in the layer is the root return layer[0]; } } library Endian { /** * @notice Converts a little endian-formatted uint64 to a big endian-formatted uint64 * @param lenum little endian-formatted uint64 input, provided as 'bytes32' type * @return n The big endian-formatted uint64 * @dev Note that the input is formatted as a 'bytes32' type (i.e. 256 bits), but it is immediately truncated to a uint64 (i.e. 64 bits) * through a right-shift/shr operation. */ function fromLittleEndianUint64(bytes32 lenum) internal pure returns (uint64 n) { // the number needs to be stored in little-endian encoding (ie in bytes 0-8) n = uint64(uint256(lenum >> 192)); return (n >> 56) | ((0x00FF000000000000 & n) >> 40) | ((0x0000FF0000000000 & n) >> 24) | ((0x000000FF00000000 & n) >> 8) | ((0x00000000FF000000 & n) << 8) | ((0x0000000000FF0000 & n) << 24) | ((0x000000000000FF00 & n) << 40) | ((0x00000000000000FF & n) << 56); } } //Utility library for parsing and PHASE0 beacon chain block headers //SSZ Spec: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization //BeaconBlockHeader Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader //BeaconState Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconstate library BeaconChainProofs { // constants are the number of fields and the heights of the different merkle trees used in merkleizing beacon chain containers uint256 internal constant NUM_BEACON_BLOCK_HEADER_FIELDS = 5; uint256 internal constant BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT = 3; uint256 internal constant NUM_BEACON_BLOCK_BODY_FIELDS = 11; uint256 internal constant BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT = 4; uint256 internal constant NUM_BEACON_STATE_FIELDS = 21; uint256 internal constant BEACON_STATE_FIELD_TREE_HEIGHT = 5; uint256 internal constant NUM_ETH1_DATA_FIELDS = 3; uint256 internal constant ETH1_DATA_FIELD_TREE_HEIGHT = 2; uint256 internal constant NUM_VALIDATOR_FIELDS = 8; uint256 internal constant VALIDATOR_FIELD_TREE_HEIGHT = 3; uint256 internal constant NUM_EXECUTION_PAYLOAD_HEADER_FIELDS = 15; uint256 internal constant EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT = 4; uint256 internal constant NUM_EXECUTION_PAYLOAD_FIELDS = 15; uint256 internal constant EXECUTION_PAYLOAD_FIELD_TREE_HEIGHT = 4; // HISTORICAL_ROOTS_LIMIT = 2**24, so tree height is 24 uint256 internal constant HISTORICAL_ROOTS_TREE_HEIGHT = 24; // HISTORICAL_BATCH is root of state_roots and block_root, so number of leaves = 2^1 uint256 internal constant HISTORICAL_BATCH_TREE_HEIGHT = 1; // SLOTS_PER_HISTORICAL_ROOT = 2**13, so tree height is 13 uint256 internal constant STATE_ROOTS_TREE_HEIGHT = 13; uint256 internal constant BLOCK_ROOTS_TREE_HEIGHT = 13; uint256 internal constant NUM_WITHDRAWAL_FIELDS = 4; // tree height for hash tree of an individual withdrawal container uint256 internal constant WITHDRAWAL_FIELD_TREE_HEIGHT = 2; uint256 internal constant VALIDATOR_TREE_HEIGHT = 40; //refer to the eigenlayer-cli proof library. Despite being the same dimensions as the validator tree, the balance tree is merkleized differently uint256 internal constant BALANCE_TREE_HEIGHT = 38; // MAX_WITHDRAWALS_PER_PAYLOAD = 2**4, making tree height = 4 uint256 internal constant WITHDRAWALS_TREE_HEIGHT = 4; //in beacon block body uint256 internal constant EXECUTION_PAYLOAD_INDEX = 9; // in beacon block header uint256 internal constant STATE_ROOT_INDEX = 3; uint256 internal constant PROPOSER_INDEX_INDEX = 1; uint256 internal constant SLOT_INDEX = 0; uint256 internal constant BODY_ROOT_INDEX = 4; // in beacon state uint256 internal constant STATE_ROOTS_INDEX = 6; uint256 internal constant BLOCK_ROOTS_INDEX = 5; uint256 internal constant HISTORICAL_ROOTS_INDEX = 7; uint256 internal constant ETH_1_ROOT_INDEX = 8; uint256 internal constant VALIDATOR_TREE_ROOT_INDEX = 11; uint256 internal constant BALANCE_INDEX = 12; uint256 internal constant EXECUTION_PAYLOAD_HEADER_INDEX = 24; uint256 internal constant HISTORICAL_BATCH_STATE_ROOT_INDEX = 1; // in validator uint256 internal constant VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX = 1; uint256 internal constant VALIDATOR_BALANCE_INDEX = 2; uint256 internal constant VALIDATOR_SLASHED_INDEX = 3; uint256 internal constant VALIDATOR_WITHDRAWABLE_EPOCH_INDEX = 7; // in execution payload header uint256 internal constant BLOCK_NUMBER_INDEX = 6; uint256 internal constant WITHDRAWALS_ROOT_INDEX = 14; //in execution payload uint256 internal constant WITHDRAWALS_INDEX = 14; // in withdrawal uint256 internal constant WITHDRAWAL_VALIDATOR_INDEX_INDEX = 1; uint256 internal constant WITHDRAWAL_VALIDATOR_AMOUNT_INDEX = 3; //In historicalBatch uint256 internal constant HISTORICALBATCH_STATEROOTS_INDEX = 1; //Misc Constants uint256 internal constant SLOTS_PER_EPOCH = 32; bytes8 internal constant UINT64_MASK = 0xffffffffffffffff; struct WithdrawalProofs { bytes blockHeaderProof; bytes withdrawalProof; bytes slotProof; bytes executionPayloadProof; bytes blockNumberProof; uint64 blockHeaderRootIndex; uint64 withdrawalIndex; bytes32 blockHeaderRoot; bytes32 blockBodyRoot; bytes32 slotRoot; bytes32 blockNumberRoot; bytes32 executionPayloadRoot; } struct ValidatorFieldsAndBalanceProofs { bytes validatorFieldsProof; bytes validatorBalanceProof; bytes32 balanceRoot; } struct ValidatorFieldsProof { bytes validatorProof; uint40 validatorIndex; } /** * * @notice This function is parses the balanceRoot to get the uint64 balance of a validator. During merkleization of the * beacon state balance tree, four uint64 values (making 32 bytes) are grouped together and treated as a single leaf in the merkle tree. Thus the * validatorIndex mod 4 is used to determine which of the four uint64 values to extract from the balanceRoot. * @param validatorIndex is the index of the validator being proven for. * @param balanceRoot is the combination of 4 validator balances being proven for. * @return The validator's balance, in Gwei */ function getBalanceFromBalanceRoot(uint40 validatorIndex, bytes32 balanceRoot) internal pure returns (uint64) { uint256 bitShiftAmount = (validatorIndex % 4) * 64; bytes32 validatorBalanceLittleEndian = bytes32((uint256(balanceRoot) << bitShiftAmount)); uint64 validatorBalance = Endian.fromLittleEndianUint64(validatorBalanceLittleEndian); return validatorBalance; } /** * @notice This function verifies merkle proofs of the fields of a certain validator against a beacon chain state root * @param validatorIndex the index of the proven validator * @param beaconStateRoot is the beacon chain state root to be proven against. * @param proof is the data used in proving the validator's fields * @param validatorFields the claimed fields of the validator */ function verifyValidatorFields( uint40 validatorIndex, bytes32 beaconStateRoot, bytes calldata proof, bytes32[] calldata validatorFields ) internal view { require( validatorFields.length == 2 ** VALIDATOR_FIELD_TREE_HEIGHT, "BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length" ); /** * Note: the length of the validator merkle proof is BeaconChainProofs.VALIDATOR_TREE_HEIGHT + 1. * There is an additional layer added by hashing the root with the length of the validator list */ require( proof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyValidatorFields: Proof has incorrect length" ); uint256 index = (VALIDATOR_TREE_ROOT_INDEX << (VALIDATOR_TREE_HEIGHT + 1)) | uint256(validatorIndex); // merkleize the validatorFields to get the leaf to prove bytes32 validatorRoot = Merkle.merkleizeSha256(validatorFields); // verify the proof of the validatorRoot against the beaconStateRoot require( Merkle.verifyInclusionSha256(proof, beaconStateRoot, validatorRoot, index), "BeaconChainProofs.verifyValidatorFields: Invalid merkle proof" ); } /** * @notice This function verifies merkle proofs of the balance of a certain validator against a beacon chain state root * @param validatorIndex the index of the proven validator * @param beaconStateRoot is the beacon chain state root to be proven against. * @param proof is the proof of the balance against the beacon chain state root * @param balanceRoot is the serialized balance used to prove the balance of the validator (refer to `getBalanceFromBalanceRoot` above for detailed explanation) */ function verifyValidatorBalance( uint40 validatorIndex, bytes32 beaconStateRoot, bytes calldata proof, bytes32 balanceRoot ) internal view { require( proof.length == 32 * ((BALANCE_TREE_HEIGHT + 1) + BEACON_STATE_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyValidatorBalance: Proof has incorrect length" ); /** * the beacon state's balance list is a list of uint64 values, and these are grouped together in 4s when merkleized. * Therefore, the index of the balance of a validator is validatorIndex/4 */ uint256 balanceIndex = uint256(validatorIndex / 4); balanceIndex = (BALANCE_INDEX << (BALANCE_TREE_HEIGHT + 1)) | balanceIndex; require( Merkle.verifyInclusionSha256(proof, beaconStateRoot, balanceRoot, balanceIndex), "BeaconChainProofs.verifyValidatorBalance: Invalid merkle proof" ); } /** * @notice This function verifies the slot and the withdrawal fields for a given withdrawal * @param beaconStateRoot is the beacon chain state root to be proven against. * @param proofs is the provided set of merkle proofs * @param withdrawalFields is the serialized withdrawal container to be proven */ function verifyWithdrawalProofs( bytes32 beaconStateRoot, WithdrawalProofs calldata proofs, bytes32[] calldata withdrawalFields ) internal view { require( withdrawalFields.length == 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawalProofs: withdrawalFields has incorrect length" ); require( proofs.blockHeaderRootIndex < 2 ** BLOCK_ROOTS_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawalProofs: blockRootIndex is too large" ); require( proofs.withdrawalIndex < 2 ** WITHDRAWALS_TREE_HEIGHT, "BeaconChainProofs.verifyWithdrawalProofs: withdrawalIndex is too large" ); // verify the block header proof length require( proofs.blockHeaderProof.length == 32 * (BEACON_STATE_FIELD_TREE_HEIGHT + BLOCK_ROOTS_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawalProofs: blockHeaderProof has incorrect length" ); require( proofs.withdrawalProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT + WITHDRAWALS_TREE_HEIGHT + 1), "BeaconChainProofs.verifyWithdrawalProofs: withdrawalProof has incorrect length" ); require( proofs.executionPayloadProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT + BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawalProofs: executionPayloadProof has incorrect length" ); require( proofs.slotProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawalProofs: slotProof has incorrect length" ); require( proofs.blockNumberProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyWithdrawalProofs: blockNumberProof has incorrect length" ); /** * Computes the block_header_index relative to the beaconStateRoot. It concatenates the indexes of all the * intermediate root indexes from the bottom of the sub trees (the block header container) to the top of the tree */ uint256 blockHeaderIndex = (BLOCK_ROOTS_INDEX << (BLOCK_ROOTS_TREE_HEIGHT)) | uint256(proofs.blockHeaderRootIndex); // Verify the blockHeaderRoot against the beaconStateRoot require( Merkle.verifyInclusionSha256( proofs.blockHeaderProof, beaconStateRoot, proofs.blockHeaderRoot, blockHeaderIndex ), "BeaconChainProofs.verifyWithdrawalProofs: Invalid block header merkle proof" ); //Next we verify the slot against the blockHeaderRoot require( Merkle.verifyInclusionSha256(proofs.slotProof, proofs.blockHeaderRoot, proofs.slotRoot, SLOT_INDEX), "BeaconChainProofs.verifyWithdrawalProofs: Invalid slot merkle proof" ); // Next we verify the executionPayloadRoot against the blockHeaderRoot uint256 executionPayloadIndex = (BODY_ROOT_INDEX << (BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT)) | EXECUTION_PAYLOAD_INDEX; require( Merkle.verifyInclusionSha256( proofs.executionPayloadProof, proofs.blockHeaderRoot, proofs.executionPayloadRoot, executionPayloadIndex ), "BeaconChainProofs.verifyWithdrawalProofs: Invalid executionPayload merkle proof" ); // Next we verify the blockNumberRoot against the executionPayload root require( Merkle.verifyInclusionSha256( proofs.blockNumberProof, proofs.executionPayloadRoot, proofs.blockNumberRoot, BLOCK_NUMBER_INDEX ), "BeaconChainProofs.verifyWithdrawalProofs: Invalid blockNumber merkle proof" ); /** * Next we verify the withdrawal fields against the blockHeaderRoot: * First we compute the withdrawal_index relative to the blockHeaderRoot by concatenating the indexes of all the * intermediate root indexes from the bottom of the sub trees (the withdrawal container) to the top, the blockHeaderRoot. * Then we calculate merkleize the withdrawalFields container to calculate the the withdrawalRoot. * Finally we verify the withdrawalRoot against the executionPayloadRoot. */ uint256 withdrawalIndex = (WITHDRAWALS_INDEX << (WITHDRAWALS_TREE_HEIGHT + 1)) | uint256(proofs.withdrawalIndex); bytes32 withdrawalRoot = Merkle.merkleizeSha256(withdrawalFields); require( Merkle.verifyInclusionSha256( proofs.withdrawalProof, proofs.executionPayloadRoot, withdrawalRoot, withdrawalIndex ), "BeaconChainProofs.verifyWithdrawalProofs: Invalid withdrawal merkle proof" ); } } /** * @title Interface for the BeaconStateOracle contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface IBeaconChainOracle { /// @notice Largest blockNumber that has been confirmed by the oracle. function latestConfirmedOracleBlockNumber() external view returns (uint64); /// @notice Mapping: Beacon Chain blockNumber => the Beacon Chain state root at the specified blockNumber. /// @dev This will return `bytes32(0)` if the state root at the specified blockNumber is not yet confirmed. function beaconStateRootAtBlockNumber(uint64 blockNumber) external view returns (bytes32); /// @notice Mapping: address => whether or not the address is in the set of oracle signers. function isOracleSigner(address _oracleSigner) external view returns (bool); /// @notice Mapping: Beacon Chain blockNumber => oracle signer address => whether or not the oracle signer has voted on the state root at the blockNumber. function hasVoted(uint64 blockNumber, address oracleSigner) external view returns (bool); /// @notice Mapping: Beacon Chain blockNumber => state root => total number of oracle signer votes for the state root at the blockNumber. function stateRootVotes(uint64 blockNumber, bytes32 stateRoot) external view returns (uint256); /// @notice Total number of members of the set of oracle signers. function totalOracleSigners() external view returns (uint256); /** * @notice Number of oracle signers that must vote for a state root in order for the state root to be confirmed. * Adjustable by this contract's owner through use of the `setThreshold` function. * @dev We note that there is an edge case -- when the threshold is adjusted downward, if a state root already has enough votes to meet the *new* threshold, * the state root must still receive one additional vote from an oracle signer to be confirmed. This behavior is intended, to minimize unexpected root confirmations. */ function threshold() external view returns (uint256); /** * @notice Owner-only function used to modify the value of the `threshold` variable. * @param _threshold Desired new value for the `threshold` variable. Function will revert if this is set to zero. */ function setThreshold(uint256 _threshold) external; /** * @notice Owner-only function used to add a signer to the set of oracle signers. * @param _oracleSigners Array of address to be added to the set. * @dev Function will have no effect on the i-th input address if `_oracleSigners[i]`is already in the set of oracle signers. */ function addOracleSigners(address[] memory _oracleSigners) external; /** * @notice Owner-only function used to remove a signer from the set of oracle signers. * @param _oracleSigners Array of address to be removed from the set. * @dev Function will have no effect on the i-th input address if `_oracleSigners[i]`is already not in the set of oracle signers. */ function removeOracleSigners(address[] memory _oracleSigners) external; /** * @notice Called by a member of the set of oracle signers to assert that the Beacon Chain state root is `stateRoot` at `blockNumber`. * @dev The state root will be finalized once the total number of votes *for this exact state root at this exact blockNumber* meets the `threshold` value. * @param blockNumber The Beacon Chain blockNumber of interest. * @param stateRoot The Beacon Chain state root that the caller asserts was the correct root, at the specified `blockNumber`. */ function voteForBeaconChainStateRoot(uint64 blockNumber, bytes32 stateRoot) external; } /** * @title The implementation contract used for restaking beacon chain ETH on EigenLayer * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice The main functionalities are: * - creating new ETH validators with their withdrawal credentials pointed to this contract * - proving from beacon chain state roots that withdrawal credentials are pointed to this contract * - proving from beacon chain state roots the balances of ETH validators with their withdrawal credentials * pointed to this contract * - updating aggregate balances in the EigenPodManager * - withdrawing eth when withdrawals are initiated * @dev Note that all beacon chain balances are stored as gwei within the beacon chain datastructures. We choose * to account balances in terms of gwei in the EigenPod contract and convert to wei when making calls to other contracts */ interface IEigenPod { enum VALIDATOR_STATUS { INACTIVE, // doesnt exist ACTIVE, // staked on ethpos and withdrawal credentials are pointed to the EigenPod OVERCOMMITTED, // proven to be overcommitted to EigenLayer WITHDRAWN // withdrawn from the Beacon Chain } // this struct keeps track of PartialWithdrawalClaims struct PartialWithdrawalClaim { PARTIAL_WITHDRAWAL_CLAIM_STATUS status; // block at which the PartialWithdrawalClaim was created uint32 creationBlockNumber; // last block (inclusive) in which the PartialWithdrawalClaim can be fraudproofed uint32 fraudproofPeriodEndBlockNumber; // amount of ETH -- in Gwei -- to be withdrawn until completion of this claim uint64 partialWithdrawalAmountGwei; } enum PARTIAL_WITHDRAWAL_CLAIM_STATUS { REDEEMED, PENDING, FAILED } /// @notice The amount of eth, in gwei, that is restaked per validator function REQUIRED_BALANCE_GWEI() external view returns (uint64); /// @notice The amount of eth, in wei, that is restaked per validator function REQUIRED_BALANCE_WEI() external view returns (uint256); /// @notice this is a mapping of validator indices to a Validator struct containing pertinent info about the validator function validatorStatus(uint40 validatorIndex) external view returns (VALIDATOR_STATUS); /// @notice the amount of execution layer ETH in this contract that is staked in EigenLayer (i.e. withdrawn from beaconchain but not EigenLayer), function restakedExecutionLayerGwei() external view returns (uint64); /// @notice Used to initialize the pointers to contracts crucial to the pod's functionality, in beacon proxy construction from EigenPodManager function initialize(address owner) external; /// @notice Called by EigenPodManager when the owner wants to create another ETH validator. function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external payable; /** * @notice Transfers `amountWei` in ether from this contract to the specified `recipient` address * @notice Called by EigenPodManager to withdrawBeaconChainETH that has been added to the EigenPod's balance due to a withdrawal from the beacon chain. * @dev Called during withdrawal or slashing. * @dev Note that this function is marked as non-reentrant to prevent the recipient calling back into it */ function withdrawRestakedBeaconChainETH(address recipient, uint256 amount) external; /// @notice The single EigenPodManager for EigenLayer function eigenPodManager() external view returns (IEigenPodManager); /// @notice The owner of this EigenPod function podOwner() external view returns (address); /// @notice an indicator of whether or not the podOwner has ever "fully restaked" by successfully calling `verifyCorrectWithdrawalCredentials`. function hasRestaked() external view returns (bool); /// @notice block number of the most recent withdrawal function mostRecentWithdrawalBlockNumber() external view returns (uint64); ///@notice mapping that tracks proven partial withdrawals function provenPartialWithdrawal(uint40 validatorIndex, uint64 slot) external view returns (bool); /** * @notice This function verifies that the withdrawal credentials of the podOwner are pointed to * this contract. It also verifies the current (not effective) balance of the validator. It verifies the provided proof of the ETH validator against the beacon chain state * root, marks the validator as 'active' in EigenLayer, and credits the restaked ETH in Eigenlayer. * @param oracleBlockNumber is the Beacon Chain blockNumber whose state root the `proof` will be proven against. * @param validatorIndex is the index of the validator being proven, refer to consensus specs * @param proofs is the bytes that prove the ETH validator's balance and withdrawal credentials against a beacon chain state root * @param validatorFields are the fields of the "Validator Container", refer to consensus specs * for details: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator */ function verifyWithdrawalCredentialsAndBalance( uint64 oracleBlockNumber, uint40 validatorIndex, BeaconChainProofs.ValidatorFieldsAndBalanceProofs memory proofs, bytes32[] calldata validatorFields ) external; /** * @notice This function records an overcommitment of stake to EigenLayer on behalf of a certain ETH validator. * If successful, the overcommitted balance is penalized (available for withdrawal whenever the pod's balance allows). * The ETH validator's shares in the enshrined beaconChainETH strategy are also removed from the StrategyManager and undelegated. * @param oracleBlockNumber The oracleBlockNumber whose state root the `proof` will be proven against. * Must be within `VERIFY_OVERCOMMITTED_WINDOW_BLOCKS` of the current block. * @param validatorIndex is the index of the validator being proven, refer to consensus specs * @param proofs is the proof of the validator's balance and validatorFields in the balance tree and the balanceRoot to prove for * @param beaconChainETHStrategyIndex is the index of the beaconChainETHStrategy for the pod owner for the callback to * the StrategyManager in case it must be removed from the list of the podOwners strategies * @param validatorFields are the fields of the "Validator Container", refer to consensus specs * @dev For more details on the Beacon Chain spec, see: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator */ function verifyOvercommittedStake( uint40 validatorIndex, BeaconChainProofs.ValidatorFieldsAndBalanceProofs calldata proofs, bytes32[] calldata validatorFields, uint256 beaconChainETHStrategyIndex, uint64 oracleBlockNumber ) external; /** * @notice This function records a full withdrawal on behalf of one of the Ethereum validators for this EigenPod * @param withdrawalProofs is the information needed to check the veracity of the block number and withdrawal being proven * @param validatorFieldsProof is the proof of the validator's fields in the validator tree * @param withdrawalFields are the fields of the withdrawal being proven * @param validatorFields are the fields of the validator being proven * @param beaconChainETHStrategyIndex is the index of the beaconChainETHStrategy for the pod owner for the callback to * the EigenPodManager to the StrategyManager in case it must be removed from the podOwner's list of strategies */ function verifyAndProcessWithdrawal( BeaconChainProofs.WithdrawalProofs calldata withdrawalProofs, bytes calldata validatorFieldsProof, bytes32[] calldata validatorFields, bytes32[] calldata withdrawalFields, uint256 beaconChainETHStrategyIndex, uint64 oracleBlockNumber ) external; /// @notice Called by the pod owner to withdraw the balance of the pod when `hasRestaked` is set to false function withdrawBeforeRestaking() external; } /** * @title Interface for the `PauserRegistry` contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface IPauserRegistry { /// @notice Mapping of addresses to whether they hold the pauser role. function isPauser(address pauser) external view returns (bool); /// @notice Unique address that holds the unpauser role. Capable of changing *both* the pauser and unpauser addresses. function unpauser() external view returns (address); } /** * @title Adds pausability to a contract, with pausing & unpausing controlled by the `pauser` and `unpauser` of a PauserRegistry contract. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice Contracts that inherit from this contract may define their own `pause` and `unpause` (and/or related) functions. * These functions should be permissioned as "onlyPauser" which defers to a `PauserRegistry` for determining access control. * @dev Pausability is implemented using a uint256, which allows up to 256 different single bit-flags; each bit can potentially pause different functionality. * Inspiration for this was taken from the NearBridge design here https://etherscan.io/address/0x3FEFc5A4B1c02f21cBc8D3613643ba0635b9a873#code. * For the `pause` and `unpause` functions we've implemented, if you pause, you can only flip (any number of) switches to on/1 (aka "paused"), and if you unpause, * you can only flip (any number of) switches to off/0 (aka "paused"). * If you want a pauseXYZ function that just flips a single bit / "pausing flag", it will: * 1) 'bit-wise and' (aka `&`) a flag with the current paused state (as a uint256) * 2) update the paused state to this new value * @dev We note as well that we have chosen to identify flags by their *bit index* as opposed to their numerical value, so, e.g. defining `DEPOSITS_PAUSED = 3` * indicates specifically that if the *third bit* of `_paused` is flipped -- i.e. it is a '1' -- then deposits should be paused */ interface IPausable { /// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing). function pauserRegistry() external view returns (IPauserRegistry); /** * @notice This function is used to pause an EigenLayer contract's functionality. * It is permissioned to the `pauser` address, which is expected to be a low threshold multisig. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0. */ function pause(uint256 newPausedStatus) external; /** * @notice Alias for `pause(type(uint256).max)`. */ function pauseAll() external; /** * @notice This function is used to unpause an EigenLayer contract's functionality. * It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract. * @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once. * @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1. */ function unpause(uint256 newPausedStatus) external; /// @notice Returns the current paused status as a uint256. function paused() external view returns (uint256); /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise function paused(uint8 index) external view returns (bool); /// @notice Allows the unpauser to set a new pauser registry function setPauserRegistry(IPauserRegistry newPauserRegistry) external; } /** * @title Interface for factory that creates and manages solo staking pods that have their withdrawal credentials pointed to EigenLayer. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface IEigenPodManager is IPausable { /** * @notice Creates an EigenPod for the sender. * @dev Function will revert if the `msg.sender` already has an EigenPod. */ function createPod() external; /** * @notice Stakes for a new beacon chain validator on the sender's EigenPod. * Also creates an EigenPod for the sender if they don't have one already. * @param pubkey The 48 bytes public key of the beacon chain validator. * @param signature The validator's signature of the deposit data. * @param depositDataRoot The root/hash of the deposit data for the validator's deposit. */ function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external payable; /** * @notice Deposits/Restakes beacon chain ETH in EigenLayer on behalf of the owner of an EigenPod. * @param podOwner The owner of the pod whose balance must be deposited. * @param amount The amount of ETH to 'deposit' (i.e. be credited to the podOwner). * @dev Callable only by the podOwner's EigenPod contract. */ function restakeBeaconChainETH(address podOwner, uint256 amount) external; /** * @notice Removes beacon chain ETH from EigenLayer on behalf of the owner of an EigenPod, when the * balance of a validator is lower than how much stake they have committed to EigenLayer * @param podOwner The owner of the pod whose balance must be removed. * @param beaconChainETHStrategyIndex is the index of the beaconChainETHStrategy for the pod owner for the callback to * the StrategyManager in case it must be removed from the list of the podOwner's strategies * @param amount The amount of ETH to remove. * @dev Callable only by the podOwner's EigenPod contract. */ function recordOvercommittedBeaconChainETH( address podOwner, uint256 beaconChainETHStrategyIndex, uint256 amount ) external; /** * @notice Withdraws ETH from an EigenPod. The ETH must have first been withdrawn from the beacon chain. * @param podOwner The owner of the pod whose balance must be withdrawn. * @param recipient The recipient of the withdrawn ETH. * @param amount The amount of ETH to withdraw. * @dev Callable only by the StrategyManager contract. */ function withdrawRestakedBeaconChainETH(address podOwner, address recipient, uint256 amount) external; /** * @notice Updates the oracle contract that provides the beacon chain state root * @param newBeaconChainOracle is the new oracle contract being pointed to * @dev Callable only by the owner of this contract (i.e. governance) */ function updateBeaconChainOracle(IBeaconChainOracle newBeaconChainOracle) external; /// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed. function ownerToPod(address podOwner) external view returns (IEigenPod); /// @notice Returns the address of the `podOwner`'s EigenPod (whether it is deployed yet or not). function getPod(address podOwner) external view returns (IEigenPod); /// @notice Oracle contract that provides updates to the beacon chain's state function beaconChainOracle() external view returns (IBeaconChainOracle); /// @notice Returns the Beacon Chain state root at `blockNumber`. Reverts if the Beacon Chain state root at `blockNumber` has not yet been finalized. function getBeaconChainStateRoot(uint64 blockNumber) external view returns (bytes32); /// @notice EigenLayer's StrategyManager contract function strategyManager() external view returns (IStrategyManager); /// @notice EigenLayer's Slasher contract function slasher() external view returns (ISlasher); function hasPod(address podOwner) external view returns (bool); } interface IDelayedWithdrawalRouter { // struct used to pack data into a single storage slot struct DelayedWithdrawal { uint224 amount; uint32 blockCreated; } // struct used to store a single users delayedWithdrawal data struct UserDelayedWithdrawals { uint256 delayedWithdrawalsCompleted; DelayedWithdrawal[] delayedWithdrawals; } /** * @notice Creates an delayed withdrawal for `msg.value` to the `recipient`. * @dev Only callable by the `podOwner`'s EigenPod contract. */ function createDelayedWithdrawal(address podOwner, address recipient) external payable; /** * @notice Called in order to withdraw delayed withdrawals made to the `recipient` that have passed the `withdrawalDelayBlocks` period. * @param recipient The address to claim delayedWithdrawals for. * @param maxNumberOfWithdrawalsToClaim Used to limit the maximum number of withdrawals to loop through claiming. */ function claimDelayedWithdrawals(address recipient, uint256 maxNumberOfWithdrawalsToClaim) external; /** * @notice Called in order to withdraw delayed withdrawals made to the caller that have passed the `withdrawalDelayBlocks` period. * @param maxNumberOfWithdrawalsToClaim Used to limit the maximum number of withdrawals to loop through claiming. */ function claimDelayedWithdrawals(uint256 maxNumberOfWithdrawalsToClaim) external; /// @notice Owner-only function for modifying the value of the `withdrawalDelayBlocks` variable. function setWithdrawalDelayBlocks(uint256 newValue) external; /// @notice Getter function for the mapping `_userWithdrawals` function userWithdrawals(address user) external view returns (UserDelayedWithdrawals memory); /// @notice Getter function to get all delayedWithdrawals of the `user` function getUserDelayedWithdrawals(address user) external view returns (DelayedWithdrawal[] memory); /// @notice Getter function to get all delayedWithdrawals that are currently claimable by the `user` function getClaimableUserDelayedWithdrawals(address user) external view returns (DelayedWithdrawal[] memory); /// @notice Getter function for fetching the delayedWithdrawal at the `index`th entry from the `_userWithdrawals[user].delayedWithdrawals` array function userDelayedWithdrawalByIndex(address user, uint256 index) external view returns (DelayedWithdrawal memory); /// @notice Getter function for fetching the length of the delayedWithdrawals array of a specific user function userWithdrawalsLength(address user) external view returns (uint256); /// @notice Convenience function for checking whether or not the delayedWithdrawal at the `index`th entry from the `_userWithdrawals[user].delayedWithdrawals` array is currently claimable function canClaimDelayedWithdrawal(address user, uint256 index) external view returns (bool); /** * @notice Delay enforced by this contract for completing any delayedWithdrawal. 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 withdrawalDelayBlocks() external view returns (uint256); } /// @title NodeManager contract. /// @notice This contract is responsible for managing the validator nodes and their deposits. /// @dev This contract is upgradeable. /// @dev This contract is pausable. /// @dev This contract is re-entrant guarded. /** @dev Node Types by unique number 0: Direct Staking 1: SSV Node 10: EigenLayer **/ contract NodeManager is INodeManager, UUPSUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable { using ECDSAUpgradeable for bytes32; /// @notice ClayStack's default list of access-control roles. bytes32 private constant TIMELOCK_ROLE = keccak256("TIMELOCK_ROLE"); bytes32 private constant TIMELOCK_UPGRADES_ROLE = keccak256("TIMELOCK_UPGRADES_ROLE"); bytes32 private constant CS_SERVICE_ROLE = keccak256("CS_SERVICE_ROLE"); /// @notice Constants uint256 private constant DEPOSIT_SIZE = 32 ether; uint256 private constant PRE_DEPOSIT_SIZE = 1 ether; uint256 private constant PERCENTAGE_BASE = 10000; uint256 private constant MAX_NODE_OPERATOR_FEES = 2000; uint256 private constant NODE_TYPE_EIGENLAYER = 10; /// @notice RoleManager instance. IRoleManager private roleManager; /// @notice address of clayMain contract. IClayMain public clayMain; /// @notice Instance of deposit contract. IDepositContract private depositContract; /// @notice Mapping of node ids to validator data. mapping(uint256 => Validator) public validators; /// @notice Nonce of validators ids registered uint256 public validatorNonce; /// @notice Number of exit requests uint256 public exitRequestsCount; /// @notice Number of exited validators uint256 public exitedValidators; /// @notice Number of validators active in the Consensus Layer state uint256 public activeValidators; /// @notice Total balance on active validators in the Consensus Layer state uint256 public activeValidatorsBalance; /// @notice Rewards accrued not yet added to liquidity uint256 public rewardsAccrued; /// @notice Oracle report block number uint256 public oracleReportBlock; /// @notice Keeps track of registered publicKey for validators mapping(bytes => bool) public registeredValidator; /// @notice Batch id to exit count request mapping(uint256 => uint256) public batchExitRequests; /// @notice Circular buffer queue of batches ids to exit in sequential order uint256[] public batchExitQueue; /// @notice Front of the queue uint256 public batchExitQueueFront; /// @notice Mapping of whitelisted oracles mapping(address => bool) public oracleWhitelist; /// @notice Mapping of whitelisted autobalance callers mapping(address => bool) public autobalanceWhitelist; /// @notice Mapping of last block number voted on oracle report mapping(address => uint256) public oracleVotes; /// @notice Minimum number of votes required for oracle update uint256 public oracleQuorum; /// @notice address of node operator address public nodeOperator; /// @notice Node operator fees uint256 public nodeOperatorFees; /// @notice Accrued fees not yet paid to node operator uint256 public nodeOperatorAccruedFees; /// @notice PreDeposit information mapping(bytes => address) public preDepositOwner; /// @notice Total amount of pre-deposits uint256 public preDepositsAmount; /// @notice Instance of EigenPodManager contract. IEigenPodManager private eigenPodManager; /// @notice Instance of DelayedWithdrawalRouter IDelayedWithdrawalRouter private eigenDelayedWithdrawalRouter; /// @notice Amount in delayed withdrawals to be claimed uint256 public eigenLayerWithdraws; /// @notice Maps EigenLayer claim id with total EigenLayer exits mapping(uint256 => uint256) public eigenLayerExits; /// @notice Check if the msg.sender has permission. /// @param _roleName : bytes32 hash of the role. modifier onlyRole(bytes32 _roleName) { _onlyRole(_roleName); _; } /// @notice Initializes the contract's state vars. /// @param _roleManager : Address of ClayStack's role manager contract. /// @param _depositContract : Address of the deposit contract. function initialize(address _roleManager, address _depositContract) external initializer onlyProxy { require(_roleManager != address(0), "Invalid roleManager address"); require(_depositContract != address(0), "Invalid depositContract address"); __Pausable_init(); __ReentrancyGuard_init(); __UUPSUpgradeable_init(); roleManager = IRoleManager(_roleManager); depositContract = IDepositContract(_depositContract); oracleQuorum = 1; } /** STAKING **/ /// @notice preDeposit can be called by NodeOperator contract or directly by node operator. /// @dev Amount will be locked and refunded when oracle registration confirms validity of withdrawal address. /// @dev preDeposit nodes are not supported for EigenLayer type nodes /// @param _publicKey The public key(s) of the validator. /// @param _signature The signature(s) of the validator. /// @param _deposit_data_root The deposit data root(s) of the validator. function preDeposit( bytes[] memory _publicKey, bytes[] memory _signature, bytes32[] memory _deposit_data_root ) external payable whenNotPaused nonReentrant returns (bool) { require( _publicKey.length == _signature.length && _publicKey.length == _deposit_data_root.length && _publicKey.length > 0, "Invalid param lengths" ); require(msg.value == PRE_DEPOSIT_SIZE * _publicKey.length, "preDeposit value must be 1 ether per validator"); for (uint256 i = 0; i < _publicKey.length; i++) { require(!registeredValidator[_publicKey[i]], "publicKey already registered"); require(preDepositOwner[_publicKey[i]] == address(0), "publicKey already pre-deposited"); depositContract.deposit{value: PRE_DEPOSIT_SIZE}( _publicKey[i], abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)), _signature[i], _deposit_data_root[i] ); preDepositOwner[_publicKey[i]] = msg.sender; emit LogPreDeposit(_publicKey[i], msg.sender); } preDepositsAmount += msg.value; return true; } /// @notice Deposits / Withdraws while registering validators with the specified parameters. /// @dev Anyone can call the function as long as no registration occurs ir order to close NetStaking batches. /// @param _publicKey The public key(s) of the validator. /// @param _signature The signature(s) of the validator. /// @param _deposit_data_root The deposit data root(s) of the validator. /// @param _validatorType The type of the validator code internally used. /// @return A boolean indicating whether the registration was successful. function autoBalance( bytes[] memory _publicKey, bytes[] memory _signature, bytes32[] memory _deposit_data_root, uint256[] memory _validatorType ) public whenNotPaused nonReentrant returns (bool) { require( _publicKey.length == _signature.length && _publicKey.length == _deposit_data_root.length && _publicKey.length == _validatorType.length, "Invalid param lengths" ); require(address(clayMain) != address(0), "Claymain not set"); if (_publicKey.length > 0) { require( roleManager.checkRole(CS_SERVICE_ROLE, msg.sender) || autobalanceWhitelist[msg.sender], "Auth Failed" ); } // get action from ClayMain (uint256 currentBatchId, bool netStaking, uint256 validatorCount) = clayMain.autoBalance(_publicKey.length); if (netStaking && validatorCount > 0) { uint256 id = validatorNonce; for (uint256 i = 0; i < validatorCount; i++) { require(!registeredValidator[_publicKey[i]], "publicKey already registered"); ++id; validators[id] = Validator(_publicKey[i], _signature[i], _validatorType[i]); registeredValidator[_publicKey[i]] = true; address preDepositOwnerAddress = preDepositOwner[_publicKey[i]]; uint256 deposit = preDepositOwnerAddress == address(0) ? 0 : PRE_DEPOSIT_SIZE; if (_validatorType[i] == NODE_TYPE_EIGENLAYER) { require(address(eigenPodManager) != address(0), "EigenPodManager not set"); require(deposit == 0, "EigenPod M1 Requires 32 ETH"); eigenPodManager.stake{value: DEPOSIT_SIZE}(_publicKey[i], _signature[i], _deposit_data_root[i]); } else { depositContract.deposit{value: DEPOSIT_SIZE - deposit}( _publicKey[i], abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)), _signature[i], _deposit_data_root[i] ); } // Refund pre-deposit if (deposit > 0) { (bool success, ) = preDepositOwnerAddress.call{value: deposit}(""); require(success, "Transfer of pre-deposit failed"); preDepositsAmount -= deposit; emit LogPreDepositRefund(id, _publicKey[i], preDepositOwnerAddress); } emit LogDeposit(id, _publicKey[i], _validatorType[i]); } validatorNonce = id; } else if (!netStaking && validatorCount > 0) { require(batchExitRequests[currentBatchId] == 0, "Batch already requested"); exitRequestsCount += validatorCount; batchExitRequests[currentBatchId] = validatorCount; batchExitQueue.push(currentBatchId); emit LogWithdraw(currentBatchId, validatorCount); } return true; } /// @notice Simplified public autoBalance function. function autoBalancePublic() external returns (bool) { return autoBalance(new bytes[](0), new bytes[](0), new bytes32[](0), new uint256[](0)); } /** NODE MANAGEMENT **/ /// @notice Returns validators and status /// @notice Returns list of validators. /// @dev Max 10 results starting at page 0 /// @param _page : Page to query. /// @return info Array for struct of nodes view /// @return totalPages supported. function getValidators(uint256 _page) external view returns (ValidatorView[] memory, uint256) { ValidatorView[] memory info = new ValidatorView[](10); uint256 pageSize = 10; uint256 length = validatorNonce; uint256 totalPages = length / pageSize; if (length > 0 && length % pageSize == 0) { totalPages--; } if (_page <= totalPages && length != 0) { for (uint256 i = 0; i < pageSize; i++) { uint256 index = length - _page * pageSize - i; Validator memory validator = validators[index]; info[i] = ValidatorView({ id: index, publicKey: validator.publicKey, validatorType: validator.validatorType }); if (index == 1) break; } } return (info, totalPages); } /** NETWORK ORACLES **/ /// @notice Consensus layer oracle report on validators and balances. /// Called by the oracle service that consolidates all the signatures and data posted by oracles for a decided block. /// The frequency of the updates is decided by the oracle service. /// @param _reportBlock : block number of the report. /// @param _validatorsCount : Number of validators on Consensus Layer. /// @param _validatorsBalance: Total balance of active validators on Consensus Layer. /// @param _validatorsExited: Number of validators exited. /// @param _eigenLayerValidatorsExited: Number of validators exited part of EigenLayer. /// @param _maxNumberOfWithdrawalsToClaim: Triggers claims from EigenLayer. /// @param _withdrawalsDisabled: Whether withdrawals are disabled based on slashing conditions. /// @param _signatures : Signatures of the report from trusted oracles. function oracleReport( uint256 _reportBlock, uint256 _validatorsCount, uint256 _validatorsBalance, uint256 _validatorsExited, uint256 _eigenLayerValidatorsExited, uint256 _maxNumberOfWithdrawalsToClaim, bool _withdrawalsDisabled, bytes[] calldata _signatures ) external whenNotPaused nonReentrant { require(_reportBlock > oracleReportBlock, "Invalid report block"); require(_validatorsCount <= validatorNonce, "Invalid validatorsCount"); require( _validatorsExited <= validatorNonce && _validatorsExited >= exitedValidators, "Invalid validatorsExited" ); require(_signatures.length >= oracleQuorum, "Invalid signatures length"); require(address(clayMain) != address(0), "Claymain not set"); // Verify signatures and quorum bytes32 signedHash = keccak256( abi.encodePacked( _reportBlock, _validatorsCount, _validatorsBalance, _validatorsExited, _eigenLayerValidatorsExited, _withdrawalsDisabled ) ).toEthSignedMessageHash(); for (uint256 i = 0; i < _signatures.length; i++) { require(_validateSignature(_reportBlock, signedHash, _signatures[i]), "Invalid Signature"); } _oracleReport( _reportBlock, _validatorsCount, _validatorsBalance, _validatorsExited, _eigenLayerValidatorsExited, _maxNumberOfWithdrawalsToClaim, _withdrawalsDisabled ); } /// @notice Internal implementation and update of rate. function _oracleReport( uint256 _reportBlock, uint256 _validatorsCount, uint256 _validatorsBalance, uint256 _validatorsExited, uint256 _eigenLayerValidatorsExited, uint256 _maxNumberOfWithdrawalsToClaim, bool _withdrawalsDisabled ) internal { // EigenLayer adjustments if (address(eigenPodManager) != address(0)) { // Claim if (_maxNumberOfWithdrawalsToClaim > 0) { claimEigenLayer(_maxNumberOfWithdrawalsToClaim); } // Start any EigenLayer withdraws uint256 balanceEigenLayer = _withdrawBeforeRestaking(_eigenLayerValidatorsExited); IDelayedWithdrawalRouter.UserDelayedWithdrawals memory queue = eigenDelayedWithdrawalRouter.userWithdrawals( address(this) ); uint256 eigenLayerClaimed = queue.delayedWithdrawalsCompleted > 0 ? eigenLayerExits[queue.delayedWithdrawalsCompleted - 1] : 0; uint256 eigenLayerExitedPending = _eigenLayerValidatorsExited - eigenLayerClaimed; // Adds back exited, for accounting and rewards, doesn't consider EigenLayer fully exited until claimed _validatorsBalance += balanceEigenLayer; _validatorsCount += eigenLayerExitedPending; _validatorsExited = _validatorsExited - eigenLayerExitedPending; } uint256 amountRewards = _validatorsBalance > _validatorsCount * DEPOSIT_SIZE ? _validatorsBalance - _validatorsCount * DEPOSIT_SIZE : 0; uint256 previousRewardsAccrued = rewardsAccrued; uint256 newExits = _validatorsExited - exitedValidators; // Update report oracleReportBlock = _reportBlock; activeValidators = _validatorsCount; activeValidatorsBalance = _validatorsBalance; exitedValidators = _validatorsExited; rewardsAccrued = amountRewards; // execute withdrawals disabling if (clayMain.withdrawalsDisabled() != _withdrawalsDisabled) { clayMain.setWithdrawalsDisabled(_withdrawalsDisabled); } // Adjust accrued rewards based on rewards on beacon chain if (nodeOperator != address(0)) { nodeOperatorAccruedFees = (amountRewards * nodeOperatorFees) / PERCENTAGE_BASE; } // Transfer balance to ClayMain and update it's contract tracker uint256 amountLiquid = address(this).balance; if (amountLiquid != 0) { uint256 amountExited = _min(amountLiquid, newExits * DEPOSIT_SIZE); uint256 amountLiquidRewards = amountLiquid - amountExited; uint256 totalRewards = amountRewards + amountLiquidRewards; uint256 amountNewRewards = _positiveSub(totalRewards, previousRewardsAccrued); uint256 amountNewLiquidRewards = _min(amountLiquidRewards, amountNewRewards); // Calculate Nodes rewards & distribute if (amountLiquidRewards > 0 && nodeOperator != address(0)) { uint256 amountNodeRewards = (amountLiquidRewards * nodeOperatorFees) / PERCENTAGE_BASE; uint256 amountNodeNewRewards = (amountNewLiquidRewards * nodeOperatorFees) / PERCENTAGE_BASE; amountLiquidRewards -= amountNodeRewards; amountLiquid -= amountNodeRewards; amountNewLiquidRewards -= amountNodeNewRewards; (bool success, ) = nodeOperator.call{value: amountNodeRewards}(""); require(success, "Transfer of node rewards failed"); } clayMain.receiveLiquidity{value: amountLiquid}(amountNewLiquidRewards, amountExited); emit LogLiquidityTransfer(_reportBlock, amountNewLiquidRewards, amountExited, amountLiquid); } else { clayMain.updateBalances(); } // Close batches if (newExits != 0) _closeBatches(newExits); emit LogOracleReport(_reportBlock, _validatorsCount, _validatorsBalance, _validatorsExited); } /// @notice Validates oracle signature and records block voted on. /// @param _reportBlock : block number of the report. /// @param _signedHash : Hash of the report. /// @param _signature : Signature of the report. /// @return A boolean indicating whether the signature is valid. function _validateSignature( uint256 _reportBlock, bytes32 _signedHash, bytes memory _signature ) internal returns (bool) { address signer = _signedHash.recover(_signature); // check it's in the list if (!oracleWhitelist[signer]) return false; // check single vote and mark block if (oracleVotes[signer] >= _reportBlock) return false; oracleVotes[signer] = _reportBlock; emit LogOracleVote(_reportBlock, signer); return true; } /// @notice Closes batch confirmation sent to ClayMain. /// @param _newExits : Number of new exits. function _closeBatches(uint256 _newExits) internal { // determine which batches can be closed uint256 fulfilledBatches = 0; for (uint256 i = batchExitQueueFront; i < batchExitQueue.length; i++) { uint256 batchId = batchExitQueue[i]; uint256 requestCount = batchExitRequests[batchId]; if (requestCount <= _newExits) { // close batch fulfilledBatches++; _newExits -= requestCount; } else { // partial fulfill, update and break batchExitRequests[batchId] = requestCount - _newExits; break; } // no more exits, end loop if (_newExits <= 0) break; } // create output uint256[] memory batches = new uint256[](fulfilledBatches); for (uint256 i = 0; i < fulfilledBatches; i++) { batches[i] = _deleteBatchFromQueue(); } clayMain.closeBatches(batches); } /// @notice Deletes first element from the batch exit queue. /// @return batchId The deleted element. function _deleteBatchFromQueue() internal returns (uint256 batchId) { require(batchExitQueue.length > batchExitQueueFront, "Queue is empty"); batchId = batchExitQueue[batchExitQueueFront]; delete batchExitQueue[batchExitQueueFront]; batchExitQueueFront += 1; } /** EIGENLAYER **/ /// @notice Update EigenPodManager address. /// @param _eigenPodManager : EigenPodManager address. /// @param _delayedWithdrawalRouter: DelayedWithdrawalRouter address. function setEigenLayer( address _eigenPodManager, address _delayedWithdrawalRouter ) external onlyRole(TIMELOCK_ROLE) { require(_eigenPodManager != address(0), "Invalid EigenPodManager"); require(_delayedWithdrawalRouter != address(0), "Invalid DelayedWithdrawalRouter"); eigenPodManager = IEigenPodManager(_eigenPodManager); eigenDelayedWithdrawalRouter = IDelayedWithdrawalRouter(_delayedWithdrawalRouter); emit LogSetEigenLayer(_eigenPodManager, _delayedWithdrawalRouter); } /// @notice Starts the delayed withdrawal process at EigenLayer and tracks how much in the process function _withdrawBeforeRestaking(uint256 _eigenLayerValidatorsExited) internal returns (uint256) { IEigenPod pod = eigenPodManager.getPod(address(this)); uint256 balance = address(pod).balance; if (balance > 0) { // NOTE: index for "PAUSED_DELAYED_WITHDRAWAL_CLAIMS" is "0" bool withdrawBeforeActive = (pod.hasRestaked() == false) && (IPausable(address(eigenDelayedWithdrawalRouter)).paused(0) == false); if (withdrawBeforeActive) { eigenLayerWithdraws += balance; pod.withdrawBeforeRestaking(); // Connects total exits to the latest withdrawal IDelayedWithdrawalRouter.UserDelayedWithdrawals memory queue = eigenDelayedWithdrawalRouter .userWithdrawals(address(this)); eigenLayerExits[queue.delayedWithdrawals.length - 1] = _eigenLayerValidatorsExited; emit LogWithdrawBeforeRestaking(queue.delayedWithdrawals.length - 1); return eigenLayerWithdraws; } else { return eigenLayerWithdraws + balance; } } return eigenLayerWithdraws; } // @notice Claims and tracks claimed value function claimEigenLayer(uint256 maxNumberOfWithdrawalsToClaim) public { eigenDelayedWithdrawalRouter.claimDelayedWithdrawals(maxNumberOfWithdrawalsToClaim); } /** OTHER **/ /// @notice Used for receiving payments receive() external payable { // Eigenlayer Claim Accounting if(msg.sender == address(eigenDelayedWithdrawalRouter)) { eigenLayerWithdraws -= msg.value; emit LogClaimEigenLayer(msg.value); } } /** BALANCES **/ /// @notice Returns the balance of the contract accounting for pending staking. function getBalance() external view returns (uint256) { return activeValidatorsBalance + getPendingStaking() - nodeOperatorAccruedFees; } /// @notice Returns the pending staking amount assuming fixed size. function getPendingStaking() public view returns (uint256) { return (validatorNonce - activeValidators - exitedValidators) * DEPOSIT_SIZE; } /** ADMIN **/ /// @notice Set minimum number of votes required for reporting. /// @dev By design an acceptable range from 1 to 100 /// @param _newQuorum: New quorum. function setOracleQuorum(uint256 _newQuorum) external onlyRole(TIMELOCK_ROLE) { require(_newQuorum > 0 && _newQuorum <= 100, "Invalid quorum"); emit LogSetOracleQuorum(oracleQuorum, _newQuorum); oracleQuorum = _newQuorum; } /// @notice Update oracle whitelist. The whitelist is set by Claystack service and gets updated depending on the performance and reliability of the oracles. /// @param _list : list of Oracle addresses. /// @param _flag : boolean for addition or removal. function setOracleWhitelist(address[] calldata _list, bool _flag) external onlyRole(TIMELOCK_ROLE) { require(_list.length > 0, "Invalid list length"); for (uint256 i = 0; i < _list.length; i++) { require(_list[i] != address(0), "Zero Address"); oracleWhitelist[_list[i]] = _flag; emit LogSetOracleWhitelist(_list[i], _flag); } } /// @notice Update autobalance caller whitelist. /// @param _list : list of autobalance caller addresses. /// @param _flag : boolean for addition or removal. function setAutoBalanceWhitelist(address[] calldata _list, bool _flag) external onlyRole(TIMELOCK_ROLE) { require(_list.length > 0, "Invalid list length"); for (uint256 i = 0; i < _list.length; i++) { require(_list[i] != address(0), "Zero Address"); autobalanceWhitelist[_list[i]] = _flag; emit LogSetAutoBalanceWhitelist(_list[i], _flag); } } /// @notice Update node operator fees. /// @param _fees : new node operator fees. function setNodeOperatorFees(uint256 _fees) external onlyRole(TIMELOCK_ROLE) { require(_fees <= MAX_NODE_OPERATOR_FEES, "Invalid nodeOperatorFees"); emit LogSetNodeOperatorFees(nodeOperatorFees, _fees); nodeOperatorFees = _fees; } /// @notice Sets `_clayMain` address. /// @dev ClayMain can be set only once. /// @param _clayMain : Address of new ClayMain contract. function setClayMain(address _clayMain) external onlyRole(TIMELOCK_UPGRADES_ROLE) { require(_clayMain != address(0), "Invalid ClayMain"); clayMain = IClayMain(_clayMain); emit LogSetClayMain(_clayMain); } /// @notice Update node operator address. /// @param _nodeOperator : new node operator address. function setNodeOperator(address _nodeOperator) external onlyRole(TIMELOCK_ROLE) { require(_nodeOperator != address(0), "Invalid nodeOperator"); nodeOperator = _nodeOperator; emit LogSetNodeOperator(_nodeOperator); } /** SUPPORT **/ /// @dev returns the smaller number between a and b function _min(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _b : _a; } /// @dev Returns the positive difference between x & y function _positiveSub(uint256 x, uint256 y) internal pure returns (uint256) { if (x < y) { return 0; } else { return x - y; } } /// @notice Triggers stopped state. function pause() external onlyRole(CS_SERVICE_ROLE) whenNotPaused { _pause(); } /// @notice Returns to normal state. function unpause() external onlyRole(CS_SERVICE_ROLE) whenPaused { _unpause(); } /// @notice Checks caller has the given `_roleName` or not. /// @param _roleName supported by RoleManager function _onlyRole(bytes32 _roleName) internal view { require(roleManager.checkRole(_roleName, msg.sender), "Auth Failed"); } /// @notice Upgrade the implementation of the proxy to `_newImplementation`. /// @param _newImplementation : Address of new implementation of the contract function upgradeTo( address _newImplementation ) external virtual override onlyRole(TIMELOCK_UPGRADES_ROLE) onlyProxy { _authorizeUpgrade(_newImplementation); _upgradeTo(_newImplementation); } /// @notice Function that should revert when `msg.sender` is not authorized to upgrade the contract or /// @param _newImplementation : Address of new implementation of the contract. function _authorizeUpgrade(address _newImplementation) internal virtual override onlyRole(TIMELOCK_UPGRADES_ROLE) { require(_newImplementation.code.length > 0, "!contract"); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"LogClaimEigenLayer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorId","type":"uint256"},{"indexed":true,"internalType":"bytes","name":"publicKey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"validatorType","type":"uint256"}],"name":"LogDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"reportBlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountExited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountLiquid","type":"uint256"}],"name":"LogLiquidityTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reportBlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validatorsCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validatorsBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validatorsExited","type":"uint256"}],"name":"LogOracleReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"reportBlockNumber","type":"uint256"},{"indexed":true,"internalType":"address","name":"oracle","type":"address"}],"name":"LogOracleVote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"publicKey","type":"bytes"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"LogPreDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorId","type":"uint256"},{"indexed":true,"internalType":"bytes","name":"publicKey","type":"bytes"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"LogPreDepositRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"bool","name":"flag","type":"bool"}],"name":"LogSetAutoBalanceWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newClaymain","type":"address"}],"name":"LogSetClayMain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"eigenPodManager","type":"address"},{"indexed":true,"internalType":"address","name":"delayedWithdrawalRouter","type":"address"}],"name":"LogSetEigenLayer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newNodeOperator","type":"address"}],"name":"LogSetNodeOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"LogSetNodeOperatorFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"LogSetOracleQuorum","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracle","type":"address"},{"indexed":true,"internalType":"bool","name":"flag","type":"bool"}],"name":"LogSetOracleWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawCount","type":"uint256"}],"name":"LogWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"delayedWithdrawalIndex","type":"uint256"}],"name":"LogWithdrawBeforeRestaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"activeValidators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeValidatorsBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_publicKey","type":"bytes[]"},{"internalType":"bytes[]","name":"_signature","type":"bytes[]"},{"internalType":"bytes32[]","name":"_deposit_data_root","type":"bytes32[]"},{"internalType":"uint256[]","name":"_validatorType","type":"uint256[]"}],"name":"autoBalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoBalancePublic","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"autobalanceWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"batchExitQueue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchExitQueueFront","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"batchExitRequests","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxNumberOfWithdrawalsToClaim","type":"uint256"}],"name":"claimEigenLayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clayMain","outputs":[{"internalType":"contract IClayMain","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"eigenLayerExits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eigenLayerWithdraws","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitRequestsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitedValidators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingStaking","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_page","type":"uint256"}],"name":"getValidators","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"uint256","name":"validatorType","type":"uint256"}],"internalType":"struct INodeManager.ValidatorView[]","name":"","type":"tuple[]"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_roleManager","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nodeOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodeOperatorAccruedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodeOperatorFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reportBlock","type":"uint256"},{"internalType":"uint256","name":"_validatorsCount","type":"uint256"},{"internalType":"uint256","name":"_validatorsBalance","type":"uint256"},{"internalType":"uint256","name":"_validatorsExited","type":"uint256"},{"internalType":"uint256","name":"_eigenLayerValidatorsExited","type":"uint256"},{"internalType":"uint256","name":"_maxNumberOfWithdrawalsToClaim","type":"uint256"},{"internalType":"bool","name":"_withdrawalsDisabled","type":"bool"},{"internalType":"bytes[]","name":"_signatures","type":"bytes[]"}],"name":"oracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracleReportBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"oracleVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"oracleWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"bytes[]","name":"_publicKey","type":"bytes[]"},{"internalType":"bytes[]","name":"_signature","type":"bytes[]"},{"internalType":"bytes32[]","name":"_deposit_data_root","type":"bytes32[]"}],"name":"preDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"preDepositOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preDepositsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"registeredValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_list","type":"address[]"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"setAutoBalanceWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_clayMain","type":"address"}],"name":"setClayMain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_eigenPodManager","type":"address"},{"internalType":"address","name":"_delayedWithdrawalRouter","type":"address"}],"name":"setEigenLayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeOperator","type":"address"}],"name":"setNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fees","type":"uint256"}],"name":"setNodeOperatorFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newQuorum","type":"uint256"}],"name":"setOracleQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_list","type":"address[]"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"setOracleWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"validatorNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"validatorType","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051614e1961005a60003960008181610aca01528181610b13015281816113050152818161134501528181611e8f01528181611ecf0152611f470152614e196000f3fe6080604052600436106102815760003560e01c806365577c551161014f578063a33a7d53116100c1578063b20257791161007a578063b20257791461082e578063b5a561fc14610845578063b8c226071461085c578063d2d49c4b14610873578063e17a684f1461088a578063fce4deab146108a057600080fd5b8063a33a7d5314610758578063a465ff1214610778578063a55461be146107a9578063a8158f65146107d7578063aa4a0d39146107ee578063b1fe93101461080e57600080fd5b80638456cb59116101135780638456cb59146106b05780638e03ac8d146106c5578063907a587b146106dc5780639266799a146106f3578063956041971461070a578063974fb7b31461073857600080fd5b806365577c551461060d57806368a80b4314610624578063747c17171461063757806378ea2dd9146106795780638357ed421461069057600080fd5b806343981753116101f35780634f1ef286116101ac5780634f1ef28614610543578063523f49461461055657806352d1902d146105925780635347f96e146105a75780635c975abb146105d55780635d1e7a59146105ed57600080fd5b8063439817531461048957806343ebf50a1461049e578063471f40fb146104be578063478e61aa146104ec578063485cc955146105035780634aa3a34e1461052357600080fd5b806335aa2e441161024557806335aa2e44146103ce5780633659cfe6146103fd5780633882b1c91461041d5780633d1ebf35146104345780633f2cf0b1146104545780633f4ba83a1461047457600080fd5b8063023c5b08146102ec57806312065fe01461032a57806326517d901461034d57806331b46e671461036d578063323f34431461038d57600080fd5b366102e757610114546001600160a01b031633036102e5573461011560008282546102ac91906140d9565b90915550506040513481527f239494018d16a74ebf338493b53d9f2a6ad0992e071b7ace15ccd561981bf1dd9060200160405180910390a15b005b600080fd5b3480156102f857600080fd5b5061010e5461030d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561033657600080fd5b5061033f6108b5565b604051908152602001610321565b34801561035957600080fd5b5061033f6103683660046140ec565b6108e0565b34801561037957600080fd5b506102e56103883660046140ec565b610902565b34801561039957600080fd5b506103be6103a836600461411a565b61010b6020526000908152604090205460ff1681565b6040519015158152602001610321565b3480156103da57600080fd5b506103ee6103e93660046140ec565b610964565b60405161032193929190614187565b34801561040957600080fd5b506102e561041836600461411a565b610a96565b34801561042957600080fd5b5061033f6101015481565b34801561044057600080fd5b506102e561044f3660046141bd565b610b7f565b34801561046057600080fd5b506102e561046f366004614248565b610ca4565b34801561048057600080fd5b506102e5610e3e565b34801561049557600080fd5b506103be610e7b565b3480156104aa57600080fd5b506102e56104b93660046140ec565b610ef3565b3480156104ca57600080fd5b506104de6104d93660046140ec565b610fa1565b60405161032192919061429e565b3480156104f857600080fd5b5061033f6101055481565b34801561050f57600080fd5b506102e561051e3660046141bd565b61123b565b34801561052f57600080fd5b506103be61053e36600461450f565b6114e0565b6102e561055136600461460e565b611e85565b34801561056257600080fd5b506103be61057136600461465d565b80516020818301810180516101068252928201919093012091525460ff1681565b34801561059e57600080fd5b5061033f611f3a565b3480156105b357600080fd5b5061033f6105c236600461411a565b61010c6020526000908152604090205481565b3480156105e157600080fd5b5060975460ff166103be565b3480156105f957600080fd5b506102e56106083660046140ec565b611fed565b34801561061957600080fd5b5061033f6101105481565b6103be610632366004614691565b612097565b34801561064357600080fd5b5061030d61065236600461465d565b8051602081830181018051610111825292820191909301209152546001600160a01b031681565b34801561068557600080fd5b5061033f61010d5481565b34801561069c57600080fd5b506102e56106ab366004614248565b6124a0565b3480156106bc57600080fd5b506102e561263a565b3480156106d157600080fd5b5061033f6101005481565b3480156106e857600080fd5b5061033f6101155481565b3480156106ff57600080fd5b5061033f6101125481565b34801561071657600080fd5b5061033f6107253660046140ec565b6101076020526000908152604090205481565b34801561074457600080fd5b506102e561075336600461411a565b612674565b34801561076457600080fd5b5060fc5461030d906001600160a01b031681565b34801561078457600080fd5b506103be61079336600461411a565b61010a6020526000908152604090205460ff1681565b3480156107b557600080fd5b5061033f6107c43660046140ec565b6101166020526000908152604090205481565b3480156107e357600080fd5b5061033f6101045481565b3480156107fa57600080fd5b506102e5610809366004614718565b612725565b34801561081a57600080fd5b506102e561082936600461411a565b612a44565b34801561083a57600080fd5b5061033f6101035481565b34801561085157600080fd5b5061033f6101095481565b34801561086857600080fd5b5061033f61010f5481565b34801561087f57600080fd5b5061033f6101025481565b34801561089657600080fd5b5061033f60ff5481565b3480156108ac57600080fd5b5061033f612b02565b6000610110546108c3612b02565b610103546108d191906147aa565b6108db91906140d9565b905090565b61010881815481106108f157600080fd5b600091825260209091200154905081565b61011454604051636a270dbb60e11b8152600481018390526001600160a01b039091169063d44e1b7690602401600060405180830381600087803b15801561094957600080fd5b505af115801561095d573d6000803e3d6000fd5b5050505050565b60fe6020526000908152604090208054819061097f906147bd565b80601f01602080910402602001604051908101604052809291908181526020018280546109ab906147bd565b80156109f85780601f106109cd576101008083540402835291602001916109f8565b820191906000526020600020905b8154815290600101906020018083116109db57829003601f168201915b505050505090806001018054610a0d906147bd565b80601f0160208091040260200160405190810160405280929190818152602001828054610a39906147bd565b8015610a865780601f10610a5b57610100808354040283529160200191610a86565b820191906000526020600020905b815481529060010190602001808311610a6957829003601f168201915b5050505050908060020154905083565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1610ac081612b37565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b115760405162461bcd60e51b8152600401610b08906147f1565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b43612be4565b6001600160a01b031614610b695760405162461bcd60e51b8152600401610b089061483d565b610b7282612c00565b610b7b82612c70565b5050565b600080516020614d7d833981519152610b9781612b37565b6001600160a01b038316610bed5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420456967656e506f644d616e616765720000000000000000006044820152606401610b08565b6001600160a01b038216610c435760405162461bcd60e51b815260206004820152601f60248201527f496e76616c69642044656c617965645769746864726177616c526f75746572006044820152606401610b08565b61011380546001600160a01b03199081166001600160a01b0386811691821790935561011480549092169285169283179091556040517f02a8f2ee3a37fb50b19f6b965301f3d567f9d0d7001b4df74d926f2870bc355790600090a3505050565b600080516020614d7d833981519152610cbc81612b37565b82610cff5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840d8d2e6e840d8cadccee8d606b1b6044820152606401610b08565b60005b8381101561095d576000858583818110610d1e57610d1e614889565b9050602002016020810190610d33919061411a565b6001600160a01b031603610d785760405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606401610b08565b8261010b6000878785818110610d9057610d90614889565b9050602002016020810190610da5919061411a565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055821515858583818110610de257610de2614889565b9050602002016020810190610df7919061411a565b6001600160a01b03167f37db4d805bae1ff00af5ccce3625706c8bc4181c0f0577c5d3715765e71edd8360405160405180910390a380610e368161489f565b915050610d02565b7f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc8610e6881612b37565b610e70612cb0565b610e78612cfb565b50565b604080516000808252602082019092526108db9082610eaa565b6060815260200190600190039081610e955790505b506040805160008082526020820190925290610ed6565b6060815260200190600190039081610ec15790505b5060408051600080825260208201908152818301909252906114e0565b600080516020614d7d833981519152610f0b81612b37565b6107d0821115610f5d5760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206e6f64654f70657261746f724665657300000000000000006044820152606401610b08565b61010f5460408051918252602082018490527fb1e342ac4a9cc386141d1bbc96e62081e34d521bdd7671a2dfe9b07424babd4b910160405180910390a15061010f55565b60408051600a80825261016082019092526060916000918291816020015b610fe360405180606001604052806000815260200160608152602001600081525090565b815260200190600190039081610fbf57505060ff54909150600a90600061100a83836148ce565b9050600082118015611023575061102183836148e2565b155b156110365780611032816148f6565b9150505b80871115801561104557508115155b1561122e5760005b8381101561122c57600081611062868b61490d565b61106c90866140d9565b61107691906140d9565b9050600060fe60008381526020019081526020016000206040518060600160405290816000820180546110a8906147bd565b80601f01602080910402602001604051908101604052809291908181526020018280546110d4906147bd565b80156111215780601f106110f657610100808354040283529160200191611121565b820191906000526020600020905b81548152906001019060200180831161110457829003601f168201915b5050505050815260200160018201805461113a906147bd565b80601f0160208091040260200160405190810160405280929190818152602001828054611166906147bd565b80156111b35780601f10611188576101008083540402835291602001916111b3565b820191906000526020600020905b81548152906001019060200180831161119657829003601f168201915b50505050508152602001600282015481525050905060405180606001604052808381526020018260000151815260200182604001518152508784815181106111fd576111fd614889565b60200260200101819052508160010361121757505061122c565b505080806112249061489f565b91505061104d565b505b9296929550919350505050565b600054610100900460ff161580801561125b5750600054600160ff909116105b806112755750303b158015611275575060005460ff166001145b6112d85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b08565b6000805460ff1916600117905580156112fb576000805461ff0019166101001790555b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036113435760405162461bcd60e51b8152600401610b08906147f1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611375612be4565b6001600160a01b03161461139b5760405162461bcd60e51b8152600401610b089061483d565b6001600160a01b0383166113f15760405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420726f6c654d616e61676572206164647265737300000000006044820152606401610b08565b6001600160a01b0382166114475760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964206465706f736974436f6e74726163742061646472657373006044820152606401610b08565b61144f612d4d565b611457612d7c565b61145f612dab565b60fb80546001600160a01b038086166001600160a01b03199283161790925560fd805492851692909116919091179055600161010d5580156114db576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006114ea612dd2565b6114f2612e18565b83518551148015611504575082518551145b8015611511575081518551145b6115555760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420706172616d206c656e6774687360581b6044820152606401610b08565b60fc546001600160a01b03166115a05760405162461bcd60e51b815260206004820152601060248201526f10db185e5b585a5b881b9bdd081cd95d60821b6044820152606401610b08565b84511561168e5760fb546040516312d9a6ad60e01b81527f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc860048201523360248201526001600160a01b03909116906312d9a6ad90604401602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190614924565b80611654575033600090815261010b602052604090205460ff165b61168e5760405162461bcd60e51b815260206004820152600b60248201526a105d5d1a0811985a5b195960aa1b6044820152606401610b08565b60fc548551604051637e70d9c560e01b81526004810191909152600091829182916001600160a01b031690637e70d9c5906024016060604051808303816000875af11580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190614941565b9250925092508180156117185750600081115b15611d625760ff5460005b82811015611d59576101068a828151811061174057611740614889565b6020026020010151604051611755919061497a565b9081526040519081900360200190205460ff16156117b55760405162461bcd60e51b815260206004820152601c60248201527f7075626c69634b657920616c72656164792072656769737465726564000000006044820152606401610b08565b6117be8261489f565b915060405180606001604052808b83815181106117dd576117dd614889565b602002602001015181526020018a83815181106117fc576117fc614889565b6020026020010151815260200188838151811061181b5761181b614889565b602090810291909101810151909152600084815260fe909152604090208151819061184690826149e4565b506020820151600182019061185b90826149e4565b506040820151816002015590505060016101068b838151811061188057611880614889565b6020026020010151604051611895919061497a565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060006101118b83815181106118d1576118d1614889565b60200260200101516040516118e6919061497a565b908152604051908190036020019020546001600160a01b031690506000811561191757670de0b6b3a764000061191a565b60005b9050600a89848151811061193057611930614889565b602002602001015103611aaa57610113546001600160a01b03166119965760405162461bcd60e51b815260206004820152601760248201527f456967656e506f644d616e61676572206e6f74207365740000000000000000006044820152606401610b08565b80156119e45760405162461bcd60e51b815260206004820152601b60248201527f456967656e506f64204d312052657175697265732033322045544800000000006044820152606401610b08565b610113548c516001600160a01b0390911690639b4e4634906801bc16d674ec800000908f9087908110611a1957611a19614889565b60200260200101518e8781518110611a3357611a33614889565b60200260200101518e8881518110611a4d57611a4d614889565b60200260200101516040518563ffffffff1660e01b8152600401611a7393929190614187565b6000604051808303818588803b158015611a8c57600080fd5b505af1158015611aa0573d6000803e3d6000fd5b5050505050611b9a565b60fd546001600160a01b03166322895118611ace836801bc16d674ec8000006140d9565b8e8681518110611ae057611ae0614889565b6020026020010151600160f81b600060a81b30604051602001611b0593929190614aa3565b6040516020818303038152906040528f8881518110611b2657611b26614889565b60200260200101518f8981518110611b4057611b40614889565b60200260200101516040518663ffffffff1660e01b8152600401611b679493929190614ae1565b6000604051808303818588803b158015611b8057600080fd5b505af1158015611b94573d6000803e3d6000fd5b50505050505b8015611cc2576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611bed576040519150601f19603f3d011682016040523d82523d6000602084013e611bf2565b606091505b5050905080611c435760405162461bcd60e51b815260206004820152601e60248201527f5472616e73666572206f66207072652d6465706f736974206661696c656400006044820152606401610b08565b816101126000828254611c5691906140d9565b92505081905550826001600160a01b03168d8581518110611c7957611c79614889565b6020026020010151604051611c8e919061497a565b6040519081900381209087907fa9600995f0aabc7cf77040d60ec36eb9ed073c47abfe0717fa47ca4c3df692a590600090a4505b8b8381518110611cd457611cd4614889565b6020026020010151604051611ce9919061497a565b6040518091039020847f3424df4338b4478ef58d99493e4ed96927ec2c63beec8d9de1d410a8b351acf18b8681518110611d2557611d25614889565b6020026020010151604051611d3c91815260200190565b60405180910390a350508080611d519061489f565b915050611723565b5060ff55611e6c565b81158015611d705750600081115b15611e6c576000838152610107602052604090205415611dd25760405162461bcd60e51b815260206004820152601760248201527f426174636820616c7265616479207265717565737465640000000000000000006044820152606401610b08565b806101006000828254611de591906147aa565b909155505060008381526101076020526040808220839055610108805460018101825592527f8543e9adbfbe1f62b7411fdf032fcfea758a7d6b332f64d971a1334c2ff364dd9091018490555183907f210405eb88ac7589aa9de0a6e36b9c9d3cd6e4061b74363d250a77afe3c6efb790611e639084815260200190565b60405180910390a25b60019350505050611e7d600160c955565b949350505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003611ecd5760405162461bcd60e51b8152600401610b08906147f1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611eff612be4565b6001600160a01b031614611f255760405162461bcd60e51b8152600401610b089061483d565b611f2e82612c00565b610b7b82826001612e78565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611fda5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610b08565b50600080516020614d9d83398151915290565b600080516020614d7d83398151915261200581612b37565b600082118015612016575060648211155b6120535760405162461bcd60e51b815260206004820152600e60248201526d496e76616c69642071756f72756d60901b6044820152606401610b08565b61010d5460408051918252602082018490527fd7916aef7cb7f069c87c44c871962132fdd6653e603c7180377b7226b1a5506d910160405180910390a15061010d55565b60006120a1612dd2565b6120a9612e18565b825184511480156120bb575081518451145b80156120c8575060008451115b61210c5760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420706172616d206c656e6774687360581b6044820152606401610b08565b835161212090670de0b6b3a764000061490d565b34146121855760405162461bcd60e51b815260206004820152602e60248201527f7072654465706f7369742076616c7565206d757374206265203120657468657260448201526d103832b9103b30b634b230ba37b960911b6064820152608401610b08565b60005b8451811015612472576101068582815181106121a6576121a6614889565b60200260200101516040516121bb919061497a565b9081526040519081900360200190205460ff161561221b5760405162461bcd60e51b815260206004820152601c60248201527f7075626c69634b657920616c72656164792072656769737465726564000000006044820152606401610b08565b60006001600160a01b031661011186838151811061223b5761223b614889565b6020026020010151604051612250919061497a565b908152604051908190036020019020546001600160a01b0316146122b65760405162461bcd60e51b815260206004820152601f60248201527f7075626c69634b657920616c7265616479207072652d6465706f7369746564006044820152606401610b08565b60fd5485516001600160a01b0390911690632289511890670de0b6b3a7640000908890859081106122e9576122e9614889565b6020026020010151600160f81b600060a81b3060405160200161230e93929190614aa3565b60405160208183030381529060405288868151811061232f5761232f614889565b602002602001015188878151811061234957612349614889565b60200260200101516040518663ffffffff1660e01b81526004016123709493929190614ae1565b6000604051808303818588803b15801561238957600080fd5b505af115801561239d573d6000803e3d6000fd5b5050505050336101118683815181106123b8576123b8614889565b60200260200101516040516123cd919061497a565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550336001600160a01b031685828151811061241b5761241b614889565b6020026020010151604051612430919061497a565b604051908190038120907f306a11966d026aa41af5f696c416464d527e1b8539d6b1db76a5a3298703720e90600090a38061246a8161489f565b915050612188565b5034610112600082825461248691906147aa565b909155506001915050612499600160c955565b9392505050565b600080516020614d7d8339815191526124b881612b37565b826124fb5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840d8d2e6e840d8cadccee8d606b1b6044820152606401610b08565b60005b8381101561095d57600085858381811061251a5761251a614889565b905060200201602081019061252f919061411a565b6001600160a01b0316036125745760405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606401610b08565b8261010a600087878581811061258c5761258c614889565b90506020020160208101906125a1919061411a565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558215158585838181106125de576125de614889565b90506020020160208101906125f3919061411a565b6001600160a01b03167fdf67d94eba45581175e628d76b5e5058cf811bb243dfa6627fd46b8465234e6260405160405180910390a3806126328161489f565b9150506124fe565b7f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc861266481612b37565b61266c612dd2565b610e78612fe3565b600080516020614d7d83398151915261268c81612b37565b6001600160a01b0382166126d95760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103737b232a7b832b930ba37b960611b6044820152606401610b08565b61010e80546001600160a01b0319166001600160a01b0384169081179091556040517f826392384452e326ae3357d613e8f331be7a57fc88379826286d982f1261b46d90600090a25050565b61272d612dd2565b612735612e18565b61010554891161277e5760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964207265706f727420626c6f636b60601b6044820152606401610b08565b60ff548811156127d05760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642076616c696461746f7273436f756e740000000000000000006044820152606401610b08565b60ff5486111580156127e55750610101548610155b6128315760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f727345786974656400000000000000006044820152606401610b08565b61010d548110156128845760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964207369676e617475726573206c656e677468000000000000006044820152606401610b08565b60fc546001600160a01b03166128cf5760405162461bcd60e51b815260206004820152601060248201526f10db185e5b585a5b881b9bdd081cd95d60821b6044820152606401610b08565b6040805160208082018c90528183018b9052606082018a90526080820189905260a0820188905285151560f81b60c0830152825160a181840301815260c1830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060e184015260fd808401919091528351808403909101815261011d909201909252805191012060005b82811015612a1e576129cc8b8386868581811061298057612980614889565b90506020028101906129929190614b2c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061302092505050565b612a0c5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964205369676e617475726560781b6044820152606401610b08565b80612a168161489f565b915050612961565b50612a2e8a8a8a8a8a8a8a6130d2565b50612a39600160c955565b505050505050505050565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1612a6e81612b37565b6001600160a01b038216612ab75760405162461bcd60e51b815260206004820152601060248201526f24b73b30b634b21021b630bca6b0b4b760811b6044820152606401610b08565b60fc80546001600160a01b0319166001600160a01b0384169081179091556040517f104a66f1cbeb1a854e33542efdf4cab6dd7bd309067e996a7c9cd2bb5c082b8390600090a25050565b60006801bc16d674ec800000610101546101025460ff54612b2391906140d9565b612b2d91906140d9565b6108db919061490d565b60fb546040516312d9a6ad60e01b8152600481018390523360248201526001600160a01b03909116906312d9a6ad90604401602060405180830381865afa158015612b86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612baa9190614924565b610e785760405162461bcd60e51b815260206004820152600b60248201526a105d5d1a0811985a5b195960aa1b6044820152606401610b08565b600080516020614d9d833981519152546001600160a01b031690565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1612c2a81612b37565b6000826001600160a01b03163b11610b7b5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610b08565b612c7981613688565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60975460ff16612cf95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b08565b565b612d03612cb0565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600054610100900460ff16612d745760405162461bcd60e51b8152600401610b0890614b72565b612cf9613724565b600054610100900460ff16612da35760405162461bcd60e51b8152600401610b0890614b72565b612cf9613757565b600054610100900460ff16612cf95760405162461bcd60e51b8152600401610b0890614b72565b60975460ff1615612cf95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b08565b600260c95403612e6a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b08565b600260c955565b600160c955565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612eab576114db83613688565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612f05575060408051601f3d908101601f19168201909252612f0291810190614bbd565b60015b612f685760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610b08565b600080516020614d9d8339815191528114612fd75760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610b08565b506114db83838361377e565b612feb612dd2565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612d303390565b60008061302d84846137a9565b6001600160a01b038116600090815261010a602052604090205490915060ff1661305b576000915050612499565b6001600160a01b038116600090815261010c60205260409020548511613085576000915050612499565b6001600160a01b038116600081815261010c60205260408082208890555187917e4a0156b3be77c48016f4bd6f1dcb3d729680a091d3889629370a973475d75d91a3506001949350505050565b610113546001600160a01b0316156131ea5781156130f3576130f382610902565b60006130fe846137cf565b6101145460405163ecb7cb1b60e01b81523060048201529192506000916001600160a01b039091169063ecb7cb1b90602401600060405180830381865afa15801561314d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131759190810190614bd6565b905060008082600001511161318b5760006131b1565b6101166000600184600001516131a191906140d9565b8152602001908152602001600020545b905060006131bf82886140d9565b90506131cb848a6147aa565b98506131d7818b6147aa565b99506131e381896140d9565b9750505050505b60006131ff6801bc16d674ec8000008861490d565b861161320c576000613229565b61321f6801bc16d674ec8000008861490d565b61322990876140d9565b61010454610101549192509060009061324290886140d9565b6101058b90556101028a905561010389905561010188905561010484905560fc54604080516344573f9760e11b81529051929350861515926001600160a01b03909216916388ae7f2e916004818101926020929091908290030181865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d59190614924565b15151461333c5760fc54604051630a54644f60e21b815285151560048201526001600160a01b0390911690632951913c90602401600060405180830381600087803b15801561332357600080fd5b505af1158015613337573d6000803e3d6000fd5b505050505b61010e546001600160a01b03161561336f5761271061010f5484613360919061490d565b61336a91906148ce565b610110555b4780156135bb5760006133948261338f6801bc16d674ec8000008661490d565b613ab2565b905060006133a282846140d9565b905060006133b082886147aa565b905060006133be8288613ac7565b905060006133cc8483613ab2565b90506000841180156133e9575061010e546001600160a01b031615155b156134fd57600061271061010f5486613402919061490d565b61340c91906148ce565b9050600061271061010f5484613422919061490d565b61342c91906148ce565b905061343882876140d9565b955061344482896140d9565b975061345081846140d9565b61010e546040519194506000916001600160a01b039091169084908381818185875af1925050503d80600081146134a3576040519150601f19603f3d011682016040523d82523d6000602084013e6134a8565b606091505b50509050806134f95760405162461bcd60e51b815260206004820152601f60248201527f5472616e73666572206f66206e6f64652072657761726473206661696c6564006044820152606401610b08565b5050505b60fc5460405163070f0b8960e21b815260048101839052602481018790526001600160a01b0390911690631c3c2e249088906044016000604051808303818588803b15801561354b57600080fd5b505af115801561355f573d6000803e3d6000fd5b50505050508f7f1947dd35f2ad7cfad67d80241fe2f032f18b67bf60792d5f9132dac5817527cb8287896040516135a9939291909283526020830191909152604082015260600190565b60405180910390a25050505050613624565b60fc60009054906101000a90046001600160a01b03166001600160a01b0316636f3fe4046040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561360b57600080fd5b505af115801561361f573d6000803e3d6000fd5b505050505b81156136335761363382613aea565b604080518c8152602081018c90529081018a9052606081018990527f7a4a8ff550d096ae3e71e1c79680b17560ea3076ff95d4666ab60c0ef5308a569060800160405180910390a15050505050505050505050565b6001600160a01b0381163b6136f55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b08565b600080516020614d9d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1661374b5760405162461bcd60e51b8152600401610b0890614b72565b6097805460ff19169055565b600054610100900460ff16612e715760405162461bcd60e51b8152600401610b0890614b72565b61378783612c70565b6000825111806137945750805b156114db576137a38383613c92565b50505050565b60008060006137b88585613d7d565b915091506137c581613dc2565b5090505b92915050565b6101135460405163a38406a360e01b815230600482015260009182916001600160a01b039091169063a38406a390602401602060405180830381865afa15801561381d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138419190614cf2565b90506001600160a01b038116318015613aa6576000826001600160a01b0316633106ab536040518163ffffffff1660e01b8152600401602060405180830381865afa158015613894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b89190614924565b158015613930575061011454604051635ac86ab760e01b8152600060048201526001600160a01b0390911690635ac86ab790602401602060405180830381865afa15801561390a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392e9190614924565b155b90508015613a8e5781610115600082825461394b91906147aa565b92505081905550826001600160a01b031663baa7145a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561398d57600080fd5b505af11580156139a1573d6000803e3d6000fd5b50506101145460405163ecb7cb1b60e01b8152306004820152600093506001600160a01b03909116915063ecb7cb1b90602401600060405180830381865afa1580156139f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a199190810190614bd6565b90508561011660006001846020015151613a3391906140d9565b8152602001908152602001600020819055506001816020015151613a5791906140d9565b6040517f6ae853a67b9b71d5e6454259a07b6b7fcf4b2c78c0703a0ccc38834d66ed952990600090a2505061011554949350505050565b8161011554613a9d91906147aa565b95945050505050565b50506101155492915050565b6000818311613ac15782612499565b50919050565b600081831015613ad9575060006137c9565b613ae382846140d9565b90506137c9565b610109546000905b61010854811015613ba15760006101088281548110613b1357613b13614889565b6000918252602080832090910154808352610107909152604090912054909150848111613b595783613b448161489f565b9450613b52905081866140d9565b9450613b7d565b613b6385826140d9565b600092835261010760205260409092209190915550613ba1565b60008511613b8c575050613ba1565b50508080613b999061489f565b915050613af2565b506000816001600160401b03811115613bbc57613bbc614325565b604051908082528060200260200182016040528015613be5578160200160208202803683370190505b50905060005b82811015613c2a57613bfb613f0c565b828281518110613c0d57613c0d614889565b602090810291909101015280613c228161489f565b915050613beb565b5060fc546040516370e301fb60e11b81526001600160a01b039091169063e1c603f690613c5b908490600401614d0f565b600060405180830381600087803b158015613c7557600080fd5b505af1158015613c89573d6000803e3d6000fd5b50505050505050565b60606001600160a01b0383163b613cfa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b08565b600080846001600160a01b031684604051613d15919061497a565b600060405180830381855af49150503d8060008114613d50576040519150601f19603f3d011682016040523d82523d6000602084013e613d55565b606091505b5091509150613a9d8282604051806060016040528060278152602001614dbd60279139613fbc565b6000808251604103613db35760208301516040840151606085015160001a613da787828585613fd5565b94509450505050613dbb565b506000905060025b9250929050565b6000816004811115613dd657613dd6614d53565b03613dde5750565b6001816004811115613df257613df2614d53565b03613e3f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b08565b6002816004811115613e5357613e53614d53565b03613ea05760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b08565b6003816004811115613eb457613eb4614d53565b03610e785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b08565b610109546101085460009110613f555760405162461bcd60e51b815260206004820152600e60248201526d517565756520697320656d70747960901b6044820152606401610b08565b6101086101095481548110613f6c57613f6c614889565b906000526020600020015490506101086101095481548110613f9057613f90614889565b906000526020600020016000905560016101096000828254613fb291906147aa565b9250508190555090565b60608315613fcb575081612499565b6124998383614099565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561400c5750600090506003614090565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614060573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661408957600060019250925050614090565b9150600090505b94509492505050565b8151156140a95781518083602001fd5b8060405162461bcd60e51b8152600401610b089190614d69565b634e487b7160e01b600052601160045260246000fd5b818103818111156137c9576137c96140c3565b6000602082840312156140fe57600080fd5b5035919050565b6001600160a01b0381168114610e7857600080fd5b60006020828403121561412c57600080fd5b813561249981614105565b60005b8381101561415257818101518382015260200161413a565b50506000910152565b60008151808452614173816020860160208601614137565b601f01601f19169290920160200192915050565b60608152600061419a606083018661415b565b82810360208401526141ac818661415b565b915050826040830152949350505050565b600080604083850312156141d057600080fd5b82356141db81614105565b915060208301356141eb81614105565b809150509250929050565b60008083601f84011261420857600080fd5b5081356001600160401b0381111561421f57600080fd5b6020830191508360208260051b8501011115613dbb57600080fd5b8015158114610e7857600080fd5b60008060006040848603121561425d57600080fd5b83356001600160401b0381111561427357600080fd5b61427f868287016141f6565b90945092505060208401356142938161423a565b809150509250925092565b60006040808301818452808651808352606092508286019150828160051b8701016020808a0160005b8481101561431057605f198a85030186528151805185528381015188858701526142f38987018261415b565b918a0151958a0195909552958301959350908201906001016142c7565b50509690960196909652509295945050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561435d5761435d614325565b60405290565b604051601f8201601f191681016001600160401b038111828210171561438b5761438b614325565b604052919050565b60006001600160401b038211156143ac576143ac614325565b5060051b60200190565b600082601f8301126143c757600080fd5b81356001600160401b038111156143e0576143e0614325565b6143f3601f8201601f1916602001614363565b81815284602083860101111561440857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261443657600080fd5b8135602061444b61444683614393565b614363565b82815260059290921b8401810191818101908684111561446a57600080fd5b8286015b848110156144a95780356001600160401b0381111561448d5760008081fd5b61449b8986838b01016143b6565b84525091830191830161446e565b509695505050505050565b600082601f8301126144c557600080fd5b813560206144d561444683614393565b82815260059290921b840181019181810190868411156144f457600080fd5b8286015b848110156144a957803583529183019183016144f8565b6000806000806080858703121561452557600080fd5b84356001600160401b038082111561453c57600080fd5b61454888838901614425565b955060209150818701358181111561455f57600080fd5b61456b89828a01614425565b95505060408701358181111561458057600080fd5b61458c89828a016144b4565b9450506060870135818111156145a157600080fd5b87019050601f810188136145b457600080fd5b80356145c261444682614393565b81815260059190911b8201830190838101908a8311156145e157600080fd5b928401925b828410156145ff578335825292840192908401906145e6565b979a9699509497505050505050565b6000806040838503121561462157600080fd5b823561462c81614105565b915060208301356001600160401b0381111561464757600080fd5b614653858286016143b6565b9150509250929050565b60006020828403121561466f57600080fd5b81356001600160401b0381111561468557600080fd5b611e7d848285016143b6565b6000806000606084860312156146a657600080fd5b83356001600160401b03808211156146bd57600080fd5b6146c987838801614425565b945060208601359150808211156146df57600080fd5b6146eb87838801614425565b9350604086013591508082111561470157600080fd5b5061470e868287016144b4565b9150509250925092565b60008060008060008060008060006101008a8c03121561473757600080fd5b8935985060208a0135975060408a0135965060608a0135955060808a0135945060a08a0135935060c08a013561476c8161423a565b925060e08a01356001600160401b0381111561478757600080fd5b6147938c828d016141f6565b915080935050809150509295985092959850929598565b808201808211156137c9576137c96140c3565b600181811c908216806147d157607f821691505b602082108103613ac157634e487b7160e01b600052602260045260246000fd5b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600182016148b1576148b16140c3565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826148dd576148dd6148b8565b500490565b6000826148f1576148f16148b8565b500690565b600081614905576149056140c3565b506000190190565b80820281158282048414176137c9576137c96140c3565b60006020828403121561493657600080fd5b81516124998161423a565b60008060006060848603121561495657600080fd5b8351925060208401516149688161423a565b80925050604084015190509250925092565b6000825161498c818460208701614137565b9190910192915050565b601f8211156114db57600081815260208120601f850160051c810160208610156149bd5750805b601f850160051c820191505b818110156149dc578281556001016149c9565b505050505050565b81516001600160401b038111156149fd576149fd614325565b614a1181614a0b84546147bd565b84614996565b602080601f831160018114614a465760008415614a2e5750858301515b600019600386901b1c1916600185901b1785556149dc565b600085815260208120601f198616915b82811015614a7557888601518255948401946001909101908401614a56565b5085821015614a935787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160f81b03199390931683526001600160a81b031991909116600183015260601b6bffffffffffffffffffffffff1916600c82015260200190565b608081526000614af4608083018761415b565b8281036020840152614b06818761415b565b90508281036040840152614b1a818661415b565b91505082606083015295945050505050565b6000808335601e19843603018112614b4357600080fd5b8301803591506001600160401b03821115614b5d57600080fd5b602001915036819003821315613dbb57600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215614bcf57600080fd5b5051919050565b60006020808385031215614be957600080fd5b82516001600160401b0380821115614c0057600080fd5b81850191506040808388031215614c1657600080fd5b614c1e61433b565b835181528484015183811115614c3357600080fd5b80850194505087601f850112614c4857600080fd5b83519250614c5861444684614393565b83815260069390931b84018501928581019089851115614c7757600080fd5b948601945b84861015614ce05783868b031215614c945760008081fd5b614c9c61433b565b86516001600160e01b0381168114614cb45760008081fd5b81528688015163ffffffff81168114614ccd5760008081fd5b8189015282529483019490860190614c7c565b95820195909552979650505050505050565b600060208284031215614d0457600080fd5b815161249981614105565b6020808252825182820181905260009190848201906040850190845b81811015614d4757835183529284019291840191600101614d2b565b50909695505050505050565b634e487b7160e01b600052602160045260246000fd5b602081526000612499602083018461415b56fef66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202d5aeadc3340defc038b9c71a09d61a2ccd715d6fd8efadaaeb86875e6ee919464736f6c63430008120033
Deployed Bytecode
0x6080604052600436106102815760003560e01c806365577c551161014f578063a33a7d53116100c1578063b20257791161007a578063b20257791461082e578063b5a561fc14610845578063b8c226071461085c578063d2d49c4b14610873578063e17a684f1461088a578063fce4deab146108a057600080fd5b8063a33a7d5314610758578063a465ff1214610778578063a55461be146107a9578063a8158f65146107d7578063aa4a0d39146107ee578063b1fe93101461080e57600080fd5b80638456cb59116101135780638456cb59146106b05780638e03ac8d146106c5578063907a587b146106dc5780639266799a146106f3578063956041971461070a578063974fb7b31461073857600080fd5b806365577c551461060d57806368a80b4314610624578063747c17171461063757806378ea2dd9146106795780638357ed421461069057600080fd5b806343981753116101f35780634f1ef286116101ac5780634f1ef28614610543578063523f49461461055657806352d1902d146105925780635347f96e146105a75780635c975abb146105d55780635d1e7a59146105ed57600080fd5b8063439817531461048957806343ebf50a1461049e578063471f40fb146104be578063478e61aa146104ec578063485cc955146105035780634aa3a34e1461052357600080fd5b806335aa2e441161024557806335aa2e44146103ce5780633659cfe6146103fd5780633882b1c91461041d5780633d1ebf35146104345780633f2cf0b1146104545780633f4ba83a1461047457600080fd5b8063023c5b08146102ec57806312065fe01461032a57806326517d901461034d57806331b46e671461036d578063323f34431461038d57600080fd5b366102e757610114546001600160a01b031633036102e5573461011560008282546102ac91906140d9565b90915550506040513481527f239494018d16a74ebf338493b53d9f2a6ad0992e071b7ace15ccd561981bf1dd9060200160405180910390a15b005b600080fd5b3480156102f857600080fd5b5061010e5461030d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561033657600080fd5b5061033f6108b5565b604051908152602001610321565b34801561035957600080fd5b5061033f6103683660046140ec565b6108e0565b34801561037957600080fd5b506102e56103883660046140ec565b610902565b34801561039957600080fd5b506103be6103a836600461411a565b61010b6020526000908152604090205460ff1681565b6040519015158152602001610321565b3480156103da57600080fd5b506103ee6103e93660046140ec565b610964565b60405161032193929190614187565b34801561040957600080fd5b506102e561041836600461411a565b610a96565b34801561042957600080fd5b5061033f6101015481565b34801561044057600080fd5b506102e561044f3660046141bd565b610b7f565b34801561046057600080fd5b506102e561046f366004614248565b610ca4565b34801561048057600080fd5b506102e5610e3e565b34801561049557600080fd5b506103be610e7b565b3480156104aa57600080fd5b506102e56104b93660046140ec565b610ef3565b3480156104ca57600080fd5b506104de6104d93660046140ec565b610fa1565b60405161032192919061429e565b3480156104f857600080fd5b5061033f6101055481565b34801561050f57600080fd5b506102e561051e3660046141bd565b61123b565b34801561052f57600080fd5b506103be61053e36600461450f565b6114e0565b6102e561055136600461460e565b611e85565b34801561056257600080fd5b506103be61057136600461465d565b80516020818301810180516101068252928201919093012091525460ff1681565b34801561059e57600080fd5b5061033f611f3a565b3480156105b357600080fd5b5061033f6105c236600461411a565b61010c6020526000908152604090205481565b3480156105e157600080fd5b5060975460ff166103be565b3480156105f957600080fd5b506102e56106083660046140ec565b611fed565b34801561061957600080fd5b5061033f6101105481565b6103be610632366004614691565b612097565b34801561064357600080fd5b5061030d61065236600461465d565b8051602081830181018051610111825292820191909301209152546001600160a01b031681565b34801561068557600080fd5b5061033f61010d5481565b34801561069c57600080fd5b506102e56106ab366004614248565b6124a0565b3480156106bc57600080fd5b506102e561263a565b3480156106d157600080fd5b5061033f6101005481565b3480156106e857600080fd5b5061033f6101155481565b3480156106ff57600080fd5b5061033f6101125481565b34801561071657600080fd5b5061033f6107253660046140ec565b6101076020526000908152604090205481565b34801561074457600080fd5b506102e561075336600461411a565b612674565b34801561076457600080fd5b5060fc5461030d906001600160a01b031681565b34801561078457600080fd5b506103be61079336600461411a565b61010a6020526000908152604090205460ff1681565b3480156107b557600080fd5b5061033f6107c43660046140ec565b6101166020526000908152604090205481565b3480156107e357600080fd5b5061033f6101045481565b3480156107fa57600080fd5b506102e5610809366004614718565b612725565b34801561081a57600080fd5b506102e561082936600461411a565b612a44565b34801561083a57600080fd5b5061033f6101035481565b34801561085157600080fd5b5061033f6101095481565b34801561086857600080fd5b5061033f61010f5481565b34801561087f57600080fd5b5061033f6101025481565b34801561089657600080fd5b5061033f60ff5481565b3480156108ac57600080fd5b5061033f612b02565b6000610110546108c3612b02565b610103546108d191906147aa565b6108db91906140d9565b905090565b61010881815481106108f157600080fd5b600091825260209091200154905081565b61011454604051636a270dbb60e11b8152600481018390526001600160a01b039091169063d44e1b7690602401600060405180830381600087803b15801561094957600080fd5b505af115801561095d573d6000803e3d6000fd5b5050505050565b60fe6020526000908152604090208054819061097f906147bd565b80601f01602080910402602001604051908101604052809291908181526020018280546109ab906147bd565b80156109f85780601f106109cd576101008083540402835291602001916109f8565b820191906000526020600020905b8154815290600101906020018083116109db57829003601f168201915b505050505090806001018054610a0d906147bd565b80601f0160208091040260200160405190810160405280929190818152602001828054610a39906147bd565b8015610a865780601f10610a5b57610100808354040283529160200191610a86565b820191906000526020600020905b815481529060010190602001808311610a6957829003601f168201915b5050505050908060020154905083565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1610ac081612b37565b6001600160a01b037f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f163003610b115760405162461bcd60e51b8152600401610b08906147f1565b60405180910390fd5b7f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f6001600160a01b0316610b43612be4565b6001600160a01b031614610b695760405162461bcd60e51b8152600401610b089061483d565b610b7282612c00565b610b7b82612c70565b5050565b600080516020614d7d833981519152610b9781612b37565b6001600160a01b038316610bed5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420456967656e506f644d616e616765720000000000000000006044820152606401610b08565b6001600160a01b038216610c435760405162461bcd60e51b815260206004820152601f60248201527f496e76616c69642044656c617965645769746864726177616c526f75746572006044820152606401610b08565b61011380546001600160a01b03199081166001600160a01b0386811691821790935561011480549092169285169283179091556040517f02a8f2ee3a37fb50b19f6b965301f3d567f9d0d7001b4df74d926f2870bc355790600090a3505050565b600080516020614d7d833981519152610cbc81612b37565b82610cff5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840d8d2e6e840d8cadccee8d606b1b6044820152606401610b08565b60005b8381101561095d576000858583818110610d1e57610d1e614889565b9050602002016020810190610d33919061411a565b6001600160a01b031603610d785760405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606401610b08565b8261010b6000878785818110610d9057610d90614889565b9050602002016020810190610da5919061411a565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055821515858583818110610de257610de2614889565b9050602002016020810190610df7919061411a565b6001600160a01b03167f37db4d805bae1ff00af5ccce3625706c8bc4181c0f0577c5d3715765e71edd8360405160405180910390a380610e368161489f565b915050610d02565b7f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc8610e6881612b37565b610e70612cb0565b610e78612cfb565b50565b604080516000808252602082019092526108db9082610eaa565b6060815260200190600190039081610e955790505b506040805160008082526020820190925290610ed6565b6060815260200190600190039081610ec15790505b5060408051600080825260208201908152818301909252906114e0565b600080516020614d7d833981519152610f0b81612b37565b6107d0821115610f5d5760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206e6f64654f70657261746f724665657300000000000000006044820152606401610b08565b61010f5460408051918252602082018490527fb1e342ac4a9cc386141d1bbc96e62081e34d521bdd7671a2dfe9b07424babd4b910160405180910390a15061010f55565b60408051600a80825261016082019092526060916000918291816020015b610fe360405180606001604052806000815260200160608152602001600081525090565b815260200190600190039081610fbf57505060ff54909150600a90600061100a83836148ce565b9050600082118015611023575061102183836148e2565b155b156110365780611032816148f6565b9150505b80871115801561104557508115155b1561122e5760005b8381101561122c57600081611062868b61490d565b61106c90866140d9565b61107691906140d9565b9050600060fe60008381526020019081526020016000206040518060600160405290816000820180546110a8906147bd565b80601f01602080910402602001604051908101604052809291908181526020018280546110d4906147bd565b80156111215780601f106110f657610100808354040283529160200191611121565b820191906000526020600020905b81548152906001019060200180831161110457829003601f168201915b5050505050815260200160018201805461113a906147bd565b80601f0160208091040260200160405190810160405280929190818152602001828054611166906147bd565b80156111b35780601f10611188576101008083540402835291602001916111b3565b820191906000526020600020905b81548152906001019060200180831161119657829003601f168201915b50505050508152602001600282015481525050905060405180606001604052808381526020018260000151815260200182604001518152508784815181106111fd576111fd614889565b60200260200101819052508160010361121757505061122c565b505080806112249061489f565b91505061104d565b505b9296929550919350505050565b600054610100900460ff161580801561125b5750600054600160ff909116105b806112755750303b158015611275575060005460ff166001145b6112d85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b08565b6000805460ff1916600117905580156112fb576000805461ff0019166101001790555b6001600160a01b037f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f1630036113435760405162461bcd60e51b8152600401610b08906147f1565b7f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f6001600160a01b0316611375612be4565b6001600160a01b03161461139b5760405162461bcd60e51b8152600401610b089061483d565b6001600160a01b0383166113f15760405162461bcd60e51b815260206004820152601b60248201527f496e76616c696420726f6c654d616e61676572206164647265737300000000006044820152606401610b08565b6001600160a01b0382166114475760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964206465706f736974436f6e74726163742061646472657373006044820152606401610b08565b61144f612d4d565b611457612d7c565b61145f612dab565b60fb80546001600160a01b038086166001600160a01b03199283161790925560fd805492851692909116919091179055600161010d5580156114db576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006114ea612dd2565b6114f2612e18565b83518551148015611504575082518551145b8015611511575081518551145b6115555760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420706172616d206c656e6774687360581b6044820152606401610b08565b60fc546001600160a01b03166115a05760405162461bcd60e51b815260206004820152601060248201526f10db185e5b585a5b881b9bdd081cd95d60821b6044820152606401610b08565b84511561168e5760fb546040516312d9a6ad60e01b81527f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc860048201523360248201526001600160a01b03909116906312d9a6ad90604401602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190614924565b80611654575033600090815261010b602052604090205460ff165b61168e5760405162461bcd60e51b815260206004820152600b60248201526a105d5d1a0811985a5b195960aa1b6044820152606401610b08565b60fc548551604051637e70d9c560e01b81526004810191909152600091829182916001600160a01b031690637e70d9c5906024016060604051808303816000875af11580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190614941565b9250925092508180156117185750600081115b15611d625760ff5460005b82811015611d59576101068a828151811061174057611740614889565b6020026020010151604051611755919061497a565b9081526040519081900360200190205460ff16156117b55760405162461bcd60e51b815260206004820152601c60248201527f7075626c69634b657920616c72656164792072656769737465726564000000006044820152606401610b08565b6117be8261489f565b915060405180606001604052808b83815181106117dd576117dd614889565b602002602001015181526020018a83815181106117fc576117fc614889565b6020026020010151815260200188838151811061181b5761181b614889565b602090810291909101810151909152600084815260fe909152604090208151819061184690826149e4565b506020820151600182019061185b90826149e4565b506040820151816002015590505060016101068b838151811061188057611880614889565b6020026020010151604051611895919061497a565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060006101118b83815181106118d1576118d1614889565b60200260200101516040516118e6919061497a565b908152604051908190036020019020546001600160a01b031690506000811561191757670de0b6b3a764000061191a565b60005b9050600a89848151811061193057611930614889565b602002602001015103611aaa57610113546001600160a01b03166119965760405162461bcd60e51b815260206004820152601760248201527f456967656e506f644d616e61676572206e6f74207365740000000000000000006044820152606401610b08565b80156119e45760405162461bcd60e51b815260206004820152601b60248201527f456967656e506f64204d312052657175697265732033322045544800000000006044820152606401610b08565b610113548c516001600160a01b0390911690639b4e4634906801bc16d674ec800000908f9087908110611a1957611a19614889565b60200260200101518e8781518110611a3357611a33614889565b60200260200101518e8881518110611a4d57611a4d614889565b60200260200101516040518563ffffffff1660e01b8152600401611a7393929190614187565b6000604051808303818588803b158015611a8c57600080fd5b505af1158015611aa0573d6000803e3d6000fd5b5050505050611b9a565b60fd546001600160a01b03166322895118611ace836801bc16d674ec8000006140d9565b8e8681518110611ae057611ae0614889565b6020026020010151600160f81b600060a81b30604051602001611b0593929190614aa3565b6040516020818303038152906040528f8881518110611b2657611b26614889565b60200260200101518f8981518110611b4057611b40614889565b60200260200101516040518663ffffffff1660e01b8152600401611b679493929190614ae1565b6000604051808303818588803b158015611b8057600080fd5b505af1158015611b94573d6000803e3d6000fd5b50505050505b8015611cc2576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611bed576040519150601f19603f3d011682016040523d82523d6000602084013e611bf2565b606091505b5050905080611c435760405162461bcd60e51b815260206004820152601e60248201527f5472616e73666572206f66207072652d6465706f736974206661696c656400006044820152606401610b08565b816101126000828254611c5691906140d9565b92505081905550826001600160a01b03168d8581518110611c7957611c79614889565b6020026020010151604051611c8e919061497a565b6040519081900381209087907fa9600995f0aabc7cf77040d60ec36eb9ed073c47abfe0717fa47ca4c3df692a590600090a4505b8b8381518110611cd457611cd4614889565b6020026020010151604051611ce9919061497a565b6040518091039020847f3424df4338b4478ef58d99493e4ed96927ec2c63beec8d9de1d410a8b351acf18b8681518110611d2557611d25614889565b6020026020010151604051611d3c91815260200190565b60405180910390a350508080611d519061489f565b915050611723565b5060ff55611e6c565b81158015611d705750600081115b15611e6c576000838152610107602052604090205415611dd25760405162461bcd60e51b815260206004820152601760248201527f426174636820616c7265616479207265717565737465640000000000000000006044820152606401610b08565b806101006000828254611de591906147aa565b909155505060008381526101076020526040808220839055610108805460018101825592527f8543e9adbfbe1f62b7411fdf032fcfea758a7d6b332f64d971a1334c2ff364dd9091018490555183907f210405eb88ac7589aa9de0a6e36b9c9d3cd6e4061b74363d250a77afe3c6efb790611e639084815260200190565b60405180910390a25b60019350505050611e7d600160c955565b949350505050565b6001600160a01b037f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f163003611ecd5760405162461bcd60e51b8152600401610b08906147f1565b7f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f6001600160a01b0316611eff612be4565b6001600160a01b031614611f255760405162461bcd60e51b8152600401610b089061483d565b611f2e82612c00565b610b7b82826001612e78565b6000306001600160a01b037f000000000000000000000000dcf7dbe6865e52409a0fa2b4b23433db2af3646f1614611fda5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610b08565b50600080516020614d9d83398151915290565b600080516020614d7d83398151915261200581612b37565b600082118015612016575060648211155b6120535760405162461bcd60e51b815260206004820152600e60248201526d496e76616c69642071756f72756d60901b6044820152606401610b08565b61010d5460408051918252602082018490527fd7916aef7cb7f069c87c44c871962132fdd6653e603c7180377b7226b1a5506d910160405180910390a15061010d55565b60006120a1612dd2565b6120a9612e18565b825184511480156120bb575081518451145b80156120c8575060008451115b61210c5760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420706172616d206c656e6774687360581b6044820152606401610b08565b835161212090670de0b6b3a764000061490d565b34146121855760405162461bcd60e51b815260206004820152602e60248201527f7072654465706f7369742076616c7565206d757374206265203120657468657260448201526d103832b9103b30b634b230ba37b960911b6064820152608401610b08565b60005b8451811015612472576101068582815181106121a6576121a6614889565b60200260200101516040516121bb919061497a565b9081526040519081900360200190205460ff161561221b5760405162461bcd60e51b815260206004820152601c60248201527f7075626c69634b657920616c72656164792072656769737465726564000000006044820152606401610b08565b60006001600160a01b031661011186838151811061223b5761223b614889565b6020026020010151604051612250919061497a565b908152604051908190036020019020546001600160a01b0316146122b65760405162461bcd60e51b815260206004820152601f60248201527f7075626c69634b657920616c7265616479207072652d6465706f7369746564006044820152606401610b08565b60fd5485516001600160a01b0390911690632289511890670de0b6b3a7640000908890859081106122e9576122e9614889565b6020026020010151600160f81b600060a81b3060405160200161230e93929190614aa3565b60405160208183030381529060405288868151811061232f5761232f614889565b602002602001015188878151811061234957612349614889565b60200260200101516040518663ffffffff1660e01b81526004016123709493929190614ae1565b6000604051808303818588803b15801561238957600080fd5b505af115801561239d573d6000803e3d6000fd5b5050505050336101118683815181106123b8576123b8614889565b60200260200101516040516123cd919061497a565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550336001600160a01b031685828151811061241b5761241b614889565b6020026020010151604051612430919061497a565b604051908190038120907f306a11966d026aa41af5f696c416464d527e1b8539d6b1db76a5a3298703720e90600090a38061246a8161489f565b915050612188565b5034610112600082825461248691906147aa565b909155506001915050612499600160c955565b9392505050565b600080516020614d7d8339815191526124b881612b37565b826124fb5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840d8d2e6e840d8cadccee8d606b1b6044820152606401610b08565b60005b8381101561095d57600085858381811061251a5761251a614889565b905060200201602081019061252f919061411a565b6001600160a01b0316036125745760405162461bcd60e51b815260206004820152600c60248201526b5a65726f204164647265737360a01b6044820152606401610b08565b8261010a600087878581811061258c5761258c614889565b90506020020160208101906125a1919061411a565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558215158585838181106125de576125de614889565b90506020020160208101906125f3919061411a565b6001600160a01b03167fdf67d94eba45581175e628d76b5e5058cf811bb243dfa6627fd46b8465234e6260405160405180910390a3806126328161489f565b9150506124fe565b7f70afc91226fba57efa6b459a2add00f29a9a7961e6eb3103074a44780ab8cdc861266481612b37565b61266c612dd2565b610e78612fe3565b600080516020614d7d83398151915261268c81612b37565b6001600160a01b0382166126d95760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103737b232a7b832b930ba37b960611b6044820152606401610b08565b61010e80546001600160a01b0319166001600160a01b0384169081179091556040517f826392384452e326ae3357d613e8f331be7a57fc88379826286d982f1261b46d90600090a25050565b61272d612dd2565b612735612e18565b61010554891161277e5760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964207265706f727420626c6f636b60601b6044820152606401610b08565b60ff548811156127d05760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642076616c696461746f7273436f756e740000000000000000006044820152606401610b08565b60ff5486111580156127e55750610101548610155b6128315760405162461bcd60e51b815260206004820152601860248201527f496e76616c69642076616c696461746f727345786974656400000000000000006044820152606401610b08565b61010d548110156128845760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964207369676e617475726573206c656e677468000000000000006044820152606401610b08565b60fc546001600160a01b03166128cf5760405162461bcd60e51b815260206004820152601060248201526f10db185e5b585a5b881b9bdd081cd95d60821b6044820152606401610b08565b6040805160208082018c90528183018b9052606082018a90526080820189905260a0820188905285151560f81b60c0830152825160a181840301815260c1830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060e184015260fd808401919091528351808403909101815261011d909201909252805191012060005b82811015612a1e576129cc8b8386868581811061298057612980614889565b90506020028101906129929190614b2c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061302092505050565b612a0c5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964205369676e617475726560781b6044820152606401610b08565b80612a168161489f565b915050612961565b50612a2e8a8a8a8a8a8a8a6130d2565b50612a39600160c955565b505050505050505050565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1612a6e81612b37565b6001600160a01b038216612ab75760405162461bcd60e51b815260206004820152601060248201526f24b73b30b634b21021b630bca6b0b4b760811b6044820152606401610b08565b60fc80546001600160a01b0319166001600160a01b0384169081179091556040517f104a66f1cbeb1a854e33542efdf4cab6dd7bd309067e996a7c9cd2bb5c082b8390600090a25050565b60006801bc16d674ec800000610101546101025460ff54612b2391906140d9565b612b2d91906140d9565b6108db919061490d565b60fb546040516312d9a6ad60e01b8152600481018390523360248201526001600160a01b03909116906312d9a6ad90604401602060405180830381865afa158015612b86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612baa9190614924565b610e785760405162461bcd60e51b815260206004820152600b60248201526a105d5d1a0811985a5b195960aa1b6044820152606401610b08565b600080516020614d9d833981519152546001600160a01b031690565b7fb8ea7c31de614c54f5b3938aa9732e87deb869a880ec52d4bb778c09789441b1612c2a81612b37565b6000826001600160a01b03163b11610b7b5760405162461bcd60e51b81526020600482015260096024820152680858dbdb9d1c9858dd60ba1b6044820152606401610b08565b612c7981613688565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60975460ff16612cf95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b08565b565b612d03612cb0565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600054610100900460ff16612d745760405162461bcd60e51b8152600401610b0890614b72565b612cf9613724565b600054610100900460ff16612da35760405162461bcd60e51b8152600401610b0890614b72565b612cf9613757565b600054610100900460ff16612cf95760405162461bcd60e51b8152600401610b0890614b72565b60975460ff1615612cf95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b08565b600260c95403612e6a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b08565b600260c955565b600160c955565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612eab576114db83613688565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612f05575060408051601f3d908101601f19168201909252612f0291810190614bbd565b60015b612f685760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610b08565b600080516020614d9d8339815191528114612fd75760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610b08565b506114db83838361377e565b612feb612dd2565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612d303390565b60008061302d84846137a9565b6001600160a01b038116600090815261010a602052604090205490915060ff1661305b576000915050612499565b6001600160a01b038116600090815261010c60205260409020548511613085576000915050612499565b6001600160a01b038116600081815261010c60205260408082208890555187917e4a0156b3be77c48016f4bd6f1dcb3d729680a091d3889629370a973475d75d91a3506001949350505050565b610113546001600160a01b0316156131ea5781156130f3576130f382610902565b60006130fe846137cf565b6101145460405163ecb7cb1b60e01b81523060048201529192506000916001600160a01b039091169063ecb7cb1b90602401600060405180830381865afa15801561314d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131759190810190614bd6565b905060008082600001511161318b5760006131b1565b6101166000600184600001516131a191906140d9565b8152602001908152602001600020545b905060006131bf82886140d9565b90506131cb848a6147aa565b98506131d7818b6147aa565b99506131e381896140d9565b9750505050505b60006131ff6801bc16d674ec8000008861490d565b861161320c576000613229565b61321f6801bc16d674ec8000008861490d565b61322990876140d9565b61010454610101549192509060009061324290886140d9565b6101058b90556101028a905561010389905561010188905561010484905560fc54604080516344573f9760e11b81529051929350861515926001600160a01b03909216916388ae7f2e916004818101926020929091908290030181865afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d59190614924565b15151461333c5760fc54604051630a54644f60e21b815285151560048201526001600160a01b0390911690632951913c90602401600060405180830381600087803b15801561332357600080fd5b505af1158015613337573d6000803e3d6000fd5b505050505b61010e546001600160a01b03161561336f5761271061010f5484613360919061490d565b61336a91906148ce565b610110555b4780156135bb5760006133948261338f6801bc16d674ec8000008661490d565b613ab2565b905060006133a282846140d9565b905060006133b082886147aa565b905060006133be8288613ac7565b905060006133cc8483613ab2565b90506000841180156133e9575061010e546001600160a01b031615155b156134fd57600061271061010f5486613402919061490d565b61340c91906148ce565b9050600061271061010f5484613422919061490d565b61342c91906148ce565b905061343882876140d9565b955061344482896140d9565b975061345081846140d9565b61010e546040519194506000916001600160a01b039091169084908381818185875af1925050503d80600081146134a3576040519150601f19603f3d011682016040523d82523d6000602084013e6134a8565b606091505b50509050806134f95760405162461bcd60e51b815260206004820152601f60248201527f5472616e73666572206f66206e6f64652072657761726473206661696c6564006044820152606401610b08565b5050505b60fc5460405163070f0b8960e21b815260048101839052602481018790526001600160a01b0390911690631c3c2e249088906044016000604051808303818588803b15801561354b57600080fd5b505af115801561355f573d6000803e3d6000fd5b50505050508f7f1947dd35f2ad7cfad67d80241fe2f032f18b67bf60792d5f9132dac5817527cb8287896040516135a9939291909283526020830191909152604082015260600190565b60405180910390a25050505050613624565b60fc60009054906101000a90046001600160a01b03166001600160a01b0316636f3fe4046040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561360b57600080fd5b505af115801561361f573d6000803e3d6000fd5b505050505b81156136335761363382613aea565b604080518c8152602081018c90529081018a9052606081018990527f7a4a8ff550d096ae3e71e1c79680b17560ea3076ff95d4666ab60c0ef5308a569060800160405180910390a15050505050505050505050565b6001600160a01b0381163b6136f55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610b08565b600080516020614d9d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1661374b5760405162461bcd60e51b8152600401610b0890614b72565b6097805460ff19169055565b600054610100900460ff16612e715760405162461bcd60e51b8152600401610b0890614b72565b61378783612c70565b6000825111806137945750805b156114db576137a38383613c92565b50505050565b60008060006137b88585613d7d565b915091506137c581613dc2565b5090505b92915050565b6101135460405163a38406a360e01b815230600482015260009182916001600160a01b039091169063a38406a390602401602060405180830381865afa15801561381d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138419190614cf2565b90506001600160a01b038116318015613aa6576000826001600160a01b0316633106ab536040518163ffffffff1660e01b8152600401602060405180830381865afa158015613894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b89190614924565b158015613930575061011454604051635ac86ab760e01b8152600060048201526001600160a01b0390911690635ac86ab790602401602060405180830381865afa15801561390a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392e9190614924565b155b90508015613a8e5781610115600082825461394b91906147aa565b92505081905550826001600160a01b031663baa7145a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561398d57600080fd5b505af11580156139a1573d6000803e3d6000fd5b50506101145460405163ecb7cb1b60e01b8152306004820152600093506001600160a01b03909116915063ecb7cb1b90602401600060405180830381865afa1580156139f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a199190810190614bd6565b90508561011660006001846020015151613a3391906140d9565b8152602001908152602001600020819055506001816020015151613a5791906140d9565b6040517f6ae853a67b9b71d5e6454259a07b6b7fcf4b2c78c0703a0ccc38834d66ed952990600090a2505061011554949350505050565b8161011554613a9d91906147aa565b95945050505050565b50506101155492915050565b6000818311613ac15782612499565b50919050565b600081831015613ad9575060006137c9565b613ae382846140d9565b90506137c9565b610109546000905b61010854811015613ba15760006101088281548110613b1357613b13614889565b6000918252602080832090910154808352610107909152604090912054909150848111613b595783613b448161489f565b9450613b52905081866140d9565b9450613b7d565b613b6385826140d9565b600092835261010760205260409092209190915550613ba1565b60008511613b8c575050613ba1565b50508080613b999061489f565b915050613af2565b506000816001600160401b03811115613bbc57613bbc614325565b604051908082528060200260200182016040528015613be5578160200160208202803683370190505b50905060005b82811015613c2a57613bfb613f0c565b828281518110613c0d57613c0d614889565b602090810291909101015280613c228161489f565b915050613beb565b5060fc546040516370e301fb60e11b81526001600160a01b039091169063e1c603f690613c5b908490600401614d0f565b600060405180830381600087803b158015613c7557600080fd5b505af1158015613c89573d6000803e3d6000fd5b50505050505050565b60606001600160a01b0383163b613cfa5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610b08565b600080846001600160a01b031684604051613d15919061497a565b600060405180830381855af49150503d8060008114613d50576040519150601f19603f3d011682016040523d82523d6000602084013e613d55565b606091505b5091509150613a9d8282604051806060016040528060278152602001614dbd60279139613fbc565b6000808251604103613db35760208301516040840151606085015160001a613da787828585613fd5565b94509450505050613dbb565b506000905060025b9250929050565b6000816004811115613dd657613dd6614d53565b03613dde5750565b6001816004811115613df257613df2614d53565b03613e3f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b08565b6002816004811115613e5357613e53614d53565b03613ea05760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b08565b6003816004811115613eb457613eb4614d53565b03610e785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b08565b610109546101085460009110613f555760405162461bcd60e51b815260206004820152600e60248201526d517565756520697320656d70747960901b6044820152606401610b08565b6101086101095481548110613f6c57613f6c614889565b906000526020600020015490506101086101095481548110613f9057613f90614889565b906000526020600020016000905560016101096000828254613fb291906147aa565b9250508190555090565b60608315613fcb575081612499565b6124998383614099565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561400c5750600090506003614090565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614060573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661408957600060019250925050614090565b9150600090505b94509492505050565b8151156140a95781518083602001fd5b8060405162461bcd60e51b8152600401610b089190614d69565b634e487b7160e01b600052601160045260246000fd5b818103818111156137c9576137c96140c3565b6000602082840312156140fe57600080fd5b5035919050565b6001600160a01b0381168114610e7857600080fd5b60006020828403121561412c57600080fd5b813561249981614105565b60005b8381101561415257818101518382015260200161413a565b50506000910152565b60008151808452614173816020860160208601614137565b601f01601f19169290920160200192915050565b60608152600061419a606083018661415b565b82810360208401526141ac818661415b565b915050826040830152949350505050565b600080604083850312156141d057600080fd5b82356141db81614105565b915060208301356141eb81614105565b809150509250929050565b60008083601f84011261420857600080fd5b5081356001600160401b0381111561421f57600080fd5b6020830191508360208260051b8501011115613dbb57600080fd5b8015158114610e7857600080fd5b60008060006040848603121561425d57600080fd5b83356001600160401b0381111561427357600080fd5b61427f868287016141f6565b90945092505060208401356142938161423a565b809150509250925092565b60006040808301818452808651808352606092508286019150828160051b8701016020808a0160005b8481101561431057605f198a85030186528151805185528381015188858701526142f38987018261415b565b918a0151958a0195909552958301959350908201906001016142c7565b50509690960196909652509295945050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561435d5761435d614325565b60405290565b604051601f8201601f191681016001600160401b038111828210171561438b5761438b614325565b604052919050565b60006001600160401b038211156143ac576143ac614325565b5060051b60200190565b600082601f8301126143c757600080fd5b81356001600160401b038111156143e0576143e0614325565b6143f3601f8201601f1916602001614363565b81815284602083860101111561440857600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261443657600080fd5b8135602061444b61444683614393565b614363565b82815260059290921b8401810191818101908684111561446a57600080fd5b8286015b848110156144a95780356001600160401b0381111561448d5760008081fd5b61449b8986838b01016143b6565b84525091830191830161446e565b509695505050505050565b600082601f8301126144c557600080fd5b813560206144d561444683614393565b82815260059290921b840181019181810190868411156144f457600080fd5b8286015b848110156144a957803583529183019183016144f8565b6000806000806080858703121561452557600080fd5b84356001600160401b038082111561453c57600080fd5b61454888838901614425565b955060209150818701358181111561455f57600080fd5b61456b89828a01614425565b95505060408701358181111561458057600080fd5b61458c89828a016144b4565b9450506060870135818111156145a157600080fd5b87019050601f810188136145b457600080fd5b80356145c261444682614393565b81815260059190911b8201830190838101908a8311156145e157600080fd5b928401925b828410156145ff578335825292840192908401906145e6565b979a9699509497505050505050565b6000806040838503121561462157600080fd5b823561462c81614105565b915060208301356001600160401b0381111561464757600080fd5b614653858286016143b6565b9150509250929050565b60006020828403121561466f57600080fd5b81356001600160401b0381111561468557600080fd5b611e7d848285016143b6565b6000806000606084860312156146a657600080fd5b83356001600160401b03808211156146bd57600080fd5b6146c987838801614425565b945060208601359150808211156146df57600080fd5b6146eb87838801614425565b9350604086013591508082111561470157600080fd5b5061470e868287016144b4565b9150509250925092565b60008060008060008060008060006101008a8c03121561473757600080fd5b8935985060208a0135975060408a0135965060608a0135955060808a0135945060a08a0135935060c08a013561476c8161423a565b925060e08a01356001600160401b0381111561478757600080fd5b6147938c828d016141f6565b915080935050809150509295985092959850929598565b808201808211156137c9576137c96140c3565b600181811c908216806147d157607f821691505b602082108103613ac157634e487b7160e01b600052602260045260246000fd5b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600182016148b1576148b16140c3565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826148dd576148dd6148b8565b500490565b6000826148f1576148f16148b8565b500690565b600081614905576149056140c3565b506000190190565b80820281158282048414176137c9576137c96140c3565b60006020828403121561493657600080fd5b81516124998161423a565b60008060006060848603121561495657600080fd5b8351925060208401516149688161423a565b80925050604084015190509250925092565b6000825161498c818460208701614137565b9190910192915050565b601f8211156114db57600081815260208120601f850160051c810160208610156149bd5750805b601f850160051c820191505b818110156149dc578281556001016149c9565b505050505050565b81516001600160401b038111156149fd576149fd614325565b614a1181614a0b84546147bd565b84614996565b602080601f831160018114614a465760008415614a2e5750858301515b600019600386901b1c1916600185901b1785556149dc565b600085815260208120601f198616915b82811015614a7557888601518255948401946001909101908401614a56565b5085821015614a935787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160f81b03199390931683526001600160a81b031991909116600183015260601b6bffffffffffffffffffffffff1916600c82015260200190565b608081526000614af4608083018761415b565b8281036020840152614b06818761415b565b90508281036040840152614b1a818661415b565b91505082606083015295945050505050565b6000808335601e19843603018112614b4357600080fd5b8301803591506001600160401b03821115614b5d57600080fd5b602001915036819003821315613dbb57600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215614bcf57600080fd5b5051919050565b60006020808385031215614be957600080fd5b82516001600160401b0380821115614c0057600080fd5b81850191506040808388031215614c1657600080fd5b614c1e61433b565b835181528484015183811115614c3357600080fd5b80850194505087601f850112614c4857600080fd5b83519250614c5861444684614393565b83815260069390931b84018501928581019089851115614c7757600080fd5b948601945b84861015614ce05783868b031215614c945760008081fd5b614c9c61433b565b86516001600160e01b0381168114614cb45760008081fd5b81528688015163ffffffff81168114614ccd5760008081fd5b8189015282529483019490860190614c7c565b95820195909552979650505050505050565b600060208284031215614d0457600080fd5b815161249981614105565b6020808252825182820181905260009190848201906040850190845b81811015614d4757835183529284019291840191600101614d2b565b50909695505050505050565b634e487b7160e01b600052602160045260246000fd5b602081526000612499602083018461415b56fef66846415d2bf9eabda9e84793ff9c0ea96d87f50fc41e66aa16469c6a442f05360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202d5aeadc3340defc038b9c71a09d61a2ccd715d6fd8efadaaeb86875e6ee919464736f6c63430008120033
Deployed Bytecode Sourcemap
166497:28711:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;189921:28;;-1:-1:-1;;;;;189921:28:0;189899:10;:51;189896:164;;189990:9;189967:19;;:32;;;;;;;:::i;:::-;;;;-1:-1:-1;;190019:29:0;;190038:9;425:25:1;;190019:29:0;;413:2:1;398:18;190019:29:0;;;;;;;189896:164;166497:28711;;;;;169260:27;;;;;;;;;;-1:-1:-1;169260:27:0;;;;-1:-1:-1;;;;;169260:27:0;;;;;;-1:-1:-1;;;;;625:32:1;;;607:51;;595:2;580:18;169260:27:0;;;;;;;;190184:151;;;;;;;;;;;;;:::i;:::-;;;425:25:1;;;413:2;398:18;190184:151:0;279:177:1;168646:31:0;;;;;;;;;;-1:-1:-1;168646:31:0;;;;;:::i;:::-;;:::i;189571:173::-;;;;;;;;;;-1:-1:-1;189571:173:0;;;;;:::i;:::-;;:::i;168929:52::-;;;;;;;;;;-1:-1:-1;168929:52:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1407:14:1;;1400:22;1382:41;;1370:2;1355:18;168929:52:0;1242:187:1;167591:47:0;;;;;;;;;;-1:-1:-1;167591:47:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;194587:229::-;;;;;;;;;;-1:-1:-1;194587:229:0;;;;;:::i;:::-;;:::i;167864:31::-;;;;;;;;;;;;;;;;187621:554;;;;;;;;;;-1:-1:-1;187621:554:0;;;;;:::i;:::-;;:::i;191878:414::-;;;;;;;;;;-1:-1:-1;191878:414:0;;;;;:::i;:::-;;:::i;194057:94::-;;;;;;;;;;;;;:::i;176685:158::-;;;;;;;;;;;;;:::i;192392:262::-;;;;;;;;;;-1:-1:-1;192392:262:0;;;;;:::i;:::-;;:::i;177153:925::-;;;;;;;;;;-1:-1:-1;177153:925:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;168288:32::-;;;;;;;;;;;;;;;;170531:512;;;;;;;;;;-1:-1:-1;170531:512:0;;;;;:::i;:::-;;:::i;173421:3199::-;;;;;;;;;;-1:-1:-1;173421:3199:0;;;;;:::i;:::-;;:::i;30848:225::-;;;;;;:::i;:::-;;:::i;168397:49::-;;;;;;;;;;-1:-1:-1;168397:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30067:133;;;;;;;;;;;;;:::i;169059:46::-;;;;;;;;;;-1:-1:-1;169059:46:0;;;;;:::i;:::-;;;;;;;;;;;;;;34926:86;;;;;;;;;;-1:-1:-1;34997:7:0;;;;34926:86;;190766:255;;;;;;;;;;-1:-1:-1;190766:255:0;;;;;:::i;:::-;;:::i;169432:38::-;;;;;;;;;;;;;;;;171564:1275;;;;;;:::i;:::-;;:::i;169519:48::-;;;;;;;;;;-1:-1:-1;169519:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;169519:48:0;;;169182:27;;;;;;;;;;;;;;;;191298:399;;;;;;;;;;-1:-1:-1;191298:399:0;;;;;:::i;:::-;;:::i;193914:93::-;;;;;;;;;;;;;:::i;167778:32::-;;;;;;;;;;;;;;;;169951:34;;;;;;;;;;;;;;;;169622:32;;;;;;;;;;;;;;;;168503:52;;;;;;;;;;-1:-1:-1;168503:52:0;;;;;:::i;:::-;;;;;;;;;;;;;;193162:248;;;;;;;;;;-1:-1:-1;193162:248:0;;;;;:::i;:::-;;:::i;167405:25::-;;;;;;;;;;-1:-1:-1;167405:25:0;;;;-1:-1:-1;;;;;167405:25:0;;;168813:47;;;;;;;;;;-1:-1:-1;168813:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;170064:50;;;;;;;;;;-1:-1:-1;170064:50:0;;;;;:::i;:::-;;;;;;;;;;;;;;168206:29;;;;;;;;;;;;;;;;179029:1702;;;;;;;;;;-1:-1:-1;179029:1702:0;;;;;:::i;:::-;;:::i;192812:236::-;;;;;;;;;;-1:-1:-1;192812:236:0;;;;;:::i;:::-;;:::i;168099:38::-;;;;;;;;;;;;;;;;168722:34;;;;;;;;;;;;;;;;169332:31;;;;;;;;;;;;;;;;167978;;;;;;;;;;;;;;;;167699:29;;;;;;;;;;;;;;;;190416:154;;;;;;;;;;;;;:::i;190184:151::-;190229:7;190304:23;;190282:19;:17;:19::i;:::-;190256:23;;:45;;;;:::i;:::-;:71;;;;:::i;:::-;190249:78;;190184:151;:::o;168646:31::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;168646:31:0;:::o;189571:173::-;189653:28;;:83;;-1:-1:-1;;;189653:83:0;;;;;425:25:1;;;-1:-1:-1;;;;;189653:28:0;;;;:52;;398:18:1;;189653:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;189571:173;:::o;167591:47::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;194587:229::-;166841:35;170282:20;170292:9;170282;:20::i;:::-;-1:-1:-1;;;;;28937:6:0::1;28920:23;28928:4;28920:23:::0;28912:80:::1;;;;-1:-1:-1::0;;;28912:80:0::1;;;;;;;:::i;:::-;;;;;;;;;29035:6;-1:-1:-1::0;;;;;29011:30:0::1;:20;:18;:20::i;:::-;-1:-1:-1::0;;;;;29011:30:0::1;;29003:87;;;;-1:-1:-1::0;;;29003:87:0::1;;;;;;;:::i;:::-;194730:37:::2;194748:18;194730:17;:37::i;:::-;194778:30;194789:18;194778:10;:30::i;:::-;194587:229:::0;;:::o;187621:554::-;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;-1:-1:-1;;;;;187781:30:0;::::1;187773:66;;;::::0;-1:-1:-1;;;187773:66:0;;14230:2:1;187773:66:0::1;::::0;::::1;14212:21:1::0;14269:2;14249:18;;;14242:30;14308:25;14288:18;;;14281:53;14351:18;;187773:66:0::1;14028:347:1::0;187773:66:0::1;-1:-1:-1::0;;;;;187858:38:0;::::1;187850:82;;;::::0;-1:-1:-1;;;187850:82:0;;14582:2:1;187850:82:0::1;::::0;::::1;14564:21:1::0;14621:2;14601:18;;;14594:30;14660:33;14640:18;;;14633:61;14711:18;;187850:82:0::1;14380:355:1::0;187850:82:0::1;187945:15;:52:::0;;-1:-1:-1;;;;;;187945:52:0;;::::1;-1:-1:-1::0;;;;;187945:52:0;;::::1;::::0;;::::1;::::0;;;188008:28:::1;:81:::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;188107:60:::1;::::0;::::1;::::0;-1:-1:-1;;188107:60:0::1;187621:554:::0;;;:::o;191878:414::-;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;192001:16;191993:48:::1;;;::::0;-1:-1:-1;;;191993:48:0;;14942:2:1;191993:48:0::1;::::0;::::1;14924:21:1::0;14981:2;14961:18;;;14954:30;-1:-1:-1;;;15000:18:1;;;14993:49;15059:18;;191993:48:0::1;14740:343:1::0;191993:48:0::1;192057:9;192052:233;192072:16:::0;;::::1;192052:233;;;192138:1;192118:5:::0;;192124:1;192118:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;192118:22:0::1;::::0;192110:47:::1;;;::::0;-1:-1:-1;;;192110:47:0;;15422:2:1;192110:47:0::1;::::0;::::1;15404:21:1::0;15461:2;15441:18;;;15434:30;-1:-1:-1;;;15480:18:1;;;15473:42;15532:18;;192110:47:0::1;15220:336:1::0;192110:47:0::1;192205:5;192172:20;:30;192193:5;;192199:1;192193:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;192172:30:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;192172:30:0;:38;;-1:-1:-1;;192172:38:0::1;::::0;::::1;;::::0;;;::::1;::::0;;192230:43;::::1;;192257:5:::0;;192263:1;192257:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;192230:43:0::1;;;;;;;;;;;192090:3:::0;::::1;::::0;::::1;:::i;:::-;;;;192052:233;;194057:94:::0;166926:28;170282:20;170292:9;170282;:20::i;:::-;34790:16:::1;:14;:16::i;:::-;194133:10:::2;:8;:10::i;:::-;194057:94:::0;:::o;176685:158::-;176768:14;;;176732:4;176768:14;;;;;;;;;176756:79;;176732:4;176768:14;;;;;;;;;;;;;;;;;;;-1:-1:-1;176784:14:0;;;176796:1;176784:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;176800:16:0;;;176814:1;176800:16;;;;;;176818;;;;;;;;;176800;176756:11;:79::i;192392:262::-;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;167208:4:::1;192488:5;:31;;192480:68;;;::::0;-1:-1:-1;;;192480:68:0;;15903:2:1;192480:68:0::1;::::0;::::1;15885:21:1::0;15942:2;15922:18;;;15915:30;15981:26;15961:18;;;15954:54;16025:18;;192480:68:0::1;15701:348:1::0;192480:68:0::1;192587:16;::::0;192564:47:::1;::::0;;16228:25:1;;;16284:2;16269:18;;16262:34;;;192564:47:0::1;::::0;16201:18:1;192564:47:0::1;;;;;;;-1:-1:-1::0;192622:16:0::1;:24:::0;192392:262::o;177153:925::-;177288:23;;;177308:2;177288:23;;;;;;;;;177214:22;;177238:7;;;;177288:23;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;177288:23:0;;;;;;;;;;;;;-1:-1:-1;;177371:14:0;;177258:53;;-1:-1:-1;177341:2:0;;177322:16;177417:17;177341:2;177371:14;177417:17;:::i;:::-;177396:38;;177458:1;177449:6;:10;:36;;;;-1:-1:-1;177463:17:0;177472:8;177463:6;:17;:::i;:::-;:22;177449:36;177445:81;;;177502:12;;;;:::i;:::-;;;;177445:81;177549:10;177540:5;:19;;:34;;;;-1:-1:-1;177563:11:0;;;177540:34;177536:499;;;177596:9;177591:433;177615:8;177611:1;:12;177591:433;;;177649:13;177693:1;177674:16;177682:8;177674:5;:16;:::i;:::-;177665:25;;:6;:25;:::i;:::-;:29;;;;:::i;:::-;177649:45;;177713:26;177742:10;:17;177753:5;177742:17;;;;;;;;;;;177713:46;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;177788:180;;;;;;;;177829:5;177788:180;;;;177868:9;:19;;;177788:180;;;;177925:9;:23;;;177788:180;;;177778:4;177783:1;177778:7;;;;;;;;:::i;:::-;;;;;;:190;;;;177991:5;178000:1;177991:10;177987:21;;178003:5;;;;177987:21;177630:394;;177625:3;;;;;:::i;:::-;;;;177591:433;;;;177536:499;178053:4;;178059:10;;-1:-1:-1;177153:925:0;;-1:-1:-1;;;;177153:925:0:o;170531:512::-;16551:19;16574:13;;;;;;16573:14;;16621:34;;;;-1:-1:-1;16639:12:0;;16654:1;16639:12;;;;:16;16621:34;16620:108;;;-1:-1:-1;16700:4:0;3609:19;:23;;;16661:66;;-1:-1:-1;16710:12:0;;;;;:17;16661:66;16598:204;;;;-1:-1:-1;;;16598:204:0;;17197:2:1;16598:204:0;;;17179:21:1;17236:2;17216:18;;;17209:30;17275:34;17255:18;;;17248:62;-1:-1:-1;;;17326:18:1;;;17319:44;17380:19;;16598:204:0;16995:410:1;16598:204:0;16813:12;:16;;-1:-1:-1;;16813:16:0;16828:1;16813:16;;;16840:67;;;;16875:13;:20;;-1:-1:-1;;16875:20:0;;;;;16840:67;-1:-1:-1;;;;;28937:6:0::1;28920:23;28928:4;28920:23:::0;28912:80:::1;;;;-1:-1:-1::0;;;28912:80:0::1;;;;;;;:::i;:::-;29035:6;-1:-1:-1::0;;;;;29011:30:0::1;:20;:18;:20::i;:::-;-1:-1:-1::0;;;;;29011:30:0::1;;29003:87;;;;-1:-1:-1::0;;;29003:87:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;170649:26:0;::::2;170641:66;;;::::0;-1:-1:-1;;;170641:66:0;;17612:2:1;170641:66:0::2;::::0;::::2;17594:21:1::0;17651:2;17631:18;;;17624:30;17690:29;17670:18;;;17663:57;17737:18;;170641:66:0::2;17410:351:1::0;170641:66:0::2;-1:-1:-1::0;;;;;170726:30:0;::::2;170718:74;;;::::0;-1:-1:-1;;;170718:74:0;;17968:2:1;170718:74:0::2;::::0;::::2;17950:21:1::0;18007:2;17987:18;;;17980:30;18046:33;18026:18;;;18019:61;18097:18;;170718:74:0::2;17766:355:1::0;170718:74:0::2;170805:17;:15;:17::i;:::-;170833:24;:22;:24::i;:::-;170868;:22;:24::i;:::-;170905:11;:40:::0;;-1:-1:-1;;;;;170905:40:0;;::::2;-1:-1:-1::0;;;;;;170905:40:0;;::::2;;::::0;;;170956:15:::2;:52:::0;;;;::::2;::::0;;;::::2;::::0;;;::::2;::::0;;170905:40;171019:12:::2;:16:::0;16929:102;;;;16980:5;16964:21;;-1:-1:-1;;16964:21:0;;;17005:14;;-1:-1:-1;18278:36:1;;17005:14:0;;18266:2:1;18251:18;17005:14:0;;;;;;;16929:102;16540:498;170531:512;;:::o;173421:3199::-;173652:4;34531:19;:17;:19::i;:::-;38662:21:::1;:19;:21::i;:::-;173712:10:::2;:17;173691:10;:17;:38;:105;;;;;173771:18;:25;173750:10;:17;:46;173691:105;:168;;;;;173838:14;:21;173817:10;:17;:42;173691:168;173669:239;;;::::0;-1:-1:-1;;;173669:239:0;;18527:2:1;173669:239:0::2;::::0;::::2;18509:21:1::0;18566:2;18546:18;;;18539:30;-1:-1:-1;;;18585:18:1;;;18578:51;18646:18;;173669:239:0::2;18325:345:1::0;173669:239:0::2;173935:8;::::0;-1:-1:-1;;;;;173935:8:0::2;173919:60;;;::::0;-1:-1:-1;;;173919:60:0;;18877:2:1;173919:60:0::2;::::0;::::2;18859:21:1::0;18916:2;18896:18;;;18889:30;-1:-1:-1;;;18935:18:1;;;18928:46;18991:18;;173919:60:0::2;18675:340:1::0;173919:60:0::2;173996:17:::0;;:21;173992:213:::2;;174060:11;::::0;:50:::2;::::0;-1:-1:-1;;;174060:50:0;;166926:28:::2;174060:50;::::0;::::2;19194:25:1::0;174099:10:0::2;19235:18:1::0;;;19228:60;-1:-1:-1;;;;;174060:11:0;;::::2;::::0;:21:::2;::::0;19167:18:1;;174060:50:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:86;;;-1:-1:-1::0;174135:10:0::2;174114:32;::::0;;;:20:::2;:32;::::0;;;;;::::2;;174060:86;174034:159;;;::::0;-1:-1:-1;;;174034:159:0;;19751:2:1;174034:159:0::2;::::0;::::2;19733:21:1::0;19790:2;19770:18;;;19763:30;-1:-1:-1;;;19809:18:1;;;19802:41;19860:18;;174034:159:0::2;19549:335:1::0;174034:159:0::2;174322:8;::::0;174343:17;;174322:39:::2;::::0;-1:-1:-1;;;174322:39:0;;::::2;::::0;::::2;425:25:1::0;;;;174255:22:0::2;::::0;;;;;-1:-1:-1;;;;;174322:8:0::2;::::0;:20:::2;::::0;398:18:1;;174322:39:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174254:107;;;;;;174378:10;:32;;;;;174409:1;174392:14;:18;174378:32;174374:2217;;;174440:14;::::0;174427:10:::2;174469:1703;174493:14;174489:1;:18;174469:1703;;;174542:19;174562:10;174573:1;174562:13;;;;;;;;:::i;:::-;;;;;;;174542:34;;;;;;:::i;:::-;::::0;;;::::2;::::0;;;;;::::2;::::0;;;;::::2;;174541:35;174533:76;;;::::0;-1:-1:-1;;;174533:76:0;;20755:2:1;174533:76:0::2;::::0;::::2;20737:21:1::0;20794:2;20774:18;;;20767:30;20833;20813:18;;;20806:58;20881:18;;174533:76:0::2;20553:352:1::0;174533:76:0::2;174630:4;::::0;::::2;:::i;:::-;;;174670:58;;;;;;;;174680:10;174691:1;174680:13;;;;;;;;:::i;:::-;;;;;;;174670:58;;;;174695:10;174706:1;174695:13;;;;;;;;:::i;:::-;;;;;;;174670:58;;;;174710:14;174725:1;174710:17;;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;;;;;174670:58;;;174653:14:::2;::::0;;;:10:::2;:14:::0;;;;;;:75;;:14;;:75:::2;::::0;:14;:75:::2;:::i;:::-;-1:-1:-1::0;174653:75:0::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;:::i;:::-;;;;;;;;;;;;;174784:4;174747:19;174767:10;174778:1;174767:13;;;;;;;;:::i;:::-;;;;;;;174747:34;;;;;;:::i;:::-;;;;;;;;;;;;;;:41;;;;;;;;;;;;;;;;;;174809:30;174842:15;174858:10;174869:1;174858:13;;;;;;;;:::i;:::-;;;;;;;174842:30;;;;;;:::i;:::-;::::0;;;::::2;::::0;;;;;::::2;::::0;;;;-1:-1:-1;;;;;174842:30:0::2;::::0;-1:-1:-1;174842:30:0::2;174909:36:::0;;:59:::2;;167089:7;174909:59;;;174948:1;174909:59;174891:77;;167267:2;174991:14;175006:1;174991:17;;;;;;;;:::i;:::-;;;;;;;:41:::0;174987:697:::2;;175073:15;::::0;-1:-1:-1;;;;;175073:15:0::2;175057:74;;;::::0;-1:-1:-1;;;175057:74:0;;23310:2:1;175057:74:0::2;::::0;::::2;23292:21:1::0;23349:2;23329:18;;;23322:30;23388:25;23368:18;;;23361:53;23431:18;;175057:74:0::2;23108:347:1::0;175057:74:0::2;175162:12:::0;;175154:52:::2;;;::::0;-1:-1:-1;;;175154:52:0;;23662:2:1;175154:52:0::2;::::0;::::2;23644:21:1::0;23701:2;23681:18;;;23674:30;23740:29;23720:18;;;23713:57;23787:18;;175154:52:0::2;23460:351:1::0;175154:52:0::2;175229:15;::::0;175272:13;;-1:-1:-1;;;;;175229:15:0;;::::2;::::0;:21:::2;::::0;167030:8:::2;::::0;175272:10;;175283:1;;175272:13;::::2;;;;;:::i;:::-;;;;;;;175287:10;175298:1;175287:13;;;;;;;;:::i;:::-;;;;;;;175302:18;175321:1;175302:21;;;;;;;;:::i;:::-;;;;;;;175229:95;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;174987:697;;;175373:15;::::0;-1:-1:-1;;;;;175373:15:0::2;:23;175404:22;175419:7:::0;167030:8:::2;175404:22;:::i;:::-;175454:10;175465:1;175454:13;;;;;;;;:::i;:::-;;;;;;;175518:4;175511:12;;175533:3;175525:12;;175547:4;175494:59;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;175580:10;175591:1;175580:13;;;;;;;;:::i;:::-;;;;;;;175620:18;175639:1;175620:21;;;;;;;;:::i;:::-;;;;;;;175373:291;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;174987:697;175747:11:::0;;175743:340:::2;;175784:12;175802:22;-1:-1:-1::0;;;;;175802:27:0::2;175837:7;175802:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175783:66;;;175880:7;175872:50;;;::::0;-1:-1:-1;;;175872:50:0;;25718:2:1;175872:50:0::2;::::0;::::2;25700:21:1::0;25757:2;25737:18;;;25730:30;25796:32;25776:18;;;25769:60;25846:18;;175872:50:0::2;25516:354:1::0;175872:50:0::2;175966:7;175945:17;;:28;;;;;;;:::i;:::-;;;;;;;;176040:22;-1:-1:-1::0;;;;;176001:62:0::2;176025:10;176036:1;176025:13;;;;;;;;:::i;:::-;;;;;;;176001:62;;;;;;:::i;:::-;;::::0;;;;::::2;::::0;;;176021:2;;176001:62:::2;::::0;;;::::2;175760:323;175743:340;176123:10;176134:1;176123:13;;;;;;;;:::i;:::-;;;;;;;176108:48;;;;;;:::i;:::-;;;;;;;;176119:2;176108:48;176138:14;176153:1;176138:17;;;;;;;;:::i;:::-;;;;;;;176108:48;;;;425:25:1::0;;413:2;398:18;;279:177;176108:48:0::2;;;;;;;;174514:1658;;174509:3;;;;;:::i;:::-;;;;174469:1703;;;-1:-1:-1::0;176186:14:0::2;:19:::0;174374:2217:::2;;;176228:10;176227:11;:33;;;;;176259:1;176242:14;:18;176227:33;176223:368;;;176285:33;::::0;;;:17:::2;:33;::::0;;;;;:38;176277:74:::2;;;::::0;-1:-1:-1;;;176277:74:0;;26077:2:1;176277:74:0::2;::::0;::::2;26059:21:1::0;26116:2;26096:18;;;26089:30;26155:25;26135:18;;;26128:53;26198:18;;176277:74:0::2;25875:347:1::0;176277:74:0::2;176387:14;176366:17;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;176416:33:0::2;::::0;;;:17:::2;:33;::::0;;;;;:50;;;176481:14:::2;:35:::0;;::::2;::::0;::::2;::::0;;;;;;;::::2;::::0;;;176536:43;176434:14;;176536:43:::2;::::0;::::2;::::0;176452:14;425:25:1;;413:2;398:18;;279:177;176536:43:0::2;;;;;;;;176223:368;176608:4;176601:11;;;;;38706:20:::1;37923:1:::0;39226:7;:22;39043:213;38706:20:::1;173421:3199:::0;;;;;;:::o;30848:225::-;-1:-1:-1;;;;;28937:6:0;28920:23;28928:4;28920:23;28912:80;;;;-1:-1:-1;;;28912:80:0;;;;;;;:::i;:::-;29035:6;-1:-1:-1;;;;;29011:30:0;:20;:18;:20::i;:::-;-1:-1:-1;;;;;29011:30:0;;29003:87;;;;-1:-1:-1;;;29003:87:0;;;;;;;:::i;:::-;30966:36:::1;30984:17;30966;:36::i;:::-;31013:52;31035:17;31054:4;31060;31013:21;:52::i;30067:133::-:0;30145:7;29373:4;-1:-1:-1;;;;;29382:6:0;29365:23;;29357:92;;;;-1:-1:-1;;;29357:92:0;;26429:2:1;29357:92:0;;;26411:21:1;26468:2;26448:18;;;26441:30;26507:34;26487:18;;;26480:62;26578:26;26558:18;;;26551:54;26622:19;;29357:92:0;26227:420:1;29357:92:0;-1:-1:-1;;;;;;;;;;;;30067:133:0;:::o;190766:255::-;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;190876:1:::1;190863:10;:14;:35;;;;;190895:3;190881:10;:17;;190863:35;190855:62;;;::::0;-1:-1:-1;;;190855:62:0;;26854:2:1;190855:62:0::1;::::0;::::1;26836:21:1::0;26893:2;26873:18;;;26866:30;-1:-1:-1;;;26912:18:1;;;26905:44;26966:18;;190855:62:0::1;26652:338:1::0;190855:62:0::1;190952:12;::::0;190933:44:::1;::::0;;16228:25:1;;;16284:2;16269:18;;16262:34;;;190933:44:0::1;::::0;16201:18:1;190933:44:0::1;;;;;;;-1:-1:-1::0;190988:12:0::1;:25:::0;190766:255::o;171564:1275::-;171762:4;34531:19;:17;:19::i;:::-;38662:21:::1;:19;:21::i;:::-;171822:10:::2;:17;171801:10;:17;:38;:105;;;;;171881:18;:25;171860:10;:17;:46;171801:105;:147;;;;;171947:1;171927:10;:17;:21;171801:147;171779:218;;;::::0;-1:-1:-1;;;171779:218:0;;18527:2:1;171779:218:0::2;::::0;::::2;18509:21:1::0;18566:2;18546:18;;;18539:30;-1:-1:-1;;;18585:18:1;;;18578:51;18646:18;;171779:218:0::2;18325:345:1::0;171779:218:0::2;172048:17:::0;;172029:36:::2;::::0;167089:7:::2;172029:36;:::i;:::-;172016:9;:49;172008:108;;;::::0;-1:-1:-1;;;172008:108:0;;27197:2:1;172008:108:0::2;::::0;::::2;27179:21:1::0;27236:2;27216:18;;;27209:30;27275:34;27255:18;;;27248:62;-1:-1:-1;;;27326:18:1;;;27319:44;27380:19;;172008:108:0::2;26995:410:1::0;172008:108:0::2;172134:9;172129:636;172153:10;:17;172149:1;:21;172129:636;;;172201:19;172221:10;172232:1;172221:13;;;;;;;;:::i;:::-;;;;;;;172201:34;;;;;;:::i;:::-;::::0;;;::::2;::::0;;;;;::::2;::::0;;;;::::2;;172200:35;172192:76;;;::::0;-1:-1:-1;;;172192:76:0;;20755:2:1;172192:76:0::2;::::0;::::2;20737:21:1::0;20794:2;20774:18;;;20767:30;20833;20813:18;;;20806:58;20881:18;;172192:76:0::2;20553:352:1::0;172192:76:0::2;172333:1;-1:-1:-1::0;;;;;172291:44:0::2;:15;172307:10;172318:1;172307:13;;;;;;;;:::i;:::-;;;;;;;172291:30;;;;;;:::i;:::-;::::0;;;::::2;::::0;;;;;::::2;::::0;;;;-1:-1:-1;;;;;172291:30:0::2;:44;172283:88;;;::::0;-1:-1:-1;;;172283:88:0;;27612:2:1;172283:88:0::2;::::0;::::2;27594:21:1::0;27651:2;27631:18;;;27624:30;27690:33;27670:18;;;27663:61;27741:18;;172283:88:0::2;27410:355:1::0;172283:88:0::2;172388:15;::::0;172455:13;;-1:-1:-1;;;;;172388:15:0;;::::2;::::0;:23:::2;::::0;167089:7:::2;::::0;172455:10;;172466:1;;172455:13;::::2;;;;;:::i;:::-;;;;;;;172511:4;172504:12;;172526:3;172518:12;;172540:4;172487:59;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;172565:10;172576:1;172565:13;;;;;;;;:::i;:::-;;;;;;;172597:18;172616:1;172597:21;;;;;;;;:::i;:::-;;;;;;;172388:245;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;172683:10;172650:15;172666:10;172677:1;172666:13;;;;;;;;:::i;:::-;;;;;;;172650:30;;;;;;:::i;:::-;;;;;;;;;;;;;;:43;;;;;-1:-1:-1::0;;;;;172650:43:0::2;;;;;-1:-1:-1::0;;;;;172650:43:0::2;;;;;;172742:10;-1:-1:-1::0;;;;;172713:40:0::2;172727:10;172738:1;172727:13;;;;;;;;:::i;:::-;;;;;;;172713:40;;;;;;:::i;:::-;;::::0;;;;::::2;::::0;;;::::2;::::0;;;::::2;172172:3:::0;::::2;::::0;::::2;:::i;:::-;;;;172129:636;;;;172798:9;172777:17;;:30;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;172827:4:0::2;::::0;-1:-1:-1;;38706:20:0::1;37923:1:::0;39226:7;:22;39043:213;38706:20:::1;171564:1275:::0;;;;;:::o;191298:399::-;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;191416:16;191408:48:::1;;;::::0;-1:-1:-1;;;191408:48:0;;14942:2:1;191408:48:0::1;::::0;::::1;14924:21:1::0;14981:2;14961:18;;;14954:30;-1:-1:-1;;;15000:18:1;;;14993:49;15059:18;;191408:48:0::1;14740:343:1::0;191408:48:0::1;191472:9;191467:223;191487:16:::0;;::::1;191467:223;;;191553:1;191533:5:::0;;191539:1;191533:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;191533:22:0::1;::::0;191525:47:::1;;;::::0;-1:-1:-1;;;191525:47:0;;15422:2:1;191525:47:0::1;::::0;::::1;15404:21:1::0;15461:2;15441:18;;;15434:30;-1:-1:-1;;;15480:18:1;;;15473:42;15532:18;;191525:47:0::1;15220:336:1::0;191525:47:0::1;191615:5;191587:15;:25;191603:5;;191609:1;191603:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;191587:25:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;191587:25:0;:33;;-1:-1:-1;;191587:33:0::1;::::0;::::1;;::::0;;;::::1;::::0;;191640:38;::::1;;191662:5:::0;;191668:1;191662:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;191640:38:0::1;;;;;;;;;;;191505:3:::0;::::1;::::0;::::1;:::i;:::-;;;;191467:223;;193914:93:::0;166926:28;170282:20;170292:9;170282;:20::i;:::-;34531:19:::1;:17;:19::i;:::-;193991:8:::2;:6;:8::i;193162:248::-:0;-1:-1:-1;;;;;;;;;;;170282:20:0;170292:9;170282;:20::i;:::-;-1:-1:-1;;;;;193262:27:0;::::1;193254:60;;;::::0;-1:-1:-1;;;193254:60:0;;27972:2:1;193254:60:0::1;::::0;::::1;27954:21:1::0;28011:2;27991:18;;;27984:30;-1:-1:-1;;;28030:18:1;;;28023:50;28090:18;;193254:60:0::1;27770:344:1::0;193254:60:0::1;193325:12;:28:::0;;-1:-1:-1;;;;;;193325:28:0::1;-1:-1:-1::0;;;;;193325:28:0;::::1;::::0;;::::1;::::0;;;193369:33:::1;::::0;::::1;::::0;-1:-1:-1;;193369:33:0::1;193162:248:::0;;:::o;179029:1702::-;34531:19;:17;:19::i;:::-;38662:21:::1;:19;:21::i;:::-;179437:17:::2;;179422:12;:32;179414:65;;;::::0;-1:-1:-1;;;179414:65:0;;28321:2:1;179414:65:0::2;::::0;::::2;28303:21:1::0;28360:2;28340:18;;;28333:30;-1:-1:-1;;;28379:18:1;;;28372:50;28439:18;;179414:65:0::2;28119:344:1::0;179414:65:0::2;179518:14;;179498:16;:34;;179490:70;;;::::0;-1:-1:-1;;;179490:70:0;;28670:2:1;179490:70:0::2;::::0;::::2;28652:21:1::0;28709:2;28689:18;;;28682:30;28748:25;28728:18;;;28721:53;28791:18;;179490:70:0::2;28468:347:1::0;179490:70:0::2;179614:14;;179593:17;:35;;:76;;;;;179653:16;;179632:17;:37;;179593:76;179571:150;;;::::0;-1:-1:-1;;;179571:150:0;;29022:2:1;179571:150:0::2;::::0;::::2;29004:21:1::0;29061:2;29041:18;;;29034:30;29100:26;29080:18;;;29073:54;29144:18;;179571:150:0::2;28820:348:1::0;179571:150:0::2;179762:12;::::0;179740:34;::::2;;179732:72;;;::::0;-1:-1:-1;;;179732:72:0;;29375:2:1;179732:72:0::2;::::0;::::2;29357:21:1::0;29414:2;29394:18;;;29387:30;29453:27;29433:18;;;29426:55;29498:18;;179732:72:0::2;29173:349:1::0;179732:72:0::2;179831:8;::::0;-1:-1:-1;;;;;179831:8:0::2;179815:60;;;::::0;-1:-1:-1;;;179815:60:0;;18877:2:1;179815:60:0::2;::::0;::::2;18859:21:1::0;18916:2;18896:18;;;18889:30;-1:-1:-1;;;18935:18:1;;;18928:46;18991:18;;179815:60:0::2;18675:340:1::0;179815:60:0::2;179974:255;::::0;;::::2;::::0;;::::2;29790:19:1::0;;;29825:12;;;29818:28;;;29862:12;;;29855:28;;;29899:12;;;29892:28;;;29936:13;;;29929:29;;;30005:14;;29998:22;29993:3;29989:32;29974:13;;;29967:55;179974:255:0;;;;;;;;;30038:13:1;;;179974:255:0;;179950:290;;;;::::2;::::0;34338:66:1;62197:58:0;;;34326:79:1;34421:12;;;;34414:28;;;;62197:58:0;;;;;;;;;;34458:12:1;;;;62197:58:0;;;62187:69;;;;;180281:9:::2;180276:166;180296:22:::0;;::::2;180276:166;;;180348:60;180367:12;180381:10;180393:11;;180405:1;180393:14;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;180348:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;180348:18:0::2;::::0;-1:-1:-1;;;180348:60:0:i:2;:::-;180340:90;;;::::0;-1:-1:-1;;;180340:90:0;;30790:2:1;180340:90:0::2;::::0;::::2;30772:21:1::0;30829:2;30809:18;;;30802:30;-1:-1:-1;;;30848:18:1;;;30841:47;30905:18;;180340:90:0::2;30588:341:1::0;180340:90:0::2;180320:3:::0;::::2;::::0;::::2;:::i;:::-;;;;180276:166;;;;180454:269;180482:12;180509:16;180540:18;180573:17;180605:27;180647:30;180692:20;180454:13;:269::i;:::-;179403:1328;38706:20:::1;37923:1:::0;39226:7;:22;39043:213;38706:20:::1;179029:1702:::0;;;;;;;;;:::o;192812:236::-;166841:35;170282:20;170292:9;170282;:20::i;:::-;-1:-1:-1;;;;;192913:23:0;::::1;192905:52;;;::::0;-1:-1:-1;;;192905:52:0;;31136:2:1;192905:52:0::1;::::0;::::1;31118:21:1::0;31175:2;31155:18;;;31148:30;-1:-1:-1;;;31194:18:1;;;31187:46;31250:18;;192905:52:0::1;30934:340:1::0;192905:52:0::1;192968:8;:31:::0;;-1:-1:-1;;;;;;192968:31:0::1;-1:-1:-1::0;;;;;192968:31:0;::::1;::::0;;::::1;::::0;;;193015:25:::1;::::0;::::1;::::0;-1:-1:-1;;193015:25:0::1;192812:236:::0;;:::o;190416:154::-;190466:7;167030:8;190530:16;;190511;;190494:14;;:33;;;;:::i;:::-;:52;;;;:::i;:::-;190493:69;;;;:::i;194275:139::-;194346:11;;:44;;-1:-1:-1;;;194346:44:0;;;;;19194:25:1;;;194379:10:0;19235:18:1;;;19228:60;-1:-1:-1;;;;;194346:11:0;;;;:21;;19167:18:1;;194346:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;194338:68;;;;-1:-1:-1;;;194338:68:0;;19751:2:1;194338:68:0;;;19733:21:1;19790:2;19770:18;;;19763:30;-1:-1:-1;;;19809:18:1;;;19802:41;19860:18;;194338:68:0;19549:335:1;21108:153:0;-1:-1:-1;;;;;;;;;;;21188:65:0;-1:-1:-1;;;;;21188:65:0;;21108:153::o;195016:189::-;166841:35;170282:20;170292:9;170282;:20::i;:::-;195182:1:::1;195149:18;-1:-1:-1::0;;;;;195149:30:0::1;;:34;195141:56;;;::::0;-1:-1:-1;;;195141:56:0;;31481:2:1;195141:56:0::1;::::0;::::1;31463:21:1::0;31520:1;31500:18;;;31493:29;-1:-1:-1;;;31538:18:1;;;31531:39;31587:18;;195141:56:0::1;31279:332:1::0;21754:155:0;21821:37;21840:17;21821:18;:37::i;:::-;21874:27;;-1:-1:-1;;;;;21874:27:0;;;;;;;;21754:155;:::o;35270:108::-;34997:7;;;;35329:41;;;;-1:-1:-1;;;35329:41:0;;31818:2:1;35329:41:0;;;31800:21:1;31857:2;31837:18;;;31830:30;-1:-1:-1;;;31876:18:1;;;31869:50;31936:18;;35329:41:0;31616:344:1;35329:41:0;35270:108::o;35781:120::-;34790:16;:14;:16::i;:::-;35840:7:::1;:15:::0;;-1:-1:-1;;35840:15:0::1;::::0;;35871:22:::1;32792:10:::0;35880:12:::1;35871:22;::::0;-1:-1:-1;;;;;625:32:1;;;607:51;;595:2;580:18;35871:22:0::1;;;;;;;35781:120::o:0;34096:99::-;18694:13;;;;;;;18686:69;;;;-1:-1:-1;;;18686:69:0;;;;;;;:::i;:::-;34160:27:::1;:25;:27::i;38009:113::-:0;18694:13;;;;;;;18686:69;;;;-1:-1:-1;;;18686:69:0;;;;;;;:::i;:::-;38080:34:::1;:32;:34::i;28065:68::-:0;18694:13;;;;;;;18686:69;;;;-1:-1:-1;;;18686:69:0;;;;;;;:::i;35085:108::-;34997:7;;;;35155:9;35147:38;;;;-1:-1:-1;;;35147:38:0;;32579:2:1;35147:38:0;;;32561:21:1;32618:2;32598:18;;;32591:30;-1:-1:-1;;;32637:18:1;;;32630:46;32693:18;;35147:38:0;32377:340:1;38742:293:0;37967:1;38876:7;;:19;38868:63;;;;-1:-1:-1;;;38868:63:0;;32924:2:1;38868:63:0;;;32906:21:1;32963:2;32943:18;;;32936:30;33002:33;32982:18;;;32975:61;33053:18;;38868:63:0;32722:355:1;38868:63:0;37967:1;39009:7;:18;38742:293::o;39043:213::-;37923:1;39226:7;:22;39043:213::o;22526:992::-;20610:66;22980:59;;;22976:535;;;23056:37;23075:17;23056:18;:37::i;22976:535::-;23159:17;-1:-1:-1;;;;;23130:61:0;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;23130:63:0;;;;;;;;-1:-1:-1;;23130:63:0;;;;;;;;;;;;:::i;:::-;;;23126:306;;23360:56;;-1:-1:-1;;;23360:56:0;;33473:2:1;23360:56:0;;;33455:21:1;33512:2;33492:18;;;33485:30;33551:34;33531:18;;;33524:62;-1:-1:-1;;;33602:18:1;;;33595:44;33656:19;;23360:56:0;33271:410:1;23126:306:0;-1:-1:-1;;;;;;;;;;;23244:28:0;;23236:82;;;;-1:-1:-1;;;23236:82:0;;33888:2:1;23236:82:0;;;33870:21:1;33927:2;33907:18;;;33900:30;33966:34;33946:18;;;33939:62;-1:-1:-1;;;34017:18:1;;;34010:39;34066:19;;23236:82:0;33686:405:1;23236:82:0;23194:140;23446:53;23464:17;23483:4;23489:9;23446:17;:53::i;35522:118::-;34531:19;:17;:19::i;:::-;35582:7:::1;:14:::0;;-1:-1:-1;;35582:14:0::1;35592:4;35582:14;::::0;;35612:20:::1;35619:12;32792:10:::0;;32712:98;185280:544;185428:4;;185462:31;:11;185482:10;185462:19;:31::i;:::-;-1:-1:-1;;;;;185546:23:0;;;;;;:15;:23;;;;;;185445:48;;-1:-1:-1;185546:23:0;;185541:42;;185578:5;185571:12;;;;;185541:42;-1:-1:-1;;;;;185645:19:0;;;;;;:11;:19;;;;;;:35;-1:-1:-1;185641:53:0;;185689:5;185682:12;;;;;185641:53;-1:-1:-1;;;;;185707:19:0;;;;;;:11;:19;;;;;;:34;;;185757:35;185729:12;;185757:35;;;-1:-1:-1;185812:4:0;;185280:544;-1:-1:-1;;;;185280:544:0:o;180800:4167::-;181167:15;;-1:-1:-1;;;;;181167:15:0;181159:38;181155:1110;;181240:34;;181236:122;;181295:47;181311:30;181295:15;:47::i;:::-;181421:25;181449:53;181474:27;181449:24;:53::i;:::-;181582:28;;:91;;-1:-1:-1;;;181582:91:0;;181653:4;181582:91;;;607:51:1;181421:81:0;;-1:-1:-1;181519:60:0;;-1:-1:-1;;;;;181582:28:0;;;;:44;;580:18:1;;181582:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;181582:91:0;;;;;;;;;;;;:::i;:::-;181519:154;;181688:25;181752:1;181716:5;:33;;;:37;:132;;181847:1;181716:132;;;181773:15;:54;181825:1;181789:5;:33;;;:37;;;;:::i;:::-;181773:54;;;;;;;;;;;;181716:132;181688:160;-1:-1:-1;181863:31:0;181897:47;181688:160;181897:27;:47;:::i;:::-;181863:81;-1:-1:-1;182078:39:0;182100:17;182078:39;;:::i;:::-;;-1:-1:-1;182132:43:0;182152:23;182132:43;;:::i;:::-;;-1:-1:-1;182210:43:0;182230:23;182210:17;:43;:::i;:::-;182190:63;;181199:1066;;;;181155:1110;182277:21;182322:31;167030:8;182322:16;:31;:::i;:::-;182301:18;:52;:137;;182437:1;182301:137;;;182390:31;167030:8;182390:16;:31;:::i;:::-;182369:52;;:18;:52;:::i;:::-;182482:14;;182546:16;;182277:161;;-1:-1:-1;182482:14:0;182449:30;;182526:36;;:17;:36;:::i;:::-;182601:17;:32;;;182644:16;:35;;;182690:23;:44;;;182745:16;:36;;;182792:14;:30;;;182881:8;;:30;;;-1:-1:-1;;;182881:30:0;;;;182507:55;;-1:-1:-1;182881:54:0;;;;-1:-1:-1;;;;;182881:8:0;;;;:28;;-1:-1:-1;182881:30:0;;;;;;;;;;;;;;:8;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;182877:140;;182952:8;;:53;;-1:-1:-1;;;182952:53:0;;1407:14:1;;1400:22;182952:53:0;;;1382:41:1;-1:-1:-1;;;;;182952:8:0;;;;:31;;1355:18:1;;182952:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;182877:140;183101:12;;-1:-1:-1;;;;;183101:12:0;:26;183097:137;;167146:5;183187:16;;183171:13;:32;;;;:::i;:::-;183170:52;;;;:::i;:::-;183144:23;:78;183097:137;183343:21;183379:17;;183375:1400;;183413:20;183436:43;183441:12;183455:23;167030:8;183455;:23;:::i;:::-;183436:4;:43::i;:::-;183413:66;-1:-1:-1;183494:27:0;183524;183413:66;183524:12;:27;:::i;:::-;183494:57;-1:-1:-1;183566:20:0;183589:35;183494:57;183589:13;:35;:::i;:::-;183566:58;;183639:24;183666:50;183679:12;183693:22;183666:12;:50::i;:::-;183639:77;;183731:30;183764:43;183769:19;183790:16;183764:4;:43::i;:::-;183731:76;;183903:1;183881:19;:23;:53;;;;-1:-1:-1;183908:12:0;;-1:-1:-1;;;;;183908:12:0;:26;;183881:53;183877:622;;;183955:25;167146:5;184006:16;;183984:19;:38;;;;:::i;:::-;183983:58;;;;:::i;:::-;183955:86;;184060:28;167146:5;184117:16;;184092:22;:41;;;;:::i;:::-;184091:61;;;;:::i;:::-;184060:92;-1:-1:-1;184171:40:0;184194:17;184171:40;;:::i;:::-;;-1:-1:-1;184230:33:0;184246:17;184230:33;;:::i;:::-;;-1:-1:-1;184282:46:0;184308:20;184282:46;;:::i;:::-;184366:12;;:47;;184282:46;;-1:-1:-1;184348:12:0;;-1:-1:-1;;;;;184366:12:0;;;;184391:17;;184348:12;184366:47;184348:12;184366:47;184391:17;184366:12;:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;184347:66;;;184440:7;184432:51;;;;-1:-1:-1;;;184432:51:0;;36568:2:1;184432:51:0;;;36550:21:1;36607:2;36587:18;;;36580:30;36646:33;36626:18;;;36619:61;36697:18;;184432:51:0;36366:355:1;184432:51:0;183936:563;;;183877:622;184515:8;;:84;;-1:-1:-1;;;184515:84:0;;;;;16228:25:1;;;16269:18;;;16262:34;;;-1:-1:-1;;;;;184515:8:0;;;;:25;;184548:12;;16201:18:1;;184515:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;184640:12;184619:86;184654:22;184678:12;184692;184619:86;;;;;;;36928:25:1;;;36984:2;36969:18;;36962:34;;;;37027:2;37012:18;;37005:34;36916:2;36901:18;;36726:319;184619:86:0;;;;;;;;183398:1319;;;;;183375:1400;;;184738:8;;;;;;;;;-1:-1:-1;;;;;184738:8:0;-1:-1:-1;;;;;184738:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;183375:1400;184817:13;;184813:42;;184832:23;184846:8;184832:13;:23::i;:::-;184873:86;;;37281:25:1;;;37337:2;37322:18;;37315:34;;;37365:18;;;37358:34;;;37423:2;37408:18;;37401:34;;;184873:86:0;;37268:3:1;37253:19;184873:86:0;;;;;;;181109:3858;;;;180800:4167;;;;;;;:::o;21357:284::-;-1:-1:-1;;;;;3609:19:0;;;21431:106;;;;-1:-1:-1;;;21431:106:0;;37648:2:1;21431:106:0;;;37630:21:1;37687:2;37667:18;;;37660:30;37726:34;37706:18;;;37699:62;-1:-1:-1;;;37777:18:1;;;37770:43;37830:19;;21431:106:0;37446:409:1;21431:106:0;-1:-1:-1;;;;;;;;;;;21548:85:0;;-1:-1:-1;;;;;;21548:85:0;-1:-1:-1;;;;;21548:85:0;;;;;;;;;;21357:284::o;34203:97::-;18694:13;;;;;;;18686:69;;;;-1:-1:-1;;;18686:69:0;;;;;;;:::i;:::-;34277:7:::1;:15:::0;;-1:-1:-1;;34277:15:0::1;::::0;;34203:97::o;38130:111::-;18694:13;;;;;;;18686:69;;;;-1:-1:-1;;;18686:69:0;;;;;;;:::i;22050:297::-;22193:29;22204:17;22193:10;:29::i;:::-;22251:1;22237:4;:11;:15;:28;;;;22256:9;22237:28;22233:107;;;22282:46;22304:17;22323:4;22282:21;:46::i;:::-;;22050:297;;;:::o;58305:231::-;58383:7;58404:17;58423:18;58445:27;58456:4;58462:9;58445:10;:27::i;:::-;58403:69;;;;58483:18;58495:5;58483:11;:18::i;:::-;-1:-1:-1;58519:9:0;-1:-1:-1;58305:231:0;;;;;:::o;188287:1228::-;188412:15;;:37;;-1:-1:-1;;;188412:37:0;;188443:4;188412:37;;;607:51:1;188376:7:0;;;;-1:-1:-1;;;;;188412:15:0;;;;:22;;580:18:1;;188412:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;188396:53;-1:-1:-1;;;;;;188478:20:0;;;188513:11;;188509:962;;188615:25;188644:3;-1:-1:-1;;;;;188644:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:26;;;188643:118;;-1:-1:-1;188711:28:0;;188693:58;;-1:-1:-1;;;188693:58:0;;188711:28;188693:58;;;18278:36:1;-1:-1:-1;;;;;188711:28:0;;;;188693:55;;18251:18:1;;188693:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:67;188643:118;188615:146;;188782:20;188778:682;;;188846:7;188823:19;;:30;;;;;;;:::i;:::-;;;;;;;;188872:3;-1:-1:-1;;;;;188872:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;189051:28:0;;:81;;-1:-1:-1;;;189051:81:0;;189126:4;189051:81;;;607:51:1;188988:60:0;;-1:-1:-1;;;;;;189051:28:0;;;;-1:-1:-1;189051:66:0;;580:18:1;;189051:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;189051:81:0;;;;;;;;;;;;:::i;:::-;188988:144;;189206:27;189151:15;:52;189201:1;189167:5;:24;;;:31;:35;;;;:::i;:::-;189151:52;;;;;;;;;;;:82;;;;189320:1;189286:5;:24;;;:31;:35;;;;:::i;:::-;189259:63;;;;;;;-1:-1:-1;;189348:19:0;;;188287:1228;-1:-1:-1;;;;188287:1228:0:o;188778:682::-;189437:7;189415:19;;:29;;;;:::i;:::-;189408:36;188287:1228;-1:-1:-1;;;;;188287:1228:0:o;188509:962::-;-1:-1:-1;;189488:19:0;;;188287:1228;-1:-1:-1;;188287:1228:0:o;193498:113::-;193559:7;193591:2;193586;:7;:17;;193601:2;193586:17;;;-1:-1:-1;193596:2:0;193579:24;-1:-1:-1;193498:113:0:o;193680:185::-;193747:7;193775:1;193771;:5;193767:91;;;-1:-1:-1;193800:1:0;193793:8;;193767:91;193841:5;193845:1;193841;:5;:::i;:::-;193834:12;;;;185942:1040;186110:19;;186054:24;;186093:622;186135:14;:21;186131:25;;186093:622;;;186178:15;186196:14;186211:1;186196:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;186251:26;;;:17;:26;;;;;;;;186196:17;;-1:-1:-1;186296:25:0;;;186292:332;;186374:18;;;;:::i;:::-;;-1:-1:-1;186411:25:0;;-1:-1:-1;186424:12:0;186411:25;;:::i;:::-;;;186292:332;;;186560:24;186575:9;186560:12;:24;:::i;:::-;186531:26;;;;:17;:26;;;;;;:53;;;;-1:-1:-1;186603:5:0;;186292:332;186695:1;186682:9;:14;186678:25;;186698:5;;;;186678:25;186163:552;;186158:3;;;;;:::i;:::-;;;;186093:622;;;;186753:24;186794:16;-1:-1:-1;;;;;186780:31:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;186780:31:0;;186753:58;;186827:9;186822:110;186846:16;186842:1;:20;186822:110;;;186897:23;:21;:23::i;:::-;186884:7;186892:1;186884:10;;;;;;;;:::i;:::-;;;;;;;;;;:36;186864:3;;;;:::i;:::-;;;;186822:110;;;-1:-1:-1;186944:8:0;;:30;;-1:-1:-1;;;186944:30:0;;-1:-1:-1;;;;;186944:8:0;;;;:21;;:30;;186966:7;;186944:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;185993:989;;185942:1040;:::o;26523:461::-;26606:12;-1:-1:-1;;;;;3609:19:0;;;26631:88;;;;-1:-1:-1;;;26631:88:0;;39172:2:1;26631:88:0;;;39154:21:1;39211:2;39191:18;;;39184:30;39250:34;39230:18;;;39223:62;-1:-1:-1;;;39301:18:1;;;39294:36;39347:19;;26631:88:0;38970:402:1;26631:88:0;26793:12;26807:23;26834:6;-1:-1:-1;;;;;26834:19:0;26854:4;26834:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26792:67;;;;26877:99;26913:7;26922:10;26877:99;;;;;;;;;;;;;;;;;:35;:99::i;56756:747::-;56837:7;56846:12;56875:9;:16;56895:2;56875:22;56871:625;;57219:4;57204:20;;57198:27;57269:4;57254:20;;57248:27;57327:4;57312:20;;57306:27;56914:9;57298:36;57370:25;57381:4;57298:36;57198:27;57248;57370:10;:25::i;:::-;57363:32;;;;;;;;;56871:625;-1:-1:-1;57444:1:0;;-1:-1:-1;57448:35:0;56871:625;56756:747;;;;;:::o;55149:521::-;55227:20;55218:5;:29;;;;;;;;:::i;:::-;;55214:449;;55149:521;:::o;55214:449::-;55325:29;55316:5;:38;;;;;;;;:::i;:::-;;55312:351;;55371:34;;-1:-1:-1;;;55371:34:0;;39711:2:1;55371:34:0;;;39693:21:1;39750:2;39730:18;;;39723:30;39789:26;39769:18;;;39762:54;39833:18;;55371:34:0;39509:348:1;55312:351:0;55436:35;55427:5;:44;;;;;;;;:::i;:::-;;55423:240;;55488:41;;-1:-1:-1;;;55488:41:0;;40064:2:1;55488:41:0;;;40046:21:1;40103:2;40083:18;;;40076:30;40142:33;40122:18;;;40115:61;40193:18;;55488:41:0;39862:355:1;55423:240:0;55560:30;55551:5;:39;;;;;;;;:::i;:::-;;55547:116;;55607:44;;-1:-1:-1;;;55607:44:0;;40424:2:1;55607:44:0;;;40406:21:1;40463:2;40443:18;;;40436:30;40502:34;40482:18;;;40475:62;-1:-1:-1;;;40553:18:1;;;40546:32;40595:19;;55607:44:0;40222:398:1;187102:301:0;187213:19;;187189:14;:21;187153:15;;-1:-1:-1;187181:70:0;;;;-1:-1:-1;;;187181:70:0;;40827:2:1;187181:70:0;;;40809:21:1;40866:2;40846:18;;;40839:30;-1:-1:-1;;;40885:18:1;;;40878:44;40939:18;;187181:70:0;40625:338:1;187181:70:0;187272:14;187287:19;;187272:35;;;;;;;;:::i;:::-;;;;;;;;;187262:45;;187325:14;187340:19;;187325:35;;;;;;;;:::i;:::-;;;;;;;;187318:42;;;187394:1;187371:19;;:24;;;;;;;:::i;:::-;;;;;;;;187102:301;:::o;9724:305::-;9874:12;9903:7;9899:123;;;-1:-1:-1;9934:10:0;9927:17;;9899:123;9977:33;9985:10;9997:12;9977:7;:33::i;59757:1520::-;59888:7;;60822:66;60809:79;;60805:163;;;-1:-1:-1;60921:1:0;;-1:-1:-1;60925:30:0;60905:51;;60805:163;61082:24;;;61065:14;61082:24;;;;;;;;;41195:25:1;;;41268:4;41256:17;;41236:18;;;41229:45;;;;41290:18;;;41283:34;;;41333:18;;;41326:34;;;61082:24:0;;41167:19:1;;61082:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61082:24:0;;-1:-1:-1;;61082:24:0;;;-1:-1:-1;;;;;;;61121:20:0;;61117:103;;61174:1;61178:29;61158:50;;;;;;;61117:103;61240:6;-1:-1:-1;61248:20:0;;-1:-1:-1;59757:1520:0;;;;;;;;:::o;10037:552::-;10198:17;;:21;10194:388;;10430:10;10424:17;10487:15;10474:10;10470:2;10466:19;10459:44;10194:388;10557:12;10550:20;;-1:-1:-1;;;10550:20:0;;;;;;;;:::i;14:127:1:-;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:128;213:9;;;234:11;;;231:37;;;248:18;;:::i;669:180::-;728:6;781:2;769:9;760:7;756:23;752:32;749:52;;;797:1;794;787:12;749:52;-1:-1:-1;820:23:1;;669:180;-1:-1:-1;669:180:1:o;854:131::-;-1:-1:-1;;;;;929:31:1;;919:42;;909:70;;975:1;972;965:12;990:247;1049:6;1102:2;1090:9;1081:7;1077:23;1073:32;1070:52;;;1118:1;1115;1108:12;1070:52;1157:9;1144:23;1176:31;1201:5;1176:31;:::i;1434:250::-;1519:1;1529:113;1543:6;1540:1;1537:13;1529:113;;;1619:11;;;1613:18;1600:11;;;1593:39;1565:2;1558:10;1529:113;;;-1:-1:-1;;1676:1:1;1658:16;;1651:27;1434:250::o;1689:270::-;1730:3;1768:5;1762:12;1795:6;1790:3;1783:19;1811:76;1880:6;1873:4;1868:3;1864:14;1857:4;1850:5;1846:16;1811:76;:::i;:::-;1941:2;1920:15;-1:-1:-1;;1916:29:1;1907:39;;;;1948:4;1903:50;;1689:270;-1:-1:-1;;1689:270:1:o;1964:448::-;2185:2;2174:9;2167:21;2148:4;2211:44;2251:2;2240:9;2236:18;2228:6;2211:44;:::i;:::-;2303:9;2295:6;2291:22;2286:2;2275:9;2271:18;2264:50;2331:32;2356:6;2348;2331:32;:::i;:::-;2323:40;;;2399:6;2394:2;2383:9;2379:18;2372:34;1964:448;;;;;;:::o;2417:388::-;2485:6;2493;2546:2;2534:9;2525:7;2521:23;2517:32;2514:52;;;2562:1;2559;2552:12;2514:52;2601:9;2588:23;2620:31;2645:5;2620:31;:::i;:::-;2670:5;-1:-1:-1;2727:2:1;2712:18;;2699:32;2740:33;2699:32;2740:33;:::i;:::-;2792:7;2782:17;;;2417:388;;;;;:::o;2810:367::-;2873:8;2883:6;2937:3;2930:4;2922:6;2918:17;2914:27;2904:55;;2955:1;2952;2945:12;2904:55;-1:-1:-1;2978:20:1;;-1:-1:-1;;;;;3010:30:1;;3007:50;;;3053:1;3050;3043:12;3007:50;3090:4;3082:6;3078:17;3066:29;;3150:3;3143:4;3133:6;3130:1;3126:14;3118:6;3114:27;3110:38;3107:47;3104:67;;;3167:1;3164;3157:12;3182:118;3268:5;3261:13;3254:21;3247:5;3244:32;3234:60;;3290:1;3287;3280:12;3305:566;3397:6;3405;3413;3466:2;3454:9;3445:7;3441:23;3437:32;3434:52;;;3482:1;3479;3472:12;3434:52;3522:9;3509:23;-1:-1:-1;;;;;3547:6:1;3544:30;3541:50;;;3587:1;3584;3577:12;3541:50;3626:70;3688:7;3679:6;3668:9;3664:22;3626:70;:::i;:::-;3715:8;;-1:-1:-1;3600:96:1;-1:-1:-1;;3800:2:1;3785:18;;3772:32;3813:28;3772:32;3813:28;:::i;:::-;3860:5;3850:15;;;3305:566;;;;;:::o;3876:1221::-;4108:4;4137:2;4177;4166:9;4162:18;4207:2;4196:9;4189:21;4230:6;4265;4259:13;4296:6;4288;4281:22;4322:2;4312:12;;4355:2;4344:9;4340:18;4333:25;;4417:2;4407:6;4404:1;4400:14;4389:9;4385:30;4381:39;4439:4;4478:2;4470:6;4466:15;4499:1;4509:516;4523:6;4520:1;4517:13;4509:516;;;4616:2;4612:7;4600:9;4592:6;4588:22;4584:36;4579:3;4572:49;4650:6;4644:13;4691:2;4685:9;4677:6;4670:25;4742:2;4738;4734:11;4728:18;4783:2;4778;4770:6;4766:15;4759:27;4813:47;4856:2;4848:6;4844:15;4830:12;4813:47;:::i;:::-;4903:11;;;4897:18;4880:15;;;4873:43;;;;5003:12;;;;4799:61;-1:-1:-1;4968:15:1;;;;4545:1;4538:9;4509:516;;;-1:-1:-1;;5064:18:1;;;;5057:34;;;;-1:-1:-1;5042:6:1;;3876:1221;-1:-1:-1;;;;;3876:1221:1:o;5102:127::-;5163:10;5158:3;5154:20;5151:1;5144:31;5194:4;5191:1;5184:15;5218:4;5215:1;5208:15;5234:257;5306:4;5300:11;;;5338:17;;-1:-1:-1;;;;;5370:34:1;;5406:22;;;5367:62;5364:88;;;5432:18;;:::i;:::-;5468:4;5461:24;5234:257;:::o;5496:275::-;5567:2;5561:9;5632:2;5613:13;;-1:-1:-1;;5609:27:1;5597:40;;-1:-1:-1;;;;;5652:34:1;;5688:22;;;5649:62;5646:88;;;5714:18;;:::i;:::-;5750:2;5743:22;5496:275;;-1:-1:-1;5496:275:1:o;5776:181::-;5834:4;-1:-1:-1;;;;;5859:6:1;5856:30;5853:56;;;5889:18;;:::i;:::-;-1:-1:-1;5934:1:1;5930:14;5946:4;5926:25;;5776:181::o;5962:530::-;6004:5;6057:3;6050:4;6042:6;6038:17;6034:27;6024:55;;6075:1;6072;6065:12;6024:55;6111:6;6098:20;-1:-1:-1;;;;;6133:2:1;6130:26;6127:52;;;6159:18;;:::i;:::-;6203:55;6246:2;6227:13;;-1:-1:-1;;6223:27:1;6252:4;6219:38;6203:55;:::i;:::-;6283:2;6274:7;6267:19;6329:3;6322:4;6317:2;6309:6;6305:15;6301:26;6298:35;6295:55;;;6346:1;6343;6336:12;6295:55;6411:2;6404:4;6396:6;6392:17;6385:4;6376:7;6372:18;6359:55;6459:1;6434:16;;;6452:4;6430:27;6423:38;;;;6438:7;5962:530;-1:-1:-1;;;5962:530:1:o;6497:884::-;6549:5;6602:3;6595:4;6587:6;6583:17;6579:27;6569:55;;6620:1;6617;6610:12;6569:55;6656:6;6643:20;6682:4;6706:58;6722:41;6760:2;6722:41;:::i;:::-;6706:58;:::i;:::-;6798:15;;;6884:1;6880:10;;;;6868:23;;6864:32;;;6829:12;;;;6908:15;;;6905:35;;;6936:1;6933;6926:12;6905:35;6972:2;6964:6;6960:15;6984:368;7000:6;6995:3;6992:15;6984:368;;;7086:3;7073:17;-1:-1:-1;;;;;7109:11:1;7106:35;7103:125;;;7182:1;7211:2;7207;7200:14;7103:125;7253:56;7305:3;7300:2;7286:11;7278:6;7274:24;7270:33;7253:56;:::i;:::-;7241:69;;-1:-1:-1;7330:12:1;;;;7017;;6984:368;;;-1:-1:-1;7370:5:1;6497:884;-1:-1:-1;;;;;;6497:884:1:o;7386:660::-;7440:5;7493:3;7486:4;7478:6;7474:17;7470:27;7460:55;;7511:1;7508;7501:12;7460:55;7547:6;7534:20;7573:4;7597:58;7613:41;7651:2;7613:41;:::i;7597:58::-;7689:15;;;7775:1;7771:10;;;;7759:23;;7755:32;;;7720:12;;;;7799:15;;;7796:35;;;7827:1;7824;7817:12;7796:35;7863:2;7855:6;7851:15;7875:142;7891:6;7886:3;7883:15;7875:142;;;7957:17;;7945:30;;7995:12;;;;7908;;7875:142;;8051:1603;8255:6;8263;8271;8279;8332:3;8320:9;8311:7;8307:23;8303:33;8300:53;;;8349:1;8346;8339:12;8300:53;8389:9;8376:23;-1:-1:-1;;;;;8459:2:1;8451:6;8448:14;8445:34;;;8475:1;8472;8465:12;8445:34;8498:59;8549:7;8540:6;8529:9;8525:22;8498:59;:::i;:::-;8488:69;;8576:2;8566:12;;8631:2;8620:9;8616:18;8603:32;8660:2;8650:8;8647:16;8644:36;;;8676:1;8673;8666:12;8644:36;8699:61;8752:7;8741:8;8730:9;8726:24;8699:61;:::i;:::-;8689:71;;;8813:2;8802:9;8798:18;8785:32;8842:2;8832:8;8829:16;8826:36;;;8858:1;8855;8848:12;8826:36;8881:63;8936:7;8925:8;8914:9;8910:24;8881:63;:::i;:::-;8871:73;;;8997:2;8986:9;8982:18;8969:32;9026:2;9016:8;9013:16;9010:36;;;9042:1;9039;9032:12;9010:36;9065:24;;;-1:-1:-1;9120:4:1;9112:13;;9108:27;-1:-1:-1;9098:55:1;;9149:1;9146;9139:12;9098:55;9185:2;9172:16;9208:58;9224:41;9262:2;9224:41;:::i;9208:58::-;9300:15;;;9382:1;9378:10;;;;9370:19;;9366:28;;;9331:12;;;;9406:19;;;9403:39;;;9438:1;9435;9428:12;9403:39;9462:11;;;;9482:142;9498:6;9493:3;9490:15;9482:142;;;9564:17;;9552:30;;9515:12;;;;9602;;;;9482:142;;;8051:1603;;;;-1:-1:-1;8051:1603:1;;-1:-1:-1;;;;;;8051:1603:1:o;9659:455::-;9736:6;9744;9797:2;9785:9;9776:7;9772:23;9768:32;9765:52;;;9813:1;9810;9803:12;9765:52;9852:9;9839:23;9871:31;9896:5;9871:31;:::i;:::-;9921:5;-1:-1:-1;9977:2:1;9962:18;;9949:32;-1:-1:-1;;;;;9993:30:1;;9990:50;;;10036:1;10033;10026:12;9990:50;10059:49;10100:7;10091:6;10080:9;10076:22;10059:49;:::i;:::-;10049:59;;;9659:455;;;;;:::o;10119:320::-;10187:6;10240:2;10228:9;10219:7;10215:23;10211:32;10208:52;;;10256:1;10253;10246:12;10208:52;10296:9;10283:23;-1:-1:-1;;;;;10321:6:1;10318:30;10315:50;;;10361:1;10358;10351:12;10315:50;10384:49;10425:7;10416:6;10405:9;10401:22;10384:49;:::i;10626:835::-;10796:6;10804;10812;10865:2;10853:9;10844:7;10840:23;10836:32;10833:52;;;10881:1;10878;10871:12;10833:52;10921:9;10908:23;-1:-1:-1;;;;;10991:2:1;10983:6;10980:14;10977:34;;;11007:1;11004;10997:12;10977:34;11030:59;11081:7;11072:6;11061:9;11057:22;11030:59;:::i;:::-;11020:69;;11142:2;11131:9;11127:18;11114:32;11098:48;;11171:2;11161:8;11158:16;11155:36;;;11187:1;11184;11177:12;11155:36;11210:61;11263:7;11252:8;11241:9;11237:24;11210:61;:::i;:::-;11200:71;;11324:2;11313:9;11309:18;11296:32;11280:48;;11353:2;11343:8;11340:16;11337:36;;;11369:1;11366;11359:12;11337:36;;11392:63;11447:7;11436:8;11425:9;11421:24;11392:63;:::i;:::-;11382:73;;;10626:835;;;;;:::o;11692:990::-;11849:6;11857;11865;11873;11881;11889;11897;11905;11913;11966:3;11954:9;11945:7;11941:23;11937:33;11934:53;;;11983:1;11980;11973:12;11934:53;12019:9;12006:23;11996:33;;12076:2;12065:9;12061:18;12048:32;12038:42;;12127:2;12116:9;12112:18;12099:32;12089:42;;12178:2;12167:9;12163:18;12150:32;12140:42;;12229:3;12218:9;12214:19;12201:33;12191:43;;12281:3;12270:9;12266:19;12253:33;12243:43;;12336:3;12325:9;12321:19;12308:33;12350:28;12372:5;12350:28;:::i;:::-;12397:5;-1:-1:-1;12453:3:1;12438:19;;12425:33;-1:-1:-1;;;;;12470:30:1;;12467:50;;;12513:1;12510;12503:12;12467:50;12552:70;12614:7;12605:6;12594:9;12590:22;12552:70;:::i;:::-;12526:96;;12641:8;12631:18;;;12668:8;12658:18;;;11692:990;;;;;;;;;;;:::o;12687:125::-;12752:9;;;12773:10;;;12770:36;;;12786:18;;:::i;12817:380::-;12896:1;12892:12;;;;12939;;;12960:61;;13014:4;13006:6;13002:17;12992:27;;12960:61;13067:2;13059:6;13056:14;13036:18;13033:38;13030:161;;13113:10;13108:3;13104:20;13101:1;13094:31;13148:4;13145:1;13138:15;13176:4;13173:1;13166:15;13202:408;13404:2;13386:21;;;13443:2;13423:18;;;13416:30;13482:34;13477:2;13462:18;;13455:62;-1:-1:-1;;;13548:2:1;13533:18;;13526:42;13600:3;13585:19;;13202:408::o;13615:::-;13817:2;13799:21;;;13856:2;13836:18;;;13829:30;13895:34;13890:2;13875:18;;13868:62;-1:-1:-1;;;13961:2:1;13946:18;;13939:42;14013:3;13998:19;;13615:408::o;15088:127::-;15149:10;15144:3;15140:20;15137:1;15130:31;15180:4;15177:1;15170:15;15204:4;15201:1;15194:15;15561:135;15600:3;15621:17;;;15618:43;;15641:18;;:::i;:::-;-1:-1:-1;15688:1:1;15677:13;;15561:135::o;16307:127::-;16368:10;16363:3;16359:20;16356:1;16349:31;16399:4;16396:1;16389:15;16423:4;16420:1;16413:15;16439:120;16479:1;16505;16495:35;;16510:18;;:::i;:::-;-1:-1:-1;16544:9:1;;16439:120::o;16564:112::-;16596:1;16622;16612:35;;16627:18;;:::i;:::-;-1:-1:-1;16661:9:1;;16564:112::o;16681:136::-;16720:3;16748:5;16738:39;;16757:18;;:::i;:::-;-1:-1:-1;;;16793:18:1;;16681:136::o;16822:168::-;16895:9;;;16926;;16943:15;;;16937:22;;16923:37;16913:71;;16964:18;;:::i;19299:245::-;19366:6;19419:2;19407:9;19398:7;19394:23;19390:32;19387:52;;;19435:1;19432;19425:12;19387:52;19467:9;19461:16;19486:28;19508:5;19486:28;:::i;19889:367::-;19974:6;19982;19990;20043:2;20031:9;20022:7;20018:23;20014:32;20011:52;;;20059:1;20056;20049:12;20011:52;20088:9;20082:16;20072:26;;20141:2;20130:9;20126:18;20120:25;20154:28;20176:5;20154:28;:::i;:::-;20201:5;20191:15;;;20246:2;20235:9;20231:18;20225:25;20215:35;;19889:367;;;;;:::o;20261:287::-;20390:3;20428:6;20422:13;20444:66;20503:6;20498:3;20491:4;20483:6;20479:17;20444:66;:::i;:::-;20526:16;;;;;20261:287;-1:-1:-1;;20261:287:1:o;21035:544::-;21136:2;21131:3;21128:11;21125:448;;;21172:1;21197:5;21193:2;21186:17;21242:4;21238:2;21228:19;21312:2;21300:10;21296:19;21293:1;21289:27;21283:4;21279:38;21348:4;21336:10;21333:20;21330:47;;;-1:-1:-1;21371:4:1;21330:47;21426:2;21421:3;21417:12;21414:1;21410:20;21404:4;21400:31;21390:41;;21481:82;21499:2;21492:5;21489:13;21481:82;;;21544:17;;;21525:1;21514:13;21481:82;;;21485:3;;;21035:544;;;:::o;21755:1348::-;21879:3;21873:10;-1:-1:-1;;;;;21898:6:1;21895:30;21892:56;;;21928:18;;:::i;:::-;21957:96;22046:6;22006:38;22038:4;22032:11;22006:38;:::i;:::-;22000:4;21957:96;:::i;:::-;22108:4;;22172:2;22161:14;;22189:1;22184:662;;;;22890:1;22907:6;22904:89;;;-1:-1:-1;22959:19:1;;;22953:26;22904:89;-1:-1:-1;;21712:1:1;21708:11;;;21704:24;21700:29;21690:40;21736:1;21732:11;;;21687:57;23006:81;;22154:943;;22184:662;20982:1;20975:14;;;21019:4;21006:18;;-1:-1:-1;;22220:20:1;;;22337:236;22351:7;22348:1;22345:14;22337:236;;;22440:19;;;22434:26;22419:42;;22532:27;;;;22500:1;22488:14;;;;22367:19;;22337:236;;;22341:3;22601:6;22592:7;22589:19;22586:201;;;22662:19;;;22656:26;-1:-1:-1;;22745:1:1;22741:14;;;22757:3;22737:24;22733:37;22729:42;22714:58;22699:74;;22586:201;-1:-1:-1;;;;;22833:1:1;22817:14;;;22813:22;22800:36;;-1:-1:-1;21755:1348:1:o;24269:417::-;-1:-1:-1;;;;;;24464:26:1;;;;24452:39;;-1:-1:-1;;;;;;24520:47:1;;;;24516:1;24507:11;;24500:68;24606:2;24602:15;-1:-1:-1;;24598:53:1;24593:2;24584:12;;24577:75;24677:2;24668:12;;24269:417::o;24691:610::-;24958:3;24947:9;24940:22;24921:4;24985:45;25025:3;25014:9;25010:19;25002:6;24985:45;:::i;:::-;25078:9;25070:6;25066:22;25061:2;25050:9;25046:18;25039:50;25112:32;25137:6;25129;25112:32;:::i;:::-;25098:46;;25192:9;25184:6;25180:22;25175:2;25164:9;25160:18;25153:50;25220:32;25245:6;25237;25220:32;:::i;:::-;25212:40;;;25288:6;25283:2;25272:9;25268:18;25261:34;24691:610;;;;;;;:::o;30062:521::-;30139:4;30145:6;30205:11;30192:25;30299:2;30295:7;30284:8;30268:14;30264:29;30260:43;30240:18;30236:68;30226:96;;30318:1;30315;30308:12;30226:96;30345:33;;30397:20;;;-1:-1:-1;;;;;;30429:30:1;;30426:50;;;30472:1;30469;30462:12;30426:50;30505:4;30493:17;;-1:-1:-1;30536:14:1;30532:27;;;30522:38;;30519:58;;;30573:1;30570;30563:12;31965:407;32167:2;32149:21;;;32206:2;32186:18;;;32179:30;32245:34;32240:2;32225:18;;32218:62;-1:-1:-1;;;32311:2:1;32296:18;;32289:41;32362:3;32347:19;;31965:407::o;33082:184::-;33152:6;33205:2;33193:9;33184:7;33180:23;33176:32;33173:52;;;33221:1;33218;33211:12;33173:52;-1:-1:-1;33244:16:1;;33082:184;-1:-1:-1;33082:184:1:o;34481:1880::-;34591:6;34622:2;34665;34653:9;34644:7;34640:23;34636:32;34633:52;;;34681:1;34678;34671:12;34633:52;34714:9;34708:16;-1:-1:-1;;;;;34784:2:1;34776:6;34773:14;34770:34;;;34800:1;34797;34790:12;34770:34;34838:6;34827:9;34823:22;34813:32;;34864:4;34902:2;34897;34888:7;34884:16;34880:25;34877:45;;;34918:1;34915;34908:12;34877:45;34944:22;;:::i;:::-;34995:2;34989:9;34982:5;34975:24;35038:2;35034;35030:11;35024:18;35067:2;35057:8;35054:16;35051:36;;;35083:1;35080;35073:12;35051:36;35114:8;35110:2;35106:17;35096:27;;;35161:7;35154:4;35150:2;35146:13;35142:27;35132:55;;35183:1;35180;35173:12;35132:55;35212:2;35206:9;35196:19;;35235:58;35251:41;35289:2;35251:41;:::i;35235:58::-;35327:15;;;35409:1;35405:10;;;;35397:19;;35393:28;;;35358:12;;;;35433:19;;;35430:39;;;35465:1;35462;35455:12;35430:39;35489:11;;;;35509:784;35525:6;35520:3;35517:15;35509:784;;;35605:2;35599:3;35590:7;35586:17;35582:26;35579:116;;;35649:1;35678:2;35674;35667:14;35579:116;35723:22;;:::i;:::-;35773:10;;-1:-1:-1;;;;;35818:33:1;;35806:46;;35796:144;;35894:1;35923:2;35919;35912:14;35796:144;35953:24;;36011:12;;;36005:19;36072:10;36059:24;;36047:37;;36037:135;;36126:1;36155:2;36151;36144:14;36037:135;36192:16;;;36185:33;36231:20;;35542:12;;;;36271;;;;35509:784;;;36309:14;;;36302:29;;;;36313:5;34481:1880;-1:-1:-1;;;;;;;34481:1880:1:o;37860:269::-;37948:6;38001:2;37989:9;37980:7;37976:23;37972:32;37969:52;;;38017:1;38014;38007:12;37969:52;38049:9;38043:16;38068:31;38093:5;38068:31;:::i;38333:632::-;38504:2;38556:21;;;38626:13;;38529:18;;;38648:22;;;38475:4;;38504:2;38727:15;;;;38701:2;38686:18;;;38475:4;38770:169;38784:6;38781:1;38778:13;38770:169;;;38845:13;;38833:26;;38914:15;;;;38879:12;;;;38806:1;38799:9;38770:169;;;-1:-1:-1;38956:3:1;;38333:632;-1:-1:-1;;;;;;38333:632:1:o;39377:127::-;39438:10;39433:3;39429:20;39426:1;39419:31;39469:4;39466:1;39459:15;39493:4;39490:1;39483:15;41371:219;41520:2;41509:9;41502:21;41483:4;41540:44;41580:2;41569:9;41565:18;41557:6;41540:44;:::i
Swarm Source
ipfs://2d5aeadc3340defc038b9c71a09d61a2ccd715d6fd8efadaaeb86875e6ee9194
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.