Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
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
Contract ABI
API[{"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
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.