Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StakingDrift2
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-05-21 */ // File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._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 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._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() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @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 { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } } // File: @openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } // File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } } // File: utils/AllowableAddressUpgradeable.sol pragma solidity ^0.8.4; contract AllowableAddress is OwnableUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; // @dev the allowed minter addresses EnumerableSet.AddressSet internal s_minters; // @dev the allowed burner addresses EnumerableSet.AddressSet internal s_burners; /******* Variables *******/ // blacklist address => bool mapping(address => bool) internal blacklistAddress; /******* Modifiers *******/ modifier blacklistCheck(address _from, address _to) { require(!blacklistAddress[_from] && !blacklistAddress[_to], "Address is blacklisted"); _; } modifier onlyMinter() { if (!isMinter(msg.sender)) revert SenderNotMinter(msg.sender); _; } modifier onlyBurner() { if (!isBurner(msg.sender)) revert SenderNotBurner(msg.sender); _; } /******* Events *******/ error SenderNotMinter(address sender); error SenderNotBurner(address sender); error MaxSupplyExceeded(uint256 supplyAfterMint); event MintAccessGranted(address indexed minter); event BurnAccessGranted(address indexed burner); event MintAccessRevoked(address indexed minter); event BurnAccessRevoked(address indexed burner); event BlacklistUpdated(bool status); /******* Constructor *******/ function __AllowableAddress_init(address _ownerAddress) internal { __Ownable_init(_ownerAddress); } /* * @notice Manage blacklisting to restrict addresses * @param addresses Array of addresses * @param status If blacklist passing true, false otherwise. */ function manageBlacklist(address[] calldata addresses, bool status) external virtual onlyOwner { for (uint256 i; i < addresses.length; ++i) { blacklistAddress[addresses[i]] = status; } emit BlacklistUpdated(status); } /* * @notice grants both mint and burn roles to `burnAndMinter`. * @notice Accessable to only owner. * @param burnAndMinter Any address for mint and burn access */ function grantMintAndBurnRoles(address burnAndMinter) external onlyOwner { grantMintRole(burnAndMinter); grantBurnRole(burnAndMinter); } /* * @notice Grants mint role to the given address. * @notice Accessable to only owner. * @param minter Any address for mint access */ function grantMintRole(address minter) public onlyOwner { if (s_minters.add(minter)) { emit MintAccessGranted(minter); } } /* * @notice Grants burn role to the given address. * @notice Accessable to only owner. * @param burner Any address for burn access */ function grantBurnRole(address burner) public onlyOwner { if (s_burners.add(burner)) { emit BurnAccessGranted(burner); } } /* * @notice Revokes mint role for the given address. * @notice Accessable to only owner. * @param minter Any address for remove mint access */ function revokeMintRole(address minter) public onlyOwner { if (s_minters.remove(minter)) { emit MintAccessRevoked(minter); } } /* * @notice Revokes burn role from the given address. * @notice Accessable to only owner * @param burner Any address for remove burn access */ function revokeBurnRole(address burner) public onlyOwner { if (s_burners.remove(burner)) { emit BurnAccessRevoked(burner); } } /* * @param _address Any address * @return {the address is blacklisted or not}. */ function isBlacklisted(address _address) public view returns (bool) { return blacklistAddress[_address]; } /* * @return {all permissioned minters} */ function getMinters() public view returns (address[] memory) { return s_minters.values(); } /* * @return {all permissioned burners} */ function getBurners() public view returns (address[] memory) { return s_burners.values(); } /* * @notice Checks whether a given address is a minter for this token. * @return {true if the address is allowed to mint}. */ function isMinter(address minter) public view returns (bool) { return s_minters.contains(minter); } /* * @notice Checks whether a given address is a burner for this token. * @return {true if the address is allowed to burn}. */ function isBurner(address burner) public view returns (bool) { return s_burners.contains(burner); } } // File: @openzeppelin/contracts/utils/math/SafeMath.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); } // File: StakingDrift2.sol /** * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (c) 2024, DRIFTToken. * * DRIFT is the studio token behind the Drift studio. Drift is a Web3 game studio, which already has a ready-to-play Beta version of its game, Payout Pursuit. * * The DRIFT token has utility for gamers and non-gamers. Gamers that hold DRIFT will be able to customize their gaming experience with NFT skins and other features. * Non-gamers who stake DRIFT receive a percentage of game revenue, and the token also receives Liquidity from a percentage of game revenue. * * The Drift project has been developed by a highly experienced, fully doxxed Web3 team, with multiple successes in the Web3 space. * * Drift: * https://drifttoken.io/ * * Influ3nce: * https://influ3nce.me/ * * Amba$$ador: * https://influ3nce.me/ambassador/ * * Twitter / X: * https://twitter.com/TheDriftToken * * Telegram: * https://t.me/driftportal * */ pragma solidity 0.8.20; // Interface of ERC20 interface IERC20_EXT is IERC20 { function mint(address to, uint256 amount) external; function burn(uint256 value) external; function burnFrom(address account, uint256 value) external; function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function decimals() external view returns (uint8); } // Entry of Staking Drift Pool Contract contract StakingDrift is AllowableAddress, ReentrancyGuardUpgradeable { using SafeMath for uint256; struct User { uint256 stakedBalance; uint256 lastStakedTime; uint256 lastUpdateTime; uint256 rewardsBalance; uint256 rewardRate; } struct StakeInfo { uint256 minimumStake; uint256 maximumStake; uint256 minStakePeriod; uint256 fixedAPY; // 18 decimals uint256 lockedStake; // Days bool fixedRewardRate; } /* Variables */ bool public initialized = false; string public version; IERC20_EXT public stDriftToken; // 1:1 Stake token to be issued equals to staked drift IERC20_EXT public driftToken; // Drift token to be stake IERC20_EXT public rewardToken; // Reward Token address public factory; // Deployer factory address payable public feeWallet; // Fee wallet address where the fees will be sent to. StakeInfo public stakeInfo; // Info of this Stake Pool bool private isNative = false; // Is Reward is Native Gas Token bool private openStake = false; // Is stake pool open uint256 public totalStaked; // Total Stake Amount uint256 public unstakeFee; // Percentage multiplication with 1000. uint256 public rewardRate; // Reward rate per token per day (required if Fixed APY enabled) uint256 public stakeStartTimestamp = 0; // Stake Start TimeStamp for rewardRate uint256 public stakeEndDeadline = 0; // Stake End deadline for rewardRate and/or pool. If zero, no end period. uint256 public BONUS_MULTIPLIER; // e.g. Rewards (2x, 3x etc) mapping(address => User) private users; // Mapping User address => User info /* Modifiers */ modifier checkAmount(uint256 _amount) { require( _amount >= stakeInfo.minimumStake && _amount <= stakeInfo.maximumStake, "StakingDrift: invalid stake amount" ); _; } modifier isOpen() { require(isOpenStake(), "StakingDrift: stake not opened"); _; } /* Events */ event Staked(address indexed user, uint256 amount); event Unstaked(address indexed user, uint256 amount); event Claimed(address indexed user, uint256 amount); event UpdatedDriftToken(address driftToken); event UpdatedStakeDriftToken(address stDriftToken); event UpdatedFeeWallet(address feeWallet); event UpdatedBonusMultiplier(uint8 _multiplier); event RemoveFixed(uint256 timestamp); event EnableFixed(uint256 timestamp); event StakeOpen(uint256 stakeEndDeadlineInDays, uint256 unstakeFeeRate, uint256 timestamp); event StakeClosed(uint256 timestamp); event UpdateUnstakeFeesAndLockedDays(uint256 unstakeFeeRate, uint256 lockedStakeDays); event UpdateLimits(uint256 minimumStake, uint256 maximumStake, uint256 minStakePeriod); /* Constructor */ /** * @notice Initialize Construction called from proxy initialization * @param _factory Deployer factory address * @param _driftToken Drift Token Address * @param _stDriftToken Stake Drift Token Address * @param _rewardToken Reward Token Address * @param _feeWallet Fee Wallet Address * @param _isRewardNativeToken True if Reward is Native, false otherwise. * @param _fixedAPY Percentage in wei if enable Fixed APY, zero otherwise. * @param _rewardRate Reward rate is required if Fixed APY enabled. Reward rate is a per token per day. * @param _lockedStake For Locked Stake, value in days greater than zero. Zero otherwise. */ function initialize( address _factory, address _driftToken, address _stDriftToken, address _rewardToken, address _feeWallet, bool _isRewardNativeToken, uint256 _fixedAPY, // in wei uint256 _rewardRate, // in wei uint256 _lockedStake ) public initializer { require(!initialized, "Already initialized"); __AllowableAddress_init(_msgSender()); factory = _factory; feeWallet = payable(_feeWallet); driftToken = IERC20_EXT(_driftToken); stDriftToken = IERC20_EXT(_stDriftToken); rewardToken = IERC20_EXT(_rewardToken); isNative = _isRewardNativeToken; stakeInfo.fixedAPY = _fixedAPY; if(_fixedAPY > 0) { require(_rewardRate > 0, "StakingDrift: reward rate per token per day required for fixed APY"); } if(_rewardRate > 0) { rewardRate = _rewardRate; stakeInfo.fixedRewardRate = true; } stakeInfo.maximumStake = type(uint256).max; stakeInfo.minStakePeriod = 30; stakeInfo.lockedStake = _lockedStake; BONUS_MULTIPLIER = 1; version = "1"; initialized = true; } /* * @notice fallback functions */ receive() external payable {} fallback() external payable {} /** * @notice Update Bonus Multiplier * @notice Accessable to only owner * @param _multiplier Multiplier in number (i.e. 2 = 2x, 3 = 3x, etc) */ function updateBonusMultiplier(uint8 _multiplier) external onlyOwner { require( _multiplier >= 1, "StakingDrift: bonus multiplier should be greater than or equals to 1" ); BONUS_MULTIPLIER = _multiplier; emit UpdatedBonusMultiplier(_multiplier); } /** * @notice Update Drift Token Address * @notice Accessable to only owner * @param _newDriftToken New Drift Token Address */ function updateDriftToken(address _newDriftToken) external onlyOwner { require(_newDriftToken != address(0), "StakingDrift: newDriftToken is a zero address"); driftToken = IERC20_EXT(_newDriftToken); emit UpdatedDriftToken(_newDriftToken); } /** * @notice Update Fee Wallet * @notice Accessable to only owner * @param _newStDriftToken New Stake Drift Token Address */ function updateStakeDriftToken(address _newStDriftToken) external onlyOwner { require(_newStDriftToken != address(0), "StakingDrift: newStDriftToken is a zero address"); stDriftToken = IERC20_EXT(_newStDriftToken); emit UpdatedStakeDriftToken(_newStDriftToken); } /** * @notice Update Fee Wallet * @notice Accessable to only owner * @param _newFeeWallet New Fee Wallet Address */ function updateFeeWallet(address _newFeeWallet) external onlyOwner { require(_newFeeWallet != address(0), "StakingDrift: newFeeWallet is a zero address"); feeWallet = payable(_newFeeWallet); emit UpdatedFeeWallet(_newFeeWallet); } /** * @notice Remove fixed APY, reward rate * @notice Accessable to only owner */ function removeFixed() external onlyOwner { stakeInfo.fixedAPY = 0; stakeInfo.fixedRewardRate = false; calculateRewardRate(); emit RemoveFixed(block.timestamp); } /** * @notice Enable fixed APY, reward rate if not enabled * @notice Accessable to only owner * @param _apyPercent APY percentage in wei * @param _rewardRate Reward rate per token per day in wei */ function enableFixed(uint256 _apyPercent, uint256 _rewardRate) external onlyOwner { require(rewardRate > 0, "StakingDrift: reward rate per token per day required for fixed APY"); stakeInfo.fixedAPY = _apyPercent; stakeInfo.fixedRewardRate = true; rewardRate = _rewardRate; emit EnableFixed(block.timestamp); } /** * @notice Stake with permit * @param _amount Amount in wei * @param deadline Future deadline in timestamp * @param v secp256k1 signature from `owner` * @param r secp256k1 signature from `owner` * @param s secp256k1 signature from `owner` */ function stakeWithPermit( uint256 _amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external isOpen checkAmount(_amount) nonReentrant { driftToken.permit(_msgSender(), address(this), _amount, deadline, v, r, s); revert("StakingDrift: Stake not allowed for this pool"); // _stake(_amount, _msgSender()); // updateReward(_msgSender()); } /** * @notice Stake on behalf. Owner of tokens stakes for someone. * @param _amount Amount in wei * @param _userAddress Address of user to stake for */ function stakeOnBehalf(uint256 _amount, address _userAddress) external isOpen checkAmount(_amount) nonReentrant { require(behalfStakeAllowedAddress[_msgSender()] == true || owner() == _msgSender(), "StakingDrift: Stake not allowed"); _stake(_amount, _userAddress, _msgSender()); updateReward(_userAddress); } /** * @notice Stake Drift tokens. * @param _amount Amount in wei. */ function stake(uint256 _amount) external isOpen checkAmount(_amount) nonReentrant { revert("StakingDrift: Stake not allowed for this pool"); // _stake(_amount, _msgSender()); // updateReward(_msgSender()); } /** * @notice Unstake tokens with rewards if available. * @param _amount Amount in wei. */ function unstake(uint256 _amount) external nonReentrant { require(_amount > 0, "StakingDrift: amount must be greater than zero"); updateReward(_msgSender()); User storage $ = users[_msgSender()]; require($.stakedBalance >= _amount, "StakingDrift: insufficient staked balance"); if(stakeInfo.lockedStake > 0) { require(_getDays($.lastStakedTime, block.timestamp) >= stakeInfo.lockedStake, "StakingDrift: your staked token"); } uint256 _unstakeFee = _getDays($.lastStakedTime, block.timestamp) < stakeInfo.minStakePeriod ? (_amount * unstakeFee) / 10**5 : 0; uint256 amountAfterFee = _amount - _unstakeFee; $.stakedBalance -= _amount; totalStaked -= _amount; distributeReward(_msgSender()); // Burn stDRIFT tokens stDriftToken.burnFrom(_msgSender(), _amount); if (_unstakeFee > 0) { driftToken.transfer(feeWallet, _unstakeFee); } driftToken.transfer(_msgSender(), amountAfterFee); } /** * @notice Claim rewards of staked tokens if available. */ function claimRewards() external nonReentrant { updateReward(_msgSender()); // Update rewards for the user User storage $ = users[_msgSender()]; require($.rewardsBalance > 0, "StakingDrift: no rewards to claim"); distributeReward(_msgSender()); } /** * @notice Add liquidity or Rewards in pool. * @notice Accessable to only owner * @param amount Amount in wei. */ function addLiquidty(uint256 amount) external payable onlyOwner { require(amount > 0, "StakingDrift: Amount must be greater than zero"); if (isNative) { require(msg.value == amount, "StakingDrift: incorrect amount sent"); } else { rewardToken.transferFrom(_msgSender(), address(this), amount); } calculateRewardRate(); } /** * @notice Start stake if not already open. * @notice Accessable to only owner * @param _stakeEndDeadlineInDays Stake pool deadline in days or zero otherwise for infinite * @param _unstakeFeeRate Unstake fees percentage multiplied by 1000 */ function startStake(uint256 _stakeEndDeadlineInDays, uint256 _unstakeFeeRate) external onlyOwner { require(isOpenStake() == false, "StakingDrift : stake is already open."); openStake = true; stakeStartTimestamp = block.timestamp; stakeEndDeadline = _stakeEndDeadlineInDays > 0 ? block.timestamp + (_stakeEndDeadlineInDays * 1 days) : 0; unstakeFee = _unstakeFeeRate; calculateRewardRate(); emit StakeOpen(_stakeEndDeadlineInDays, _unstakeFeeRate, block.timestamp); } /** * @notice Stop stake if not already closed. * @notice Accessable to only owner */ function stopStake() external onlyOwner { require(isOpenStake() == true, "StakingDrift : stake is already closed."); openStake = false; stakeEndDeadline = block.timestamp; emit StakeClosed(block.timestamp); } /** * @notice Update unstake fees percentage and/or locked days of stake * @notice Accessable to only owner * @param _newUnstakeFeeRate Unstake fees percentage multiplied by 1000 * @param _lockedStakeDays Locked stake in days if enable locked pool */ function updateUnstakeFeesAndLockedDays(uint256 _newUnstakeFeeRate, uint256 _lockedStakeDays) external onlyOwner { unstakeFee = _newUnstakeFeeRate; stakeInfo.lockedStake = _lockedStakeDays; emit UpdateUnstakeFeesAndLockedDays(_newUnstakeFeeRate, _lockedStakeDays); } /** * @notice Update limits and enable or disable feature that users stake (max / min) tokens and minimum stake period * @notice Accessable to only owner * @param _newMinimumStake Amount of token user min hold. * @param _newMaximumStake Amount of token user max hold. * @param _newMinStakePeriod Minimum stake period in days */ function updateLimits( uint256 _newMinimumStake, uint256 _newMaximumStake, uint256 _newMinStakePeriod ) external onlyOwner { stakeInfo.minimumStake = _newMinimumStake; stakeInfo.maximumStake = _newMaximumStake; stakeInfo.minStakePeriod = _newMinStakePeriod; emit UpdateLimits(_newMinimumStake, _newMaximumStake, _newMinStakePeriod); } /** * @return {APY} */ function calculateAPY() external view returns (uint256) { return _calculateAPY(); } /** * @return stakedBalance Staked balance * @return lastStakedTime Last staked timestamp * @return lastUpdateTime Last updated timestamp * @return rewardsBalance Reward balance */ function getUserInfo(address _userAddress) external view returns ( uint256 stakedBalance, uint256 lastStakedTime, uint256 lastUpdateTime, uint256 rewardsBalance ) { User storage user = users[_userAddress]; (uint256 _pendingRewards, ) = getPendingRewards(_userAddress); return ( user.stakedBalance, stakeStartTimestamp, user.lastUpdateTime > stakeStartTimestamp ? user.lastUpdateTime : stakeStartTimestamp, _pendingRewards ); } /** * @notice Withdraw reward liquidity from contract. * @notice Accessable to only owner * @param _amount Amount in wei */ function withdrawLiquidity(uint256 _amount) public onlyOwner { if (isNative) { require( address(this).balance >= _amount, "StakingDrift: amount is greater than balance" ); (bool os, ) = payable(owner()).call{value: address(this).balance}(""); require(os); } else { require( rewardToken.balanceOf(address(this)) >= _amount, "StakingDrift: amount is greater than balance" ); rewardToken.transfer(owner(), _amount); } } /** * @notice Withdraw Native Gas Token from contract. * @notice Accessable to only owner */ function withdrawNativeFunds() public onlyOwner { if (address(this).balance > 0) { (bool os, ) = payable(owner()).call{value: address(this).balance}(""); require(os); } else { revert("StakingDrift: no funds"); } } /** * @notice Withdraw token from contract. * @notice Accessable to only owner * @param _tokenAddress Token address */ function withdrawOtherTokenFunds(address _tokenAddress) public onlyOwner { if (IERC20(_tokenAddress).balanceOf(address(this)) > 0) { IERC20(_tokenAddress).transfer(owner(), IERC20(_tokenAddress).balanceOf(address(this))); } else { revert("StakingDrift: no funds"); } } /** * @return {true if pool open, false otherwise} */ function isOpenStake() public view returns (bool) { return openStake == true && (block.timestamp < stakeEndDeadline || stakeEndDeadline == 0); } /** * @notice Helper function to get pending rewards * @param _userAddress Address of staker * @return pendingRewards Claimable pending rewards * @return rewardDays Days of Unclaimable rewards */ function getPendingRewards(address _userAddress) public view returns (uint256 pendingRewards, uint256 rewardDays) { User storage $ = users[_userAddress]; rewardDays = rewardAccumulateStartTimestamp > 0 ? _getDays( $.lastUpdateTime > rewardAccumulateStartTimestamp ? $.lastUpdateTime : rewardAccumulateStartTimestamp, stakeEndDeadline > 0 ? min(block.timestamp, stakeEndDeadline) : block.timestamp ) : 0; uint256 pendingRewardOnSubscribedRewardRateOneDay = 0; uint256 pendingRewardsRemains = 0; if (rewardDays > 0) { pendingRewardOnSubscribedRewardRateOneDay = $.stakedBalance.mul($.rewardRate).div( 10**(stakeInfo.fixedRewardRate == true ? 18 : 20) ); pendingRewardsRemains = $.stakedBalance.mul(rewardRate.mul(rewardDays - 1)).div( 10**(stakeInfo.fixedRewardRate == true ? 18 : 20) ); } pendingRewards = $.rewardsBalance.add(pendingRewardsRemains.add(pendingRewardOnSubscribedRewardRateOneDay).mul(BONUS_MULTIPLIER)); } /** * @return {Total pending rewards} */ function getTotalPendingRewards() public view returns (uint256) { if (isNative) { return address(this).balance; } return rewardToken.balanceOf(address(this)); } /** * @notice Internal callable function when stake tokens * @param _amount Amount in wei. * @param _sender Sender address who stakes. */ function _stake(uint256 _amount, address _sender) internal { _stake(_amount, _sender, _sender); } /** * @notice Internal callable function when stake tokens * @param _amount Amount in wei. * @param _userAddress Address of user to stake for. * @param _sender Sender address who stakes. */ function _stake( uint256 _amount, address _userAddress, address _sender ) internal { User storage $ = users[_userAddress]; driftToken.transferFrom(_sender, address(this), _amount); totalStaked += _amount; $.stakedBalance += _amount; $.lastStakedTime = block.timestamp; stDriftToken.mint(_userAddress, _amount); emit Staked(_userAddress, _amount); } /** * @notice Internal callable function when claim reward calls * @param _userAddress Address of user */ function distributeReward(address _userAddress) internal { User storage $ = users[_userAddress]; uint256 amount = $.rewardsBalance; if (amount > 0) { $.rewardsBalance = 0; // Reset user rewards if (isNative) { amount = min(amount, address(this).balance); _transferNative(_userAddress, amount); } else { amount = min(calcDriftDigitsToOther(amount), rewardToken.balanceOf(address(this))); rewardToken.transfer(_msgSender(), amount); } emit Claimed(_userAddress, amount); } } /** * @notice Internal callable function to transfer Native Gas Token. * @param _recipient Address of recipient * @param _amount Amount in wei */ function _transferNative(address _recipient, uint256 _amount) internal { (bool sent, ) = payable(_recipient).call{value: _amount}(""); require(sent); } /** * @notice Internal callable function to update rewards of staker when user stakes or unstakes * @param _userAddress Address of staker */ function updateReward(address _userAddress) internal { User storage $ = users[_userAddress]; calculateRewardRate(); // Calculate dynamic reward rate if (totalStaked > 0) { ($.rewardsBalance, ) = getPendingRewards(_userAddress); // Accumulate pending rewards } $.lastUpdateTime = block.timestamp; // Update last update time $.rewardRate = rewardRate; } /** * @notice Internal callable function to update and calculate reward rate if Fixed Rate not enabled. */ function calculateRewardRate() internal { if(stakeInfo.fixedRewardRate == true) { return; } rewardRate = _calculateAPY().div(365 * 10**2); } /** * @notice Helper function to convert Drift decimals to other token decimals * @param amount Amount of tokens in Drift decimals */ function calcDriftDigitsToOther(uint256 amount) internal view returns (uint256 calcAmount) { calcAmount = (amount * 10**(isNative ? 18 : rewardToken.decimals())) / 10**driftToken.decimals(); return calcAmount; } /** * @notice Helper function to convert other token decimals to Drift decimals * @param amount Amount of tokens in other token decimals */ function calcOtherToDriftDigits(uint256 amount) internal view returns (uint256 calcAmount) { calcAmount = (amount * 10**driftToken.decimals()) / 10**(isNative ? 18 : rewardToken.decimals()); return calcAmount; } /** * @notice Helper function to get APY * @return {Fixed APY or Calculated if Fixed not enabled} */ function _calculateAPY() internal view returns (uint256) { if (getTotalPendingRewards() == 0 || totalStaked == 0) { return 0; } if (stakeInfo.fixedAPY > 0) { return stakeInfo.fixedAPY * 10**2; } uint256 apy = ((calcOtherToDriftDigits(getTotalPendingRewards()) * 10**20) / totalStaked); return apy; } /** * @notice Helper function to find the minimum of two values. * @param a Number 1 * @param b Number 2 * @return {Minimum number} */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @notice Helper function to get days * @param _timestampBefore Before time * @param _timestampAfter After time * @return {DAYS} */ function _getDays(uint256 _timestampBefore, uint256 _timestampAfter) internal pure returns (uint256) { if (_timestampBefore >= _timestampAfter || _timestampBefore == 0 || _timestampAfter == 0) { return 0; } uint256 timestamp = _timestampAfter - _timestampBefore; uint256 timestampDays = timestamp.div(60).div(60).div(24); return timestampDays; } mapping(address => bool) public behalfStakeAllowedAddress; uint256 public rewardAccumulateStartTimestamp = 0; function updateRewardAccumulateStartTimestamp(uint256 _newTimestamp) external onlyOwner { rewardAccumulateStartTimestamp = _newTimestamp; } } contract StakingDrift2 is StakingDrift { bool initialized_v2 = false; function initializeV2( address claimAddress, uint256 _rewardAccumulateStartTimestamp ) external { require(!initialized_v2, "Already initialized"); behalfStakeAllowedAddress[claimAddress] = true; rewardAccumulateStartTimestamp = _rewardAccumulateStartTimestamp; version = "2"; initialized_v2 = true; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"uint256","name":"supplyAfterMint","type":"uint256"}],"name":"MaxSupplyExceeded","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderNotBurner","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderNotMinter","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"BlacklistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"}],"name":"BurnAccessGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"}],"name":"BurnAccessRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EnableFixed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"MintAccessGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"MintAccessRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"RemoveFixed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StakeClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"stakeEndDeadlineInDays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StakeOpen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minimumStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maximumStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minStakePeriod","type":"uint256"}],"name":"UpdateLimits","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"unstakeFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedStakeDays","type":"uint256"}],"name":"UpdateUnstakeFeesAndLockedDays","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"_multiplier","type":"uint8"}],"name":"UpdatedBonusMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"driftToken","type":"address"}],"name":"UpdatedDriftToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeWallet","type":"address"}],"name":"UpdatedFeeWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"stDriftToken","type":"address"}],"name":"UpdatedStakeDriftToken","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BONUS_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addLiquidty","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"behalfStakeAllowedAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"driftToken","outputs":[{"internalType":"contract IERC20_EXT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_apyPercent","type":"uint256"},{"internalType":"uint256","name":"_rewardRate","type":"uint256"}],"name":"enableFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBurners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_userAddress","type":"address"}],"name":"getPendingRewards","outputs":[{"internalType":"uint256","name":"pendingRewards","type":"uint256"},{"internalType":"uint256","name":"rewardDays","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_userAddress","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"stakedBalance","type":"uint256"},{"internalType":"uint256","name":"lastStakedTime","type":"uint256"},{"internalType":"uint256","name":"lastUpdateTime","type":"uint256"},{"internalType":"uint256","name":"rewardsBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"grantBurnRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"burnAndMinter","type":"address"}],"name":"grantMintAndBurnRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"grantMintRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_driftToken","type":"address"},{"internalType":"address","name":"_stDriftToken","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_feeWallet","type":"address"},{"internalType":"bool","name":"_isRewardNativeToken","type":"bool"},{"internalType":"uint256","name":"_fixedAPY","type":"uint256"},{"internalType":"uint256","name":"_rewardRate","type":"uint256"},{"internalType":"uint256","name":"_lockedStake","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"claimAddress","type":"address"},{"internalType":"uint256","name":"_rewardAccumulateStartTimestamp","type":"uint256"}],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"isBurner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isOpenStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"manageBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeFixed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"revokeBurnRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"revokeMintRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardAccumulateStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20_EXT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stDriftToken","outputs":[{"internalType":"contract IERC20_EXT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeEndDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeInfo","outputs":[{"internalType":"uint256","name":"minimumStake","type":"uint256"},{"internalType":"uint256","name":"maximumStake","type":"uint256"},{"internalType":"uint256","name":"minStakePeriod","type":"uint256"},{"internalType":"uint256","name":"fixedAPY","type":"uint256"},{"internalType":"uint256","name":"lockedStake","type":"uint256"},{"internalType":"bool","name":"fixedRewardRate","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_userAddress","type":"address"}],"name":"stakeOnBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"stakeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeEndDeadlineInDays","type":"uint256"},{"internalType":"uint256","name":"_unstakeFeeRate","type":"uint256"}],"name":"startStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_multiplier","type":"uint8"}],"name":"updateBonusMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newDriftToken","type":"address"}],"name":"updateDriftToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFeeWallet","type":"address"}],"name":"updateFeeWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMinimumStake","type":"uint256"},{"internalType":"uint256","name":"_newMaximumStake","type":"uint256"},{"internalType":"uint256","name":"_newMinStakePeriod","type":"uint256"}],"name":"updateLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTimestamp","type":"uint256"}],"name":"updateRewardAccumulateStartTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newStDriftToken","type":"address"}],"name":"updateStakeDriftToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newUnstakeFeeRate","type":"uint256"},{"internalType":"uint256","name":"_lockedStakeDays","type":"uint256"}],"name":"updateUnstakeFeesAndLockedDays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawNativeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"withdrawOtherTokenFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526037805460ff199081169091556044805461ffff191690555f60488190556049819055604d55604e8054909116905534801561003e575f80fd5b50613b748061004c5f395ff3fe608060405260043610610349575f3560e01c80638aa28550116101b8578063d1c515ea116100f5578063f25f4b5611610099578063f7c618c11161006b578063f7c618c1146109df578063f81094f3146109fe578063fb2f349214610a1d578063fe575a8714610a3c57005b8063f25f4b561461094e578063f2fde38b1461096d578063f6b96d7f1461098c578063f6ed2017146109ab57005b8063def533f3116100d2578063def533f3146108dc578063df4b2d3a146108f1578063e0b3d4f814610910578063ecd9ba821461092f57005b8063d1c515ea14610894578063db313a09146108a9578063dbb0170b146108bd57005b8063aa271e1a1161015c578063c45a015511610139578063c45a015514610818578063c630948d14610837578063c64d0ebc14610856578063ccd8af221461087557005b8063aa271e1a146107bb578063aceccf8f146107da578063c2e3273d146107f957005b80638ea97d26116101955780638ea97d2614610753578063968bcfcf146107685780639852868a14610787578063a694fc3a1461079c57005b80638aa28550146106a65780638cc01fdc146106bb5780638da5cb5b1461071757005b80634e94e5f9116102865780636e19f9531161022a5780637b0a47ee116102075780637b0a47ee14610649578063817b1cd21461065e57806386fe8b431461067357806388e319611461068757005b80636e19f953146105eb5780636f21b676146105fe578063715018a61461063557005b8063627c8b2a11610263578063627c8b2a1461053e5780636386c1c71461056c57806366718524146105ab5780636b32810b146105ca57005b80634e94e5f9146104df5780634f5632f8146104fe57806354fd4d501461051d57005b8063283f13fe116102ed57806336a0f8a5116102ca57806336a0f8a514610479578063372500ab146104985780634334614a146104ac5780634b0fefe9146104cb57005b8063283f13fe146104325780632a648300146104465780632e17de781461045a57005b8063158ef93e11610326578063158ef93e146103af5780631e9b3a92146103dd5780631fdb28f0146103ff578063255412fb1461041e57005b80630a861f2a14610352578063128bfcae14610371578063130c69e81461039057005b3661035057005b005b34801561035d575f80fd5b5061035061036c3660046134fe565b610a73565b34801561037c575f80fd5b5061035061038b366004613515565b610d00565b34801561039b575f80fd5b506103506103aa366004613543565b610e10565b3480156103ba575f80fd5b506037546103c89060ff1681565b60405190151581526020015b60405180910390f35b3480156103e8575f80fd5b506103f1610ef9565b6040519081526020016103d4565b34801561040a575f80fd5b50610350610419366004613579565b610f7a565b348015610429575f80fd5b50610350611059565b34801561043d575f80fd5b5061035061113c565b348015610451575f80fd5b506103f161120a565b348015610465575f80fd5b506103506104743660046134fe565b611213565b348015610484575f80fd5b50610350610493366004613592565b61158f565b3480156104a3575f80fd5b506103506115eb565b3480156104b7575f80fd5b506103c86104c6366004613579565b611695565b3480156104d6575f80fd5b506103506116a7565b3480156104ea575f80fd5b506103506104f9366004613579565b6116f5565b348015610509575f80fd5b50610350610518366004613579565b611842565b348015610528575f80fd5b50610531611890565b6040516103d491906135bb565b348015610549575f80fd5b506103c8610558366004613579565b604c6020525f908152604090205460ff1681565b348015610577575f80fd5b5061058b610586366004613579565b61191c565b6040805194855260208501939093529183015260608201526080016103d4565b3480156105b6575f80fd5b506103506105c5366004613579565b611979565b3480156105d5575f80fd5b506105de611a58565b6040516103d49190613606565b6103506105f93660046134fe565b611a63565b348015610609575f80fd5b50603a5461061d906001600160a01b031681565b6040516001600160a01b0390911681526020016103d4565b348015610640575f80fd5b50610350611be6565b348015610654575f80fd5b506103f160475481565b348015610669575f80fd5b506103f160455481565b34801561067e575f80fd5b506105de611bf7565b348015610692575f80fd5b506103506106a1366004613579565b611c03565b3480156106b1575f80fd5b506103f1604a5481565b3480156106c6575f80fd5b50603e54603f546040546041546042546043546106e895949392919060ff1686565b6040805196875260208701959095529385019290925260608401526080830152151560a082015260c0016103d4565b348015610722575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661061d565b34801561075e575f80fd5b506103f160465481565b348015610773575f80fd5b506103506107823660046134fe565b611ce2565b348015610792575f80fd5b506103f1604d5481565b3480156107a7575f80fd5b506103506107b63660046134fe565b611cef565b3480156107c6575f80fd5b506103c86107d5366004613579565b611e16565b3480156107e5575f80fd5b506103506107f4366004613652565b611e21565b348015610804575f80fd5b50610350610813366004613579565b611fb3565b348015610823575f80fd5b50603c5461061d906001600160a01b031681565b348015610842575f80fd5b50610350610851366004613579565b612000565b348015610861575f80fd5b50610350610870366004613579565b612016565b348015610880575f80fd5b5061035061088f36600461367c565b612064565b34801561089f575f80fd5b506103f160485481565b3480156108b4575f80fd5b506103c8612133565b3480156108c8575f80fd5b5060395461061d906001600160a01b031681565b3480156108e7575f80fd5b506103f160495481565b3480156108fc575f80fd5b5061035061090b366004613515565b612160565b34801561091b575f80fd5b5061035061092a3660046136b1565b6121a8565b34801561093a575f80fd5b50610350610949366004613742565b612523565b348015610959575f80fd5b50603d5461061d906001600160a01b031681565b348015610978575f80fd5b50610350610987366004613579565b6126e5565b348015610997575f80fd5b506103506109a6366004613515565b612738565b3480156109b6575f80fd5b506109ca6109c5366004613579565b61280b565b604080519283526020830191909152016103d4565b3480156109ea575f80fd5b50603b5461061d906001600160a01b031681565b348015610a09575f80fd5b50610350610a18366004613579565b612938565b348015610a28575f80fd5b50610350610a37366004613787565b612985565b348015610a47575f80fd5b506103c8610a56366004613579565b6001600160a01b03165f9081526004602052604090205460ff1690565b610a7b612a2c565b60445460ff1615610b7f5780471015610af05760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a20616d6f756e7420697320677265617465722060448201526b7468616e2062616c616e636560a01b60648201526084015b60405180910390fd5b5f610b227f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f8114610b69576040519150601f19603f3d011682016040523d82523d5f602084013e610b6e565b606091505b5050905080610b7b575f80fd5b5050565b603b546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015610bc5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be99190613806565b1015610c4c5760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a20616d6f756e7420697320677265617465722060448201526b7468616e2062616c616e636560a01b6064820152608401610ae7565b603b546001600160a01b031663a9059cbb610c8e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b6020604051808303815f875af1158015610cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7b919061381d565b50565b610d08612a2c565b610d10612133565b15610d835760405162461bcd60e51b815260206004820152602560248201527f5374616b696e674472696674203a207374616b6520697320616c72656164792060448201527f6f70656e2e0000000000000000000000000000000000000000000000000000006064820152608401610ae7565b6044805461ff0019166101001790554260485581610da1575f610db8565b610dae826201518061384c565b610db89042613863565b6049556046819055610dc8612aa0565b604080518381526020810183905242918101919091527f6acc724939362f654a7dbb45feeec09c1ff28711ea30abf7c5a05a37cfc43e70906060015b60405180910390a15050565b610e18612a2c565b60018160ff161015610eb95760405162461bcd60e51b8152602060048201526044602482018190527f5374616b696e6744726966743a20626f6e7573206d756c7469706c6965722073908201527f686f756c642062652067726561746572207468616e206f7220657175616c732060648201527f746f203100000000000000000000000000000000000000000000000000000000608482015260a401610ae7565b60ff8116604a8190556040519081527f278d5c3334d0c365c63abf8aa4b35d4b0b1762530d646b6b13f99b3177b85491906020015b60405180910390a150565b6044545f9060ff1615610f0b57504790565b603b546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610f51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f759190613806565b905090565b610f82612a2c565b6001600160a01b038116610ffe5760405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a206e65774472696674546f6b656e206973206160448201527f207a65726f2061646472657373000000000000000000000000000000000000006064820152608401610ae7565b603a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fab1f2631b95f931423290f4c6b9fa98dee1d4da0b4267ee32ef40a027438ae0890602001610eee565b611061612a2c565b47156110f2575f6110997f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f81146110e0576040519150601f19603f3d011682016040523d82523d5f602084013e6110e5565b606091505b5050905080610cfd575f80fd5b60405162461bcd60e51b815260206004820152601660248201527f5374616b696e6744726966743a206e6f2066756e6473000000000000000000006044820152606401610ae7565b565b611144612a2c565b61114c612133565b15156001146111c35760405162461bcd60e51b815260206004820152602760248201527f5374616b696e674472696674203a207374616b6520697320616c72656164792060448201527f636c6f7365642e000000000000000000000000000000000000000000000000006064820152608401610ae7565b6044805461ff00191690554260498190556040519081527fc46bc112bb28b616434d6e89582a82bdc7cf9ef52a0b1228d20f5e5ccca7ec46906020015b60405180910390a1565b5f610f75612ac4565b61121b612b2a565b5f81116112815760405162461bcd60e51b815260206004820152602e60248201527f5374616b696e6744726966743a20616d6f756e74206d7573742062652067726560448201526d61746572207468616e207a65726f60901b6064820152608401610ae7565b61128a33612b83565b335f908152604b60205260409020805482111561130f5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e6744726966743a20696e73756666696369656e74207374616b6560448201527f642062616c616e636500000000000000000000000000000000000000000000006064820152608401610ae7565b604254156113775760425460018201546113299042612bcc565b10156113775760405162461bcd60e51b815260206004820152601f60248201527f5374616b696e6744726966743a20796f7572207374616b656420746f6b656e006044820152606401610ae7565b5f603e6002015461138c836001015442612bcc565b10611397575f6113b3565b620186a0604654846113a9919061384c565b6113b39190613876565b90505f6113c08285613895565b905083835f015f8282546113d49190613895565b925050819055508360455f8282546113ec9190613895565b909155506113fb905033612c18565b6039546001600160a01b03166379cc6790336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018790526044015f604051808303815f87803b158015611452575f80fd5b505af1158015611464573d5f803e3d5ffd5b505050505f82111561150157603a54603d546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303815f875af11580156114db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114ff919061381d565b505b603a546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af115801561155d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611581919061381d565b50505050610cfd6001600555565b611597612a2c565b603e839055603f82905560408181558051848152602081018490529081018290527f9d5e197714235d427ae6c0543814904f109a7a3a70046f3251686f6cf1bcff55906060015b60405180910390a1505050565b6115f3612b2a565b6115fc33612b83565b335f908152604b6020526040902060038101546116815760405162461bcd60e51b815260206004820152602160248201527f5374616b696e6744726966743a206e6f207265776172647320746f20636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610ae7565b61168a33612c18565b5061113a6001600555565b5f6116a1600283612dae565b92915050565b6116af612a2c565b5f6041556043805460ff191690556116c5612aa0565b6040514281527f6e1484348d28a5e4385cb314ce16d8f0a2cdd696d3b8258422e2199b2b96fceb90602001611200565b6116fd612a2c565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611741573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117659190613806565b11156110f257806001600160a01b031663a9059cbb6117ab7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156117ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118119190613806565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401610cbd565b61184a612a2c565b611855600282612dd2565b15610cfd576040516001600160a01b038216907f0a675452746933cefe3d74182e78db7afe57ba60eaa4234b5d85e9aa41b0610c905f90a250565b6038805461189d906138a8565b80601f01602080910402602001604051908101604052809291908181526020018280546118c9906138a8565b80156119145780601f106118eb57610100808354040283529160200191611914565b820191905f5260205f20905b8154815290600101906020018083116118f757829003601f168201915b505050505081565b6001600160a01b0381165f908152604b60205260408120819081908190816119438761280b565b509050815f015460485460485484600201541161196257604854611968565b83600201545b919750955093509150509193509193565b611981612a2c565b6001600160a01b0381166119fd5760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a206e657746656557616c6c657420697320612060448201527f7a65726f206164647265737300000000000000000000000000000000000000006064820152608401610ae7565b603d805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fc8a20c876b9c669362dc9e42a2b666585f6f54e625275434736b25d732f999a090602001610eee565b6060610f755f612de6565b611a6b612a2c565b5f8111611ad15760405162461bcd60e51b815260206004820152602e60248201527f5374616b696e6744726966743a20416d6f756e74206d7573742062652067726560448201526d61746572207468616e207a65726f60901b6064820152608401610ae7565b60445460ff1615611b5657803414611b515760405162461bcd60e51b815260206004820152602360248201527f5374616b696e6744726966743a20696e636f727265637420616d6f756e74207360448201527f656e7400000000000000000000000000000000000000000000000000000000006064820152608401610ae7565b611bde565b603b546001600160a01b03166323b872dd336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064016020604051808303815f875af1158015611bb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bdc919061381d565b505b610cfd612aa0565b611bee612a2c565b61113a5f612df2565b6060610f756002612de6565b611c0b612a2c565b6001600160a01b038116611c875760405162461bcd60e51b815260206004820152602f60248201527f5374616b696e6744726966743a206e657753744472696674546f6b656e20697360448201527f2061207a65726f206164647265737300000000000000000000000000000000006064820152608401610ae7565b6039805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fb6600342c49b45dfe55a55779ac7adc077bb13e35d9cc1ba4004a3a805344f5690602001610eee565b611cea612a2c565b604d55565b611cf7612133565b611d435760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e5481908110801590611d595750603f548111155b611db05760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b611db8612b2a565b60405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f7765642060448201526c199bdc881d1a1a5cc81c1bdbdb609a1b6064820152608401610ae7565b5f6116a18183612dae565b611e29612133565b611e755760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e5482908110801590611e8b5750603f548111155b611ee25760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b611eea612b2a565b335f908152604c602052604090205460ff16151560011480611f44575033611f397f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316145b611f905760405162461bcd60e51b815260206004820152601f60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f776564006044820152606401610ae7565b611f9b838333612e6f565b611fa482612b83565b611fae6001600555565b505050565b611fbb612a2c565b611fc55f8261300e565b15610cfd576040516001600160a01b038216907fe46fef8bbff1389d9010703cf8ebb363fb3daf5bf56edc27080b67bc8d9251ea905f90a250565b612008612a2c565b61201181611fb3565b610cfd815b61201e612a2c565b61202960028261300e565b15610cfd576040516001600160a01b038216907f92308bb7573b2a3d17ddb868b39d8ebec433f3194421abc22d084f89658c9bad905f90a250565b604e5460ff16156120b75760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610ae7565b6001600160a01b0382165f908152604c6020908152604091829020805460ff19166001908117909155604d849055825180840190935282527f3200000000000000000000000000000000000000000000000000000000000000908201526038906121219082613939565b5050604e805460ff1916600117905550565b6044545f9060ff6101009091041615156001148015610f755750604954421080610f755750506049541590565b612168612a2c565b6046829055604281905560408051838152602081018390527fef69957c47dd6a22ea5777b2523110960ea7bcd7a786eec305dae318e9276bb19101610e04565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156121f25750825b90505f8267ffffffffffffffff16600114801561220e5750303b155b90508115801561221c575080155b15612253576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561228757845468ff00000000000000001916680100000000000000001785555b60375460ff16156122da5760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610ae7565b6122e333613022565b8d603c5f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555089603d5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508c603a5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508b60395f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a603b5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508860445f6101000a81548160ff02191690831515021790555087603e600301819055505f88111561244c575f871161244c5760405162461bcd60e51b815260206004820152604260248201527f5374616b696e6744726966743a2072657761726420726174652070657220746f60448201527f6b656e207065722064617920726571756972656420666f722066697865642041606482015261505960f01b608482015260a401610ae7565b86156124655760478790556043805460ff191660011790555b5f19603f55601e604090815560428790556001604a819055815180830190925281527f310000000000000000000000000000000000000000000000000000000000000060208201526038906124ba9082613939565b506037805460ff19166001179055831561251357845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050505050565b61252b612133565b6125775760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e548590811080159061258d5750603f548111155b6125e45760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b6125ec612b2a565b603a546001600160a01b031663d505accf336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905260e4015f604051808303815f87803b158015612667575f80fd5b505af1158015612679573d5f803e3d5ffd5b505060405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f7765642060448201526c199bdc881d1a1a5cc81c1bdbdb609a1b60648201526084019150610ae79050565b505050505050565b6126ed612a2c565b6001600160a01b03811661272f576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610ae7565b610cfd81612df2565b612740612a2c565b5f604754116127c25760405162461bcd60e51b815260206004820152604260248201527f5374616b696e6744726966743a2072657761726420726174652070657220746f60448201527f6b656e207065722064617920726571756972656420666f722066697865642041606482015261505960f01b608482015260a401610ae7565b60418290556043805460ff1916600117905560478190556040517f4a335350be045922a3ebd54476afeff30cd29ca64c53b4b1cf15527549564a7b90610e049042815260200190565b6001600160a01b0381165f908152604b60205260408120604d54829190612832575f612870565b612870604d5482600201541161284a57604d54612850565b81600201545b5f6049541161285f5742612bcc565b61286b4260495461302b565b612bcc565b91505f808315612908576043546128b89060ff161515600114612894576014612897565b60125b6128a290600a613ad5565b600485015485546128b291613040565b9061304b565b6043549092506129059060ff1615156001146128d55760146128d8565b60125b6128e390600a613ad5565b6128b26128fd6128f4600189613895565b60475490613040565b865490613040565b90505b604a5461292e906129239061291d8486613056565b90613040565b600385015490613056565b9450505050915091565b612940612a2c565b61294a5f82612dd2565b15610cfd576040516001600160a01b038216907fed998b960f6340d045f620c119730f7aa7995e7425c2401d3a5b64ff998a59e9905f90a250565b61298d612a2c565b5f5b828110156129f9578160045f8686858181106129ad576129ad613ae3565b90506020020160208101906129c29190613579565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790556129f281613af7565b905061298f565b5060405181151581527f7dc357bd865f9219c544a8b0b14cb1583b26e3ffe765b3396ef2051d81a8de56906020016115de565b33612a5e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161461113a576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ae7565b60435460ff161515600103612ab157565b612abf618e946128b2612ac4565b604755565b5f612acd610ef9565b1580612ad95750604554155b15612ae357505f90565b60415415612af957604154610f7590606461384c565b5f604554612b0d612b08610ef9565b613061565b612b209068056bc75e2d6310000061384c565b6116a19190613876565b600260055403612b7c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ae7565b6002600555565b6001600160a01b0381165f908152604b60205260409020612ba2612aa0565b60455415612bba57612bb38261280b565b5060038201555b42600282015560475460049091015550565b5f8183101580612bda575082155b80612be3575081155b15612bef57505f6116a1565b5f612bfa8484613895565b90505f612c0f60186128b2603c81868261304b565b95945050505050565b6001600160a01b0381165f908152604b6020526040902060038101548015611fae575f600383015560445460ff1615612c6657612c55814761302b565b9050612c61838261317d565b612d66565b612ce1612c72826131d8565b603b546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612cb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cdc9190613806565b61302b565b603b549091506001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af1158015612d40573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d64919061381d565b505b826001600160a01b03167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a82604051612da191815260200190565b60405180910390a2505050565b6001600160a01b0381165f90815260018301602052604081205415155b9392505050565b5f612dcb836001600160a01b0384166132f6565b60605f612dcb836133d9565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b6001600160a01b038281165f908152604b602052604090819020603a5491517f23b872dd000000000000000000000000000000000000000000000000000000008152848416600482015230602482015260448101879052909291909116906323b872dd906064016020604051808303815f875af1158015612ef2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f16919061381d565b508360455f828254612f289190613863565b90915550508054849082905f90612f40908490613863565b90915550504260018201556039546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b158015612faf575f80fd5b505af1158015612fc1573d5f803e3d5ffd5b50505050826001600160a01b03167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8560405161300091815260200190565b60405180910390a250505050565b5f612dcb836001600160a01b038416613432565b610cfd8161347e565b5f8183106130395781612dcb565b5090919050565b5f612dcb828461384c565b5f612dcb8284613876565b5f612dcb8284613863565b6044545f9060ff166130e657603b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130e19190613b0f565b6130e9565b60125b6130f490600a613ad5565b603a5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613144573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131689190613b0f565b61317390600a613ad5565b612b20908461384c565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146131c6576040519150601f19603f3d011682016040523d82523d5f602084013e6131cb565b606091505b5050905080611fae575f80fd5b603a54604080517f313ce56700000000000000000000000000000000000000000000000000000000815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015613238573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061325c9190613b0f565b61326790600a613ad5565b60445460ff166132ea57603b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132e59190613b0f565b613168565b6131736012600a613ad5565b5f81815260018301602052604081205480156133d0575f613318600183613895565b85549091505f9061332b90600190613895565b905080821461338a575f865f01828154811061334957613349613ae3565b905f5260205f200154905080875f01848154811061336957613369613ae3565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061339b5761339b613b2a565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506116a1565b5f9150506116a1565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561342657602002820191905f5260205f20905b815481526020019060010190808311613412575b50505050509050919050565b5f81815260018301602052604081205461347757508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556116a1565b505f6116a1565b61348661348f565b610cfd816134f6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661113a576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126ed61348f565b5f6020828403121561350e575f80fd5b5035919050565b5f8060408385031215613526575f80fd5b50508035926020909101359150565b60ff81168114610cfd575f80fd5b5f60208284031215613553575f80fd5b8135612dcb81613535565b80356001600160a01b0381168114613574575f80fd5b919050565b5f60208284031215613589575f80fd5b612dcb8261355e565b5f805f606084860312156135a4575f80fd5b505081359360208301359350604090920135919050565b5f6020808352835180828501525f5b818110156135e6578581018301518582016040015282016135ca565b505f604082860101526040601f19601f8301168501019250505092915050565b602080825282518282018190525f9190848201906040850190845b818110156136465783516001600160a01b031683529284019291840191600101613621565b50909695505050505050565b5f8060408385031215613663575f80fd5b823591506136736020840161355e565b90509250929050565b5f806040838503121561368d575f80fd5b6136968361355e565b946020939093013593505050565b8015158114610cfd575f80fd5b5f805f805f805f805f6101208a8c0312156136ca575f80fd5b6136d38a61355e565b98506136e160208b0161355e565b97506136ef60408b0161355e565b96506136fd60608b0161355e565b955061370b60808b0161355e565b945060a08a013561371b816136a4565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b5f805f805f60a08688031215613756575f80fd5b8535945060208601359350604086013561376f81613535565b94979396509394606081013594506080013592915050565b5f805f60408486031215613799575f80fd5b833567ffffffffffffffff808211156137b0575f80fd5b818601915086601f8301126137c3575f80fd5b8135818111156137d1575f80fd5b8760208260051b85010111156137e5575f80fd5b602092830195509350508401356137fb816136a4565b809150509250925092565b5f60208284031215613816575f80fd5b5051919050565b5f6020828403121561382d575f80fd5b8151612dcb816136a4565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176116a1576116a1613838565b808201808211156116a1576116a1613838565b5f8261389057634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156116a1576116a1613838565b600181811c908216806138bc57607f821691505b6020821081036138da57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f821115611fae575f81815260208120601f850160051c8101602086101561391a5750805b601f850160051c820191505b818110156126dd57828155600101613926565b815167ffffffffffffffff811115613953576139536138e0565b6139678161396184546138a8565b846138f4565b602080601f83116001811461399a575f84156139835750858301515b5f19600386901b1c1916600185901b1785556126dd565b5f85815260208120601f198616915b828110156139c8578886015182559484019460019091019084016139a9565b50858210156139e557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b600181815b80851115613a2f57815f1904821115613a1557613a15613838565b80851615613a2257918102915b93841c93908002906139fa565b509250929050565b5f82613a45575060016116a1565b81613a5157505f6116a1565b8160018114613a675760028114613a7157613a8d565b60019150506116a1565b60ff841115613a8257613a82613838565b50506001821b6116a1565b5060208310610133831016604e8410600b8410161715613ab0575081810a6116a1565b613aba83836139f5565b805f1904821115613acd57613acd613838565b029392505050565b5f612dcb60ff841683613a37565b634e487b7160e01b5f52603260045260245ffd5b5f60018201613b0857613b08613838565b5060010190565b5f60208284031215613b1f575f80fd5b8151612dcb81613535565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220cba17edf99ca643d8d080d74a892478e47b55cfad642fa33c88fc5f15d7d791c64736f6c63430008140033
Deployed Bytecode
0x608060405260043610610349575f3560e01c80638aa28550116101b8578063d1c515ea116100f5578063f25f4b5611610099578063f7c618c11161006b578063f7c618c1146109df578063f81094f3146109fe578063fb2f349214610a1d578063fe575a8714610a3c57005b8063f25f4b561461094e578063f2fde38b1461096d578063f6b96d7f1461098c578063f6ed2017146109ab57005b8063def533f3116100d2578063def533f3146108dc578063df4b2d3a146108f1578063e0b3d4f814610910578063ecd9ba821461092f57005b8063d1c515ea14610894578063db313a09146108a9578063dbb0170b146108bd57005b8063aa271e1a1161015c578063c45a015511610139578063c45a015514610818578063c630948d14610837578063c64d0ebc14610856578063ccd8af221461087557005b8063aa271e1a146107bb578063aceccf8f146107da578063c2e3273d146107f957005b80638ea97d26116101955780638ea97d2614610753578063968bcfcf146107685780639852868a14610787578063a694fc3a1461079c57005b80638aa28550146106a65780638cc01fdc146106bb5780638da5cb5b1461071757005b80634e94e5f9116102865780636e19f9531161022a5780637b0a47ee116102075780637b0a47ee14610649578063817b1cd21461065e57806386fe8b431461067357806388e319611461068757005b80636e19f953146105eb5780636f21b676146105fe578063715018a61461063557005b8063627c8b2a11610263578063627c8b2a1461053e5780636386c1c71461056c57806366718524146105ab5780636b32810b146105ca57005b80634e94e5f9146104df5780634f5632f8146104fe57806354fd4d501461051d57005b8063283f13fe116102ed57806336a0f8a5116102ca57806336a0f8a514610479578063372500ab146104985780634334614a146104ac5780634b0fefe9146104cb57005b8063283f13fe146104325780632a648300146104465780632e17de781461045a57005b8063158ef93e11610326578063158ef93e146103af5780631e9b3a92146103dd5780631fdb28f0146103ff578063255412fb1461041e57005b80630a861f2a14610352578063128bfcae14610371578063130c69e81461039057005b3661035057005b005b34801561035d575f80fd5b5061035061036c3660046134fe565b610a73565b34801561037c575f80fd5b5061035061038b366004613515565b610d00565b34801561039b575f80fd5b506103506103aa366004613543565b610e10565b3480156103ba575f80fd5b506037546103c89060ff1681565b60405190151581526020015b60405180910390f35b3480156103e8575f80fd5b506103f1610ef9565b6040519081526020016103d4565b34801561040a575f80fd5b50610350610419366004613579565b610f7a565b348015610429575f80fd5b50610350611059565b34801561043d575f80fd5b5061035061113c565b348015610451575f80fd5b506103f161120a565b348015610465575f80fd5b506103506104743660046134fe565b611213565b348015610484575f80fd5b50610350610493366004613592565b61158f565b3480156104a3575f80fd5b506103506115eb565b3480156104b7575f80fd5b506103c86104c6366004613579565b611695565b3480156104d6575f80fd5b506103506116a7565b3480156104ea575f80fd5b506103506104f9366004613579565b6116f5565b348015610509575f80fd5b50610350610518366004613579565b611842565b348015610528575f80fd5b50610531611890565b6040516103d491906135bb565b348015610549575f80fd5b506103c8610558366004613579565b604c6020525f908152604090205460ff1681565b348015610577575f80fd5b5061058b610586366004613579565b61191c565b6040805194855260208501939093529183015260608201526080016103d4565b3480156105b6575f80fd5b506103506105c5366004613579565b611979565b3480156105d5575f80fd5b506105de611a58565b6040516103d49190613606565b6103506105f93660046134fe565b611a63565b348015610609575f80fd5b50603a5461061d906001600160a01b031681565b6040516001600160a01b0390911681526020016103d4565b348015610640575f80fd5b50610350611be6565b348015610654575f80fd5b506103f160475481565b348015610669575f80fd5b506103f160455481565b34801561067e575f80fd5b506105de611bf7565b348015610692575f80fd5b506103506106a1366004613579565b611c03565b3480156106b1575f80fd5b506103f1604a5481565b3480156106c6575f80fd5b50603e54603f546040546041546042546043546106e895949392919060ff1686565b6040805196875260208701959095529385019290925260608401526080830152151560a082015260c0016103d4565b348015610722575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031661061d565b34801561075e575f80fd5b506103f160465481565b348015610773575f80fd5b506103506107823660046134fe565b611ce2565b348015610792575f80fd5b506103f1604d5481565b3480156107a7575f80fd5b506103506107b63660046134fe565b611cef565b3480156107c6575f80fd5b506103c86107d5366004613579565b611e16565b3480156107e5575f80fd5b506103506107f4366004613652565b611e21565b348015610804575f80fd5b50610350610813366004613579565b611fb3565b348015610823575f80fd5b50603c5461061d906001600160a01b031681565b348015610842575f80fd5b50610350610851366004613579565b612000565b348015610861575f80fd5b50610350610870366004613579565b612016565b348015610880575f80fd5b5061035061088f36600461367c565b612064565b34801561089f575f80fd5b506103f160485481565b3480156108b4575f80fd5b506103c8612133565b3480156108c8575f80fd5b5060395461061d906001600160a01b031681565b3480156108e7575f80fd5b506103f160495481565b3480156108fc575f80fd5b5061035061090b366004613515565b612160565b34801561091b575f80fd5b5061035061092a3660046136b1565b6121a8565b34801561093a575f80fd5b50610350610949366004613742565b612523565b348015610959575f80fd5b50603d5461061d906001600160a01b031681565b348015610978575f80fd5b50610350610987366004613579565b6126e5565b348015610997575f80fd5b506103506109a6366004613515565b612738565b3480156109b6575f80fd5b506109ca6109c5366004613579565b61280b565b604080519283526020830191909152016103d4565b3480156109ea575f80fd5b50603b5461061d906001600160a01b031681565b348015610a09575f80fd5b50610350610a18366004613579565b612938565b348015610a28575f80fd5b50610350610a37366004613787565b612985565b348015610a47575f80fd5b506103c8610a56366004613579565b6001600160a01b03165f9081526004602052604090205460ff1690565b610a7b612a2c565b60445460ff1615610b7f5780471015610af05760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a20616d6f756e7420697320677265617465722060448201526b7468616e2062616c616e636560a01b60648201526084015b60405180910390fd5b5f610b227f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f8114610b69576040519150601f19603f3d011682016040523d82523d5f602084013e610b6e565b606091505b5050905080610b7b575f80fd5b5050565b603b546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015610bc5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be99190613806565b1015610c4c5760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a20616d6f756e7420697320677265617465722060448201526b7468616e2062616c616e636560a01b6064820152608401610ae7565b603b546001600160a01b031663a9059cbb610c8e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044015b6020604051808303815f875af1158015610cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7b919061381d565b50565b610d08612a2c565b610d10612133565b15610d835760405162461bcd60e51b815260206004820152602560248201527f5374616b696e674472696674203a207374616b6520697320616c72656164792060448201527f6f70656e2e0000000000000000000000000000000000000000000000000000006064820152608401610ae7565b6044805461ff0019166101001790554260485581610da1575f610db8565b610dae826201518061384c565b610db89042613863565b6049556046819055610dc8612aa0565b604080518381526020810183905242918101919091527f6acc724939362f654a7dbb45feeec09c1ff28711ea30abf7c5a05a37cfc43e70906060015b60405180910390a15050565b610e18612a2c565b60018160ff161015610eb95760405162461bcd60e51b8152602060048201526044602482018190527f5374616b696e6744726966743a20626f6e7573206d756c7469706c6965722073908201527f686f756c642062652067726561746572207468616e206f7220657175616c732060648201527f746f203100000000000000000000000000000000000000000000000000000000608482015260a401610ae7565b60ff8116604a8190556040519081527f278d5c3334d0c365c63abf8aa4b35d4b0b1762530d646b6b13f99b3177b85491906020015b60405180910390a150565b6044545f9060ff1615610f0b57504790565b603b546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610f51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f759190613806565b905090565b610f82612a2c565b6001600160a01b038116610ffe5760405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a206e65774472696674546f6b656e206973206160448201527f207a65726f2061646472657373000000000000000000000000000000000000006064820152608401610ae7565b603a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fab1f2631b95f931423290f4c6b9fa98dee1d4da0b4267ee32ef40a027438ae0890602001610eee565b611061612a2c565b47156110f2575f6110997f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f81146110e0576040519150601f19603f3d011682016040523d82523d5f602084013e6110e5565b606091505b5050905080610cfd575f80fd5b60405162461bcd60e51b815260206004820152601660248201527f5374616b696e6744726966743a206e6f2066756e6473000000000000000000006044820152606401610ae7565b565b611144612a2c565b61114c612133565b15156001146111c35760405162461bcd60e51b815260206004820152602760248201527f5374616b696e674472696674203a207374616b6520697320616c72656164792060448201527f636c6f7365642e000000000000000000000000000000000000000000000000006064820152608401610ae7565b6044805461ff00191690554260498190556040519081527fc46bc112bb28b616434d6e89582a82bdc7cf9ef52a0b1228d20f5e5ccca7ec46906020015b60405180910390a1565b5f610f75612ac4565b61121b612b2a565b5f81116112815760405162461bcd60e51b815260206004820152602e60248201527f5374616b696e6744726966743a20616d6f756e74206d7573742062652067726560448201526d61746572207468616e207a65726f60901b6064820152608401610ae7565b61128a33612b83565b335f908152604b60205260409020805482111561130f5760405162461bcd60e51b815260206004820152602960248201527f5374616b696e6744726966743a20696e73756666696369656e74207374616b6560448201527f642062616c616e636500000000000000000000000000000000000000000000006064820152608401610ae7565b604254156113775760425460018201546113299042612bcc565b10156113775760405162461bcd60e51b815260206004820152601f60248201527f5374616b696e6744726966743a20796f7572207374616b656420746f6b656e006044820152606401610ae7565b5f603e6002015461138c836001015442612bcc565b10611397575f6113b3565b620186a0604654846113a9919061384c565b6113b39190613876565b90505f6113c08285613895565b905083835f015f8282546113d49190613895565b925050819055508360455f8282546113ec9190613895565b909155506113fb905033612c18565b6039546001600160a01b03166379cc6790336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018790526044015f604051808303815f87803b158015611452575f80fd5b505af1158015611464573d5f803e3d5ffd5b505050505f82111561150157603a54603d546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303815f875af11580156114db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114ff919061381d565b505b603a546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af115801561155d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611581919061381d565b50505050610cfd6001600555565b611597612a2c565b603e839055603f82905560408181558051848152602081018490529081018290527f9d5e197714235d427ae6c0543814904f109a7a3a70046f3251686f6cf1bcff55906060015b60405180910390a1505050565b6115f3612b2a565b6115fc33612b83565b335f908152604b6020526040902060038101546116815760405162461bcd60e51b815260206004820152602160248201527f5374616b696e6744726966743a206e6f207265776172647320746f20636c616960448201527f6d000000000000000000000000000000000000000000000000000000000000006064820152608401610ae7565b61168a33612c18565b5061113a6001600555565b5f6116a1600283612dae565b92915050565b6116af612a2c565b5f6041556043805460ff191690556116c5612aa0565b6040514281527f6e1484348d28a5e4385cb314ce16d8f0a2cdd696d3b8258422e2199b2b96fceb90602001611200565b6116fd612a2c565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611741573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117659190613806565b11156110f257806001600160a01b031663a9059cbb6117ab7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156117ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118119190613806565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401610cbd565b61184a612a2c565b611855600282612dd2565b15610cfd576040516001600160a01b038216907f0a675452746933cefe3d74182e78db7afe57ba60eaa4234b5d85e9aa41b0610c905f90a250565b6038805461189d906138a8565b80601f01602080910402602001604051908101604052809291908181526020018280546118c9906138a8565b80156119145780601f106118eb57610100808354040283529160200191611914565b820191905f5260205f20905b8154815290600101906020018083116118f757829003601f168201915b505050505081565b6001600160a01b0381165f908152604b60205260408120819081908190816119438761280b565b509050815f015460485460485484600201541161196257604854611968565b83600201545b919750955093509150509193509193565b611981612a2c565b6001600160a01b0381166119fd5760405162461bcd60e51b815260206004820152602c60248201527f5374616b696e6744726966743a206e657746656557616c6c657420697320612060448201527f7a65726f206164647265737300000000000000000000000000000000000000006064820152608401610ae7565b603d805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fc8a20c876b9c669362dc9e42a2b666585f6f54e625275434736b25d732f999a090602001610eee565b6060610f755f612de6565b611a6b612a2c565b5f8111611ad15760405162461bcd60e51b815260206004820152602e60248201527f5374616b696e6744726966743a20416d6f756e74206d7573742062652067726560448201526d61746572207468616e207a65726f60901b6064820152608401610ae7565b60445460ff1615611b5657803414611b515760405162461bcd60e51b815260206004820152602360248201527f5374616b696e6744726966743a20696e636f727265637420616d6f756e74207360448201527f656e7400000000000000000000000000000000000000000000000000000000006064820152608401610ae7565b611bde565b603b546001600160a01b03166323b872dd336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064016020604051808303815f875af1158015611bb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bdc919061381d565b505b610cfd612aa0565b611bee612a2c565b61113a5f612df2565b6060610f756002612de6565b611c0b612a2c565b6001600160a01b038116611c875760405162461bcd60e51b815260206004820152602f60248201527f5374616b696e6744726966743a206e657753744472696674546f6b656e20697360448201527f2061207a65726f206164647265737300000000000000000000000000000000006064820152608401610ae7565b6039805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fb6600342c49b45dfe55a55779ac7adc077bb13e35d9cc1ba4004a3a805344f5690602001610eee565b611cea612a2c565b604d55565b611cf7612133565b611d435760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e5481908110801590611d595750603f548111155b611db05760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b611db8612b2a565b60405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f7765642060448201526c199bdc881d1a1a5cc81c1bdbdb609a1b6064820152608401610ae7565b5f6116a18183612dae565b611e29612133565b611e755760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e5482908110801590611e8b5750603f548111155b611ee25760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b611eea612b2a565b335f908152604c602052604090205460ff16151560011480611f44575033611f397f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316145b611f905760405162461bcd60e51b815260206004820152601f60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f776564006044820152606401610ae7565b611f9b838333612e6f565b611fa482612b83565b611fae6001600555565b505050565b611fbb612a2c565b611fc55f8261300e565b15610cfd576040516001600160a01b038216907fe46fef8bbff1389d9010703cf8ebb363fb3daf5bf56edc27080b67bc8d9251ea905f90a250565b612008612a2c565b61201181611fb3565b610cfd815b61201e612a2c565b61202960028261300e565b15610cfd576040516001600160a01b038216907f92308bb7573b2a3d17ddb868b39d8ebec433f3194421abc22d084f89658c9bad905f90a250565b604e5460ff16156120b75760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610ae7565b6001600160a01b0382165f908152604c6020908152604091829020805460ff19166001908117909155604d849055825180840190935282527f3200000000000000000000000000000000000000000000000000000000000000908201526038906121219082613939565b5050604e805460ff1916600117905550565b6044545f9060ff6101009091041615156001148015610f755750604954421080610f755750506049541590565b612168612a2c565b6046829055604281905560408051838152602081018390527fef69957c47dd6a22ea5777b2523110960ea7bcd7a786eec305dae318e9276bb19101610e04565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156121f25750825b90505f8267ffffffffffffffff16600114801561220e5750303b155b90508115801561221c575080155b15612253576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561228757845468ff00000000000000001916680100000000000000001785555b60375460ff16156122da5760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610ae7565b6122e333613022565b8d603c5f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555089603d5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508c603a5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508b60395f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a603b5f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508860445f6101000a81548160ff02191690831515021790555087603e600301819055505f88111561244c575f871161244c5760405162461bcd60e51b815260206004820152604260248201527f5374616b696e6744726966743a2072657761726420726174652070657220746f60448201527f6b656e207065722064617920726571756972656420666f722066697865642041606482015261505960f01b608482015260a401610ae7565b86156124655760478790556043805460ff191660011790555b5f19603f55601e604090815560428790556001604a819055815180830190925281527f310000000000000000000000000000000000000000000000000000000000000060208201526038906124ba9082613939565b506037805460ff19166001179055831561251357845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050505050565b61252b612133565b6125775760405162461bcd60e51b815260206004820152601e60248201527f5374616b696e6744726966743a207374616b65206e6f74206f70656e656400006044820152606401610ae7565b603e548590811080159061258d5750603f548111155b6125e45760405162461bcd60e51b815260206004820152602260248201527f5374616b696e6744726966743a20696e76616c6964207374616b6520616d6f756044820152611b9d60f21b6064820152608401610ae7565b6125ec612b2a565b603a546001600160a01b031663d505accf336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905260e4015f604051808303815f87803b158015612667575f80fd5b505af1158015612679573d5f803e3d5ffd5b505060405162461bcd60e51b815260206004820152602d60248201527f5374616b696e6744726966743a205374616b65206e6f7420616c6c6f7765642060448201526c199bdc881d1a1a5cc81c1bdbdb609a1b60648201526084019150610ae79050565b505050505050565b6126ed612a2c565b6001600160a01b03811661272f576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610ae7565b610cfd81612df2565b612740612a2c565b5f604754116127c25760405162461bcd60e51b815260206004820152604260248201527f5374616b696e6744726966743a2072657761726420726174652070657220746f60448201527f6b656e207065722064617920726571756972656420666f722066697865642041606482015261505960f01b608482015260a401610ae7565b60418290556043805460ff1916600117905560478190556040517f4a335350be045922a3ebd54476afeff30cd29ca64c53b4b1cf15527549564a7b90610e049042815260200190565b6001600160a01b0381165f908152604b60205260408120604d54829190612832575f612870565b612870604d5482600201541161284a57604d54612850565b81600201545b5f6049541161285f5742612bcc565b61286b4260495461302b565b612bcc565b91505f808315612908576043546128b89060ff161515600114612894576014612897565b60125b6128a290600a613ad5565b600485015485546128b291613040565b9061304b565b6043549092506129059060ff1615156001146128d55760146128d8565b60125b6128e390600a613ad5565b6128b26128fd6128f4600189613895565b60475490613040565b865490613040565b90505b604a5461292e906129239061291d8486613056565b90613040565b600385015490613056565b9450505050915091565b612940612a2c565b61294a5f82612dd2565b15610cfd576040516001600160a01b038216907fed998b960f6340d045f620c119730f7aa7995e7425c2401d3a5b64ff998a59e9905f90a250565b61298d612a2c565b5f5b828110156129f9578160045f8686858181106129ad576129ad613ae3565b90506020020160208101906129c29190613579565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790556129f281613af7565b905061298f565b5060405181151581527f7dc357bd865f9219c544a8b0b14cb1583b26e3ffe765b3396ef2051d81a8de56906020016115de565b33612a5e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161461113a576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ae7565b60435460ff161515600103612ab157565b612abf618e946128b2612ac4565b604755565b5f612acd610ef9565b1580612ad95750604554155b15612ae357505f90565b60415415612af957604154610f7590606461384c565b5f604554612b0d612b08610ef9565b613061565b612b209068056bc75e2d6310000061384c565b6116a19190613876565b600260055403612b7c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ae7565b6002600555565b6001600160a01b0381165f908152604b60205260409020612ba2612aa0565b60455415612bba57612bb38261280b565b5060038201555b42600282015560475460049091015550565b5f8183101580612bda575082155b80612be3575081155b15612bef57505f6116a1565b5f612bfa8484613895565b90505f612c0f60186128b2603c81868261304b565b95945050505050565b6001600160a01b0381165f908152604b6020526040902060038101548015611fae575f600383015560445460ff1615612c6657612c55814761302b565b9050612c61838261317d565b612d66565b612ce1612c72826131d8565b603b546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612cb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cdc9190613806565b61302b565b603b549091506001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af1158015612d40573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d64919061381d565b505b826001600160a01b03167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a82604051612da191815260200190565b60405180910390a2505050565b6001600160a01b0381165f90815260018301602052604081205415155b9392505050565b5f612dcb836001600160a01b0384166132f6565b60605f612dcb836133d9565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b6001600160a01b038281165f908152604b602052604090819020603a5491517f23b872dd000000000000000000000000000000000000000000000000000000008152848416600482015230602482015260448101879052909291909116906323b872dd906064016020604051808303815f875af1158015612ef2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f16919061381d565b508360455f828254612f289190613863565b90915550508054849082905f90612f40908490613863565b90915550504260018201556039546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b158015612faf575f80fd5b505af1158015612fc1573d5f803e3d5ffd5b50505050826001600160a01b03167f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d8560405161300091815260200190565b60405180910390a250505050565b5f612dcb836001600160a01b038416613432565b610cfd8161347e565b5f8183106130395781612dcb565b5090919050565b5f612dcb828461384c565b5f612dcb8284613876565b5f612dcb8284613863565b6044545f9060ff166130e657603b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130e19190613b0f565b6130e9565b60125b6130f490600a613ad5565b603a5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613144573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131689190613b0f565b61317390600a613ad5565b612b20908461384c565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146131c6576040519150601f19603f3d011682016040523d82523d5f602084013e6131cb565b606091505b5050905080611fae575f80fd5b603a54604080517f313ce56700000000000000000000000000000000000000000000000000000000815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015613238573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061325c9190613b0f565b61326790600a613ad5565b60445460ff166132ea57603b5f9054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132e59190613b0f565b613168565b6131736012600a613ad5565b5f81815260018301602052604081205480156133d0575f613318600183613895565b85549091505f9061332b90600190613895565b905080821461338a575f865f01828154811061334957613349613ae3565b905f5260205f200154905080875f01848154811061336957613369613ae3565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061339b5761339b613b2a565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506116a1565b5f9150506116a1565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561342657602002820191905f5260205f20905b815481526020019060010190808311613412575b50505050509050919050565b5f81815260018301602052604081205461347757508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556116a1565b505f6116a1565b61348661348f565b610cfd816134f6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661113a576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126ed61348f565b5f6020828403121561350e575f80fd5b5035919050565b5f8060408385031215613526575f80fd5b50508035926020909101359150565b60ff81168114610cfd575f80fd5b5f60208284031215613553575f80fd5b8135612dcb81613535565b80356001600160a01b0381168114613574575f80fd5b919050565b5f60208284031215613589575f80fd5b612dcb8261355e565b5f805f606084860312156135a4575f80fd5b505081359360208301359350604090920135919050565b5f6020808352835180828501525f5b818110156135e6578581018301518582016040015282016135ca565b505f604082860101526040601f19601f8301168501019250505092915050565b602080825282518282018190525f9190848201906040850190845b818110156136465783516001600160a01b031683529284019291840191600101613621565b50909695505050505050565b5f8060408385031215613663575f80fd5b823591506136736020840161355e565b90509250929050565b5f806040838503121561368d575f80fd5b6136968361355e565b946020939093013593505050565b8015158114610cfd575f80fd5b5f805f805f805f805f6101208a8c0312156136ca575f80fd5b6136d38a61355e565b98506136e160208b0161355e565b97506136ef60408b0161355e565b96506136fd60608b0161355e565b955061370b60808b0161355e565b945060a08a013561371b816136a4565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b5f805f805f60a08688031215613756575f80fd5b8535945060208601359350604086013561376f81613535565b94979396509394606081013594506080013592915050565b5f805f60408486031215613799575f80fd5b833567ffffffffffffffff808211156137b0575f80fd5b818601915086601f8301126137c3575f80fd5b8135818111156137d1575f80fd5b8760208260051b85010111156137e5575f80fd5b602092830195509350508401356137fb816136a4565b809150509250925092565b5f60208284031215613816575f80fd5b5051919050565b5f6020828403121561382d575f80fd5b8151612dcb816136a4565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176116a1576116a1613838565b808201808211156116a1576116a1613838565b5f8261389057634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156116a1576116a1613838565b600181811c908216806138bc57607f821691505b6020821081036138da57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f821115611fae575f81815260208120601f850160051c8101602086101561391a5750805b601f850160051c820191505b818110156126dd57828155600101613926565b815167ffffffffffffffff811115613953576139536138e0565b6139678161396184546138a8565b846138f4565b602080601f83116001811461399a575f84156139835750858301515b5f19600386901b1c1916600185901b1785556126dd565b5f85815260208120601f198616915b828110156139c8578886015182559484019460019091019084016139a9565b50858210156139e557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b600181815b80851115613a2f57815f1904821115613a1557613a15613838565b80851615613a2257918102915b93841c93908002906139fa565b509250929050565b5f82613a45575060016116a1565b81613a5157505f6116a1565b8160018114613a675760028114613a7157613a8d565b60019150506116a1565b60ff841115613a8257613a82613838565b50506001821b6116a1565b5060208310610133831016604e8410600b8410161715613ab0575081810a6116a1565b613aba83836139f5565b805f1904821115613acd57613acd613838565b029392505050565b5f612dcb60ff841683613a37565b634e487b7160e01b5f52603260045260245ffd5b5f60018201613b0857613b08613838565b5060010190565b5f60208284031215613b1f575f80fd5b8151612dcb81613535565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220cba17edf99ca643d8d080d74a892478e47b55cfad642fa33c88fc5f15d7d791c64736f6c63430008140033
Deployed Bytecode Sourcemap
73135:470:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64060:607;;;;;;;;;;-1:-1:-1;64060:607:0;;;;;:::i;:::-;;:::i;60557:557::-;;;;;;;;;;-1:-1:-1;60557:557:0;;;;;:::i;:::-;;:::i;53809:314::-;;;;;;;;;;-1:-1:-1;53809:314:0;;;;;:::i;:::-;;:::i;49025:31::-;;;;;;;;;;-1:-1:-1;49025:31:0;;;;;;;;;;;984:14:1;;977:22;959:41;;947:2;932:18;49025:31:0;;;;;;;;67237:205;;;;;;;;;;;;;:::i;:::-;;;1157:25:1;;;1145:2;1130:18;67237:205:0;1011:177:1;54293:273:0;;;;;;;;;;-1:-1:-1;54293:273:0;;;;;:::i;:::-;;:::i;64791:284::-;;;;;;;;;;;;;:::i;61231:249::-;;;;;;;;;;;;;:::i;62933:97::-;;;;;;;;;;;;;:::i;58222:1093::-;;;;;;;;;;-1:-1:-1;58222:1093:0;;;;;:::i;:::-;;:::i;62478:407::-;;;;;;;;;;-1:-1:-1;62478:407:0;;;;;:::i;:::-;;:::i;59402:287::-;;;;;;;;;;;;;:::i;36397:113::-;;;;;;;;;;-1:-1:-1;36397:113:0;;;;;:::i;:::-;;:::i;55564:203::-;;;;;;;;;;;;;:::i;65235:326::-;;;;;;;;;;-1:-1:-1;65235:326:0;;;;;:::i;:::-;;:::i;35221:162::-;;;;;;;;;;-1:-1:-1;35221:162:0;;;;;:::i;:::-;;:::i;49063:21::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;72853:57::-;;;;;;;;;;-1:-1:-1;72853:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;63279:612;;;;;;;;;;-1:-1:-1;63279:612:0;;;;;:::i;:::-;;:::i;:::-;;;;2690:25:1;;;2746:2;2731:18;;2724:34;;;;2774:18;;;2767:34;2832:2;2817:18;;2810:34;2677:3;2662:19;63279:612:0;2459:391:1;55189:262:0;;;;;;;;;;-1:-1:-1;55189:262:0;;;;;:::i;:::-;;:::i;35690:105::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;59853:396::-;;;;;;:::i;:::-;;:::i;49185:28::-;;;;;;;;;;-1:-1:-1;49185:28:0;;;;-1:-1:-1;;;;;49185:28:0;;;;;;-1:-1:-1;;;;;3724:55:1;;;3706:74;;3694:2;3679:18;49185:28:0;3541:245:1;17331:103:0;;;;;;;;;;;;;:::i;49762:25::-;;;;;;;;;;;;;;;;49635:26;;;;;;;;;;;;;;;;35863:105;;;;;;;;;;;;;:::i;54735:295::-;;;;;;;;;;-1:-1:-1;54735:295:0;;;;;:::i;:::-;;:::i;50060:31::-;;;;;;;;;;;;;;;;49443:26;;;;;;;;;;-1:-1:-1;49443:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;4072:25:1;;;4128:2;4113:18;;4106:34;;;;4156:18;;;4149:34;;;;4214:2;4199:18;;4192:34;4257:3;4242:19;;4235:35;4314:14;4307:22;4301:3;4286:19;;4279:51;4059:3;4044:19;49443:26:0;3791:545:1;16596:147:0;;;;;;;;;;-1:-1:-1;15427:22:0;16727:8;-1:-1:-1;;;;;16727:8:0;16596:147;;49690:25;;;;;;;;;;;;;;;;72975:153;;;;;;;;;;-1:-1:-1;72975:153:0;;;;;:::i;:::-;;:::i;72917:49::-;;;;;;;;;;;;;;;;57855:239;;;;;;;;;;-1:-1:-1;57855:239:0;;;;;:::i;:::-;;:::i;36126:113::-;;;;;;;;;;-1:-1:-1;36126:113:0;;;;;:::i;:::-;;:::i;57368:381::-;;;;;;;;;;-1:-1:-1;57368:381:0;;;;;:::i;:::-;;:::i;34200:158::-;;;;;;;;;;-1:-1:-1;34200:158:0;;;;;:::i;:::-;;:::i;49299:22::-;;;;;;;;;;-1:-1:-1;49299:22:0;;;;-1:-1:-1;;;;;49299:22:0;;;33866:159;;;;;;;;;;-1:-1:-1;33866:159:0;;;;;:::i;:::-;;:::i;34533:158::-;;;;;;;;;;-1:-1:-1;34533:158:0;;;;;:::i;:::-;;:::i;73219:377::-;;;;;;;;;;-1:-1:-1;73219:377:0;;;;;:::i;:::-;;:::i;49859:38::-;;;;;;;;;;;;;;;;65640:158;;;;;;;;;;;;;:::i;49093:30::-;;;;;;;;;;-1:-1:-1;49093:30:0;;;;-1:-1:-1;;;;;49093:30:0;;;49944:35;;;;;;;;;;;;;;;;61790:298;;;;;;;;;;-1:-1:-1;61790:298:0;;;;;:::i;:::-;;:::i;52235:1259::-;;;;;;;;;;-1:-1:-1;52235:1259:0;;;;;:::i;:::-;;:::i;56729:435::-;;;;;;;;;;-1:-1:-1;56729:435:0;;;;;:::i;:::-;;:::i;49348:32::-;;;;;;;;;;-1:-1:-1;49348:32:0;;;;-1:-1:-1;;;;;49348:32:0;;;17589:220;;;;;;;;;;-1:-1:-1;17589:220:0;;;;;:::i;:::-;;:::i;56022:359::-;;;;;;;;;;-1:-1:-1;56022:359:0;;;;;:::i;:::-;;:::i;66062:1109::-;;;;;;;;;;-1:-1:-1;66062:1109:0;;;;;:::i;:::-;;:::i;:::-;;;;6982:25:1;;;7038:2;7023:18;;7016:34;;;;6955:18;66062:1109:0;6808:248:1;49247:29:0;;;;;;;;;;-1:-1:-1;49247:29:0;;;;-1:-1:-1;;;;;49247:29:0;;;34875:162;;;;;;;;;;-1:-1:-1;34875:162:0;;;;;:::i;:::-;;:::i;33366:294::-;;;;;;;;;;-1:-1:-1;33366:294:0;;;;;:::i;:::-;;:::i;35502:120::-;;;;;;;;;;-1:-1:-1;35502:120:0;;;;;:::i;:::-;-1:-1:-1;;;;;35588:26:0;35564:4;35588:26;;;:16;:26;;;;;;;;;35502:120;64060:607;16482:13;:11;:13::i;:::-;64136:8:::1;::::0;::::1;;64132:528;;;64212:7;64187:21;:32;;64161:138;;;::::0;-1:-1:-1;;;64161:138:0;;8018:2:1;64161:138:0::1;::::0;::::1;8000:21:1::0;8057:2;8037:18;;;8030:30;8096:34;8076:18;;;8069:62;-1:-1:-1;;;8147:18:1;;;8140:42;8199:19;;64161:138:0::1;;;;;;;;;64315:7;64336;15427:22:::0;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;64336:7:::1;-1:-1:-1::0;;;;;64328:21:0::1;64357;64328:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64314:69;;;64406:2;64398:11;;;::::0;::::1;;64146:275;64060:607:::0;:::o;64132:528::-:1;64468:11;::::0;:36:::1;::::0;-1:-1:-1;;;64468:36:0;;64498:4:::1;64468:36;::::0;::::1;3706:74:1::0;64508:7:0;;-1:-1:-1;;;;;64468:11:0::1;::::0;:21:::1;::::0;3679:18:1;;64468:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;64442:153;;;::::0;-1:-1:-1;;;64442:153:0;;8018:2:1;64442:153:0::1;::::0;::::1;8000:21:1::0;8057:2;8037:18;;;8030:30;8096:34;8076:18;;;8069:62;-1:-1:-1;;;8147:18:1;;;8140:42;8199:19;;64442:153:0::1;7816:408:1::0;64442:153:0::1;64610:11;::::0;-1:-1:-1;;;;;64610:11:0::1;:20;64631:7;15427:22:::0;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;64631:7:::1;64610:38;::::0;-1:-1:-1;;;;;;64610:38:0::1;::::0;;;;;;-1:-1:-1;;;;;8820:55:1;;;64610:38:0::1;::::0;::::1;8802:74:1::0;8892:18;;;8885:34;;;8775:18;;64610:38:0::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;64132:528::-;64060:607:::0;:::o;60557:557::-;16482:13;:11;:13::i;:::-;60696::::1;:11;:13::i;:::-;:22;60688:72;;;::::0;-1:-1:-1;;;60688:72:0;;9382:2:1;60688:72:0::1;::::0;::::1;9364:21:1::0;9421:2;9401:18;;;9394:30;9460:34;9440:18;;;9433:62;9531:7;9511:18;;;9504:35;9556:19;;60688:72:0::1;9180:401:1::0;60688:72:0::1;60771:9;:16:::0;;-1:-1:-1;;60771:16:0::1;;;::::0;;60820:15:::1;60798:19;:37:::0;60865:27;:86:::1;;60950:1;60865:86;;;60914:32;:23:::0;60940:6:::1;60914:32;:::i;:::-;60895:52;::::0;:15:::1;:52;:::i;:::-;60846:16;:105:::0;60962:10:::1;:28:::0;;;61001:21:::1;:19;:21::i;:::-;61038:68;::::0;;10280:25:1;;;10336:2;10321:18;;10314:34;;;61090:15:0::1;10364:18:1::0;;;10357:34;;;;61038:68:0::1;::::0;10268:2:1;10253:18;61038:68:0::1;;;;;;;;60557:557:::0;;:::o;53809:314::-;16482:13;:11;:13::i;:::-;53926:1:::1;53911:11;:16;;;;53889:134;;;::::0;-1:-1:-1;;;53889:134:0;;10604:2:1;53889:134:0::1;::::0;::::1;10586:21:1::0;10643:2;10623:18;;;10616:30;;;10682:34;10662:18;;;10655:62;10753:34;10733:18;;;10726:62;10825:6;10804:19;;;10797:35;10849:19;;53889:134:0::1;10402:472:1::0;53889:134:0::1;54034:30;::::0;::::1;:16;:30:::0;;;54080:35:::1;::::0;11021:36:1;;;54080:35:0::1;::::0;11009:2:1;10994:18;54080:35:0::1;;;;;;;;53809:314:::0;:::o;67237:205::-;67316:8;;67292:7;;67316:8;;67312:69;;;-1:-1:-1;67348:21:0;;67237:205::o;67312:69::-;67398:11;;:36;;-1:-1:-1;;;67398:36:0;;67428:4;67398:36;;;3706:74:1;-1:-1:-1;;;;;67398:11:0;;;;:21;;3679:18:1;;67398:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67391:43;;67237:205;:::o;54293:273::-;16482:13;:11;:13::i;:::-;-1:-1:-1;;;;;54381:28:0;::::1;54373:86;;;::::0;-1:-1:-1;;;54373:86:0;;11270:2:1;54373:86:0::1;::::0;::::1;11252:21:1::0;11309:2;11289:18;;;11282:30;11348:34;11328:18;;;11321:62;11419:15;11399:18;;;11392:43;11452:19;;54373:86:0::1;11068:409:1::0;54373:86:0::1;54470:10;:39:::0;;-1:-1:-1;;54470:39:0::1;-1:-1:-1::0;;;;;54470:39:0;::::1;::::0;;::::1;::::0;;;54525:33:::1;::::0;3706:74:1;;;54525:33:0::1;::::0;3694:2:1;3679:18;54525:33:0::1;3541:245:1::0;64791:284:0;16482:13;:11;:13::i;:::-;64854:21:::1;:25:::0;64850:218:::1;;64897:7;64918;15427:22:::0;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;64918:7:::1;-1:-1:-1::0;;;;;64910:21:0::1;64939;64910:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64896:69;;;64988:2;64980:11;;;::::0;::::1;64850:218;65024:32;::::0;-1:-1:-1;;;65024:32:0;;11684:2:1;65024:32:0::1;::::0;::::1;11666:21:1::0;11723:2;11703:18;;;11696:30;11762:24;11742:18;;;11735:52;11804:18;;65024:32:0::1;11482:346:1::0;64850:218:0::1;64791:284::o:0;61231:249::-;16482:13;:11;:13::i;:::-;61290::::1;:11;:13::i;:::-;:21;;61307:4;61290:21;61282:73;;;::::0;-1:-1:-1;;;61282:73:0;;12035:2:1;61282:73:0::1;::::0;::::1;12017:21:1::0;12074:2;12054:18;;;12047:30;12113:34;12093:18;;;12086:62;12184:9;12164:18;;;12157:37;12211:19;;61282:73:0::1;11833:403:1::0;61282:73:0::1;61366:9;:17:::0;;-1:-1:-1;;61366:17:0::1;::::0;;61413:15:::1;61394:16;:34:::0;;;61444:28:::1;::::0;1157:25:1;;;61444:28:0::1;::::0;1145:2:1;1130:18;61444:28:0::1;;;;;;;;61231:249::o:0;62933:97::-;62980:7;63007:15;:13;:15::i;58222:1093::-;11762:21;:19;:21::i;:::-;58307:1:::1;58297:7;:11;58289:70;;;::::0;-1:-1:-1;;;58289:70:0;;12443:2:1;58289:70:0::1;::::0;::::1;12425:21:1::0;12482:2;12462:18;;;12455:30;12521:34;12501:18;;;12494:62;-1:-1:-1;;;12572:18:1;;;12565:44;12626:19;;58289:70:0::1;12241:410:1::0;58289:70:0::1;58370:26;13927:10:::0;58370:12:::1;:26::i;:::-;13927:10:::0;58409:14:::1;58426:19:::0;;;:5:::1;:19;::::0;;;;58466:15;;:26;-1:-1:-1;58466:26:0::1;58458:80;;;::::0;-1:-1:-1;;;58458:80:0;;12858:2:1;58458:80:0::1;::::0;::::1;12840:21:1::0;12897:2;12877:18;;;12870:30;12936:34;12916:18;;;12909:62;13007:11;12987:18;;;12980:39;13036:19;;58458:80:0::1;12656:405:1::0;58458:80:0::1;58554:21:::0;;:25;58551:169:::1;;58651:21:::0;;58613:16:::1;::::0;::::1;::::0;58604:43:::1;::::0;58631:15:::1;58604:8;:43::i;:::-;:68;;58596:112;;;::::0;-1:-1:-1;;;58596:112:0;;13268:2:1;58596:112:0::1;::::0;::::1;13250:21:1::0;13307:2;13287:18;;;13280:30;13346:33;13326:18;;;13319:61;13397:18;;58596:112:0::1;13066:355:1::0;58596:112:0::1;58732:19;58800:9;:24;;;58754:43;58763:1;:16;;;58781:15;58754:8;:43::i;:::-;:70;:133;;58886:1;58754:133;;;58865:5;58851:10;;58841:7;:20;;;;:::i;:::-;58840:30;;;;:::i;:::-;58732:155:::0;-1:-1:-1;58898:22:0::1;58923:21;58732:155:::0;58923:7;:21:::1;:::i;:::-;58898:46;;58974:7;58955:1;:15;;;:26;;;;;;;:::i;:::-;;;;;;;;59007:7;58992:11;;:22;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;59027:30:0::1;::::0;-1:-1:-1;13927:10:0;59027:16:::1;:30::i;:::-;59102:12;::::0;-1:-1:-1;;;;;59102:12:0::1;:21;13927:10:::0;59102:44:::1;::::0;-1:-1:-1;;;;;;59102:44:0::1;::::0;;;;;;-1:-1:-1;;;;;8820:55:1;;;59102:44:0::1;::::0;::::1;8802:74:1::0;8892:18;;;8885:34;;;8775:18;;59102:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;59175:1;59161:11;:15;59157:91;;;59193:10;::::0;59213:9:::1;::::0;59193:43:::1;::::0;;;;-1:-1:-1;;;;;59213:9:0;;::::1;59193:43;::::0;::::1;8802:74:1::0;8892:18;;;8885:34;;;59193:10:0;::::1;::::0;:19:::1;::::0;8775:18:1;;59193:43:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;59157:91;59258:10;::::0;-1:-1:-1;;;;;59258:10:0::1;:19;13927:10:::0;59258:49:::1;::::0;-1:-1:-1;;;;;;59258:49:0::1;::::0;;;;;;-1:-1:-1;;;;;8820:55:1;;;59258:49:0::1;::::0;::::1;8802:74:1::0;8892:18;;;8885:34;;;8775:18;;59258:49:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;58278:1037;;;11806:20:::0;11023:1;12326:7;:22;12143:213;62478:407;16482:13;:11;:13::i;:::-;62644:9:::1;:41:::0;;;62696:22;:41;;;62748:24;:45;;;62809:68;;10280:25:1;;;10336:2;10321:18;;10314:34;;;10364:18;;;10357:34;;;62809:68:0::1;::::0;10268:2:1;10253:18;62809:68:0::1;;;;;;;;62478:407:::0;;;:::o;59402:287::-;11762:21;:19;:21::i;:::-;59459:26:::1;13927:10:::0;58370:12:::1;:26::i;59459:::-;13927:10:::0;59527:14:::1;59544:19:::0;;;:5:::1;:19;::::0;;;;59582:16:::1;::::0;::::1;::::0;59574:66:::1;;;::::0;-1:-1:-1;;;59574:66:0;;14350:2:1;59574:66:0::1;::::0;::::1;14332:21:1::0;14389:2;14369:18;;;14362:30;14428:34;14408:18;;;14401:62;14499:3;14479:18;;;14472:31;14520:19;;59574:66:0::1;14148:397:1::0;59574:66:0::1;59651:30;13927:10:::0;59027:16:::1;:30::i;59651:::-;59448:241;11806:20:::0;11023:1;12326:7;:22;12143:213;36397:113;36452:4;36476:26;:9;36495:6;36476:18;:26::i;:::-;36469:33;36397:113;-1:-1:-1;;36397:113:0:o;55564:203::-;16482:13;:11;:13::i;:::-;55638:1:::1;55617:18:::0;:22;55650:25;:33;;-1:-1:-1;;55650:33:0::1;::::0;;55694:21:::1;:19;:21::i;:::-;55731:28;::::0;55743:15:::1;1157:25:1::0;;55731:28:0::1;::::0;1145:2:1;1130:18;55731:28:0::1;1011:177:1::0;65235:326:0;16482:13;:11;:13::i;:::-;65323:46:::1;::::0;-1:-1:-1;;;65323:46:0;;65363:4:::1;65323:46;::::0;::::1;3706:74:1::0;65372:1:0::1;::::0;-1:-1:-1;;;;;65323:31:0;::::1;::::0;::::1;::::0;3679:18:1;;65323:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;65319:235;;;65397:13;-1:-1:-1::0;;;;;65390:30:0::1;;65421:7;15427:22:::0;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;65421:7:::1;65430:46;::::0;-1:-1:-1;;;65430:46:0;;65470:4:::1;65430:46;::::0;::::1;3706:74:1::0;-1:-1:-1;;;;;65430:31:0;::::1;::::0;::::1;::::0;3679:18:1;;65430:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65390:87;::::0;-1:-1:-1;;;;;;65390:87:0::1;::::0;;;;;;-1:-1:-1;;;;;8820:55:1;;;65390:87:0::1;::::0;::::1;8802:74:1::0;8892:18;;;8885:34;8775:18;;65390:87:0::1;8628:297:1::0;35221:162:0;16482:13;:11;:13::i;:::-;35293:24:::1;:9;35310:6:::0;35293:16:::1;:24::i;:::-;35289:87;;;35339:25;::::0;-1:-1:-1;;;;;35339:25:0;::::1;::::0;::::1;::::0;;;::::1;35221:162:::0;:::o;49063:21::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;63279:612::-;-1:-1:-1;;;;;63566:19:0;;63386:21;63566:19;;;:5;:19;;;;;63386:21;;;;;;;63626:31;63572:12;63626:17;:31::i;:::-;63596:61;;;63690:4;:18;;;63723:19;;63779;;63757:4;:19;;;:41;:85;;63823:19;;63757:85;;;63801:4;:19;;;63757:85;63668:215;;-1:-1:-1;63668:215:0;-1:-1:-1;63668:215:0;-1:-1:-1;63857:15:0;-1:-1:-1;;63279:612:0;;;;;:::o;55189:262::-;16482:13;:11;:13::i;:::-;-1:-1:-1;;;;;55275:27:0;::::1;55267:84;;;::::0;-1:-1:-1;;;55267:84:0;;15194:2:1;55267:84:0::1;::::0;::::1;15176:21:1::0;15233:2;15213:18;;;15206:30;15272:34;15252:18;;;15245:62;15343:14;15323:18;;;15316:42;15375:19;;55267:84:0::1;14992:408:1::0;55267:84:0::1;55362:9;:34:::0;;-1:-1:-1;;55362:34:0::1;-1:-1:-1::0;;;;;55362:34:0;::::1;::::0;;::::1;::::0;;;55412:31:::1;::::0;3706:74:1;;;55412:31:0::1;::::0;3694:2:1;3679:18;55412:31:0::1;3541:245:1::0;35690:105:0;35733:16;35769:18;:9;:16;:18::i;59853:396::-;16482:13;:11;:13::i;:::-;59945:1:::1;59936:6;:10;59928:69;;;::::0;-1:-1:-1;;;59928:69:0;;15607:2:1;59928:69:0::1;::::0;::::1;15589:21:1::0;15646:2;15626:18;;;15619:30;15685:34;15665:18;;;15658:62;-1:-1:-1;;;15736:18:1;;;15729:44;15790:19;;59928:69:0::1;15405:410:1::0;59928:69:0::1;60012:8;::::0;::::1;;60008:202;;;60058:6;60045:9;:19;60037:67;;;::::0;-1:-1:-1;;;60037:67:0;;16022:2:1;60037:67:0::1;::::0;::::1;16004:21:1::0;16061:2;16041:18;;;16034:30;16100:34;16080:18;;;16073:62;16171:5;16151:18;;;16144:33;16194:19;;60037:67:0::1;15820:399:1::0;60037:67:0::1;60008:202;;;60137:11;::::0;-1:-1:-1;;;;;60137:11:0::1;:24;13927:10:::0;60137:61:::1;::::0;-1:-1:-1;;;;;;60137:61:0::1;::::0;;;;;;-1:-1:-1;;;;;16505:15:1;;;60137:61:0::1;::::0;::::1;16487:34:1::0;60184:4:0::1;16537:18:1::0;;;16530:43;16589:18;;;16582:34;;;16399:18;;60137:61:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;60008:202;60220:21;:19;:21::i;17331:103::-:0;16482:13;:11;:13::i;:::-;17396:30:::1;17423:1;17396:18;:30::i;35863:105::-:0;35906:16;35942:18;:9;:16;:18::i;54735:295::-;16482:13;:11;:13::i;:::-;-1:-1:-1;;;;;54830:30:0;::::1;54822:90;;;::::0;-1:-1:-1;;;54822:90:0;;16829:2:1;54822:90:0::1;::::0;::::1;16811:21:1::0;16868:2;16848:18;;;16841:30;16907:34;16887:18;;;16880:62;16978:17;16958:18;;;16951:45;17013:19;;54822:90:0::1;16627:411:1::0;54822:90:0::1;54923:12;:43:::0;;-1:-1:-1;;54923:43:0::1;-1:-1:-1::0;;;;;54923:43:0;::::1;::::0;;::::1;::::0;;;54982:40:::1;::::0;3706:74:1;;;54982:40:0::1;::::0;3694:2:1;3679:18;54982:40:0::1;3541:245:1::0;72975:153:0;16482:13;:11;:13::i;:::-;73074:30:::1;:46:::0;72975:153::o;57855:239::-;50502:13;:11;:13::i;:::-;50494:56;;;;-1:-1:-1;;;50494:56:0;;17245:2:1;50494:56:0;;;17227:21:1;17284:2;17264:18;;;17257:30;17323:32;17303:18;;;17296:60;17373:18;;50494:56:0;17043:354:1;50494:56:0;50316:9:::1;:22:::0;57915:7;;50305:33;::::1;::::0;::::1;::::0;:70:::1;;-1:-1:-1::0;50353:22:0;;50342:33;::::1;;50305:70;50283:154;;;::::0;-1:-1:-1;;;50283:154:0;;17604:2:1;50283:154:0::1;::::0;::::1;17586:21:1::0;17643:2;17623:18;;;17616:30;17682:34;17662:18;;;17655:62;-1:-1:-1;;;17733:18:1;;;17726:32;17775:19;;50283:154:0::1;17402:398:1::0;50283:154:0::1;11762:21:::2;:19;:21::i;:::-;57948:55:::3;::::0;-1:-1:-1;;;57948:55:0;;18007:2:1;57948:55:0::3;::::0;::::3;17989:21:1::0;18046:2;18026:18;;;18019:30;18085:34;18065:18;;;18058:62;-1:-1:-1;;;18136:18:1;;;18129:43;18189:19;;57948:55:0::3;17805:409:1::0;36126:113:0;36181:4;36205:26;36181:4;36224:6;36205:18;:26::i;57368:381::-;50502:13;:11;:13::i;:::-;50494:56;;;;-1:-1:-1;;;50494:56:0;;17245:2:1;50494:56:0;;;17227:21:1;17284:2;17264:18;;;17257:30;17323:32;17303:18;;;17296:60;17373:18;;50494:56:0;17043:354:1;50494:56:0;50316:9:::1;:22:::0;57485:7;;50305:33;::::1;::::0;::::1;::::0;:70:::1;;-1:-1:-1::0;50353:22:0;;50342:33;::::1;;50305:70;50283:154;;;::::0;-1:-1:-1;;;50283:154:0;;17604:2:1;50283:154:0::1;::::0;::::1;17586:21:1::0;17643:2;17623:18;;;17616:30;17682:34;17662:18;;;17655:62;-1:-1:-1;;;17733:18:1;;;17726:32;17775:19;;50283:154:0::1;17402:398:1::0;50283:154:0::1;11762:21:::2;:19;:21::i;:::-;13927:10:::0;57540:39:::3;::::0;;;:25:::3;:39;::::0;;;;;::::3;;:47;;:39:::0;:47:::3;::::0;:74:::3;;-1:-1:-1::0;13927:10:0;57591:7:::3;15427:22:::0;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;57591:7:::3;-1:-1:-1::0;;;;;57591:23:0::3;;57540:74;57532:118;;;::::0;-1:-1:-1;;;57532:118:0;;18421:2:1;57532:118:0::3;::::0;::::3;18403:21:1::0;18460:2;18440:18;;;18433:30;18499:33;18479:18;;;18472:61;18550:18;;57532:118:0::3;18219:355:1::0;57532:118:0::3;57661:43;57668:7:::0;57677:12;13927:10;57661:6:::3;:43::i;:::-;57715:26;57728:12;57715;:26::i;:::-;11806:20:::2;11023:1:::0;12326:7;:22;12143:213;11806:20:::2;50561:1:::1;57368:381:::0;;:::o;34200:158::-;16482:13;:11;:13::i;:::-;34271:21:::1;:9;34285:6:::0;34271:13:::1;:21::i;:::-;34267:84;;;34314:25;::::0;-1:-1:-1;;;;;34314:25:0;::::1;::::0;::::1;::::0;;;::::1;34200:158:::0;:::o;33866:159::-;16482:13;:11;:13::i;:::-;33950:28:::1;33964:13;33950;:28::i;:::-;33989;34003:13;34533:158:::0;16482:13;:11;:13::i;:::-;34604:21:::1;:9;34618:6:::0;34604:13:::1;:21::i;:::-;34600:84;;;34647:25;::::0;-1:-1:-1;;;;;34647:25:0;::::1;::::0;::::1;::::0;;;::::1;34533:158:::0;:::o;73219:377::-;73358:14;;;;73357:15;73349:47;;;;-1:-1:-1;;;73349:47:0;;18781:2:1;73349:47:0;;;18763:21:1;18820:2;18800:18;;;18793:30;18859:21;18839:18;;;18832:49;18898:18;;73349:47:0;18579:343:1;73349:47:0;-1:-1:-1;;;;;73409:39:0;;;;;;:25;:39;;;;;;;;;:46;;-1:-1:-1;;73409:46:0;73451:4;73409:46;;;;;;73466:30;:64;;;73543:13;;;;;;;;;;;;;;;:7;;:13;;:7;:13;:::i;:::-;-1:-1:-1;;73567:14:0;:21;;-1:-1:-1;;73567:21:0;73584:4;73567:21;;;-1:-1:-1;73219:377:0:o;65640:158::-;65708:9;;65684:4;;65708:9;;;;;;:17;;:9;:17;:82;;;;;65748:16;;65730:15;:34;:59;;;-1:-1:-1;;65768:16:0;;:21;;65640:158::o;61790:298::-;16482:13;:11;:13::i;:::-;61914:10:::1;:31:::0;;;61956:21;:40;;;62012:68:::1;::::0;;6982:25:1;;;7038:2;7023:18;;7016:34;;;62012:68:0::1;::::0;6955:18:1;62012:68:0::1;6808:248:1::0;52235:1259:0;9141:21;4457:15;;;;;;;4456:16;;4504:14;;4310:30;4889:16;;:34;;;;;4909:14;4889:34;4869:54;;4934:17;4954:11;:16;;4969:1;4954:16;:50;;;;-1:-1:-1;4982:4:0;4974:25;:30;4954:50;4934:70;;5022:12;5021:13;:30;;;;;5039:12;5038:13;5021:30;5017:93;;;5075:23;;;;;;;;;;;;;;5017:93;5120:18;;-1:-1:-1;;5120:18:0;5137:1;5120:18;;;5149:69;;;;5184:22;;-1:-1:-1;;5184:22:0;;;;;5149:69;52595:11:::1;::::0;::::1;;52594:12;52586:44;;;::::0;-1:-1:-1;;;52586:44:0;;18781:2:1;52586:44:0::1;::::0;::::1;18763:21:1::0;18820:2;18800:18;;;18793:30;18859:21;18839:18;;;18832:49;18898:18;;52586:44:0::1;18579:343:1::0;52586:44:0::1;52643:37;13927:10:::0;52643:23:::1;:37::i;:::-;52703:8;52693:7;;:18;;;;;-1:-1:-1::0;;;;;52693:18:0::1;;;;;-1:-1:-1::0;;;;;52693:18:0::1;;;;;;52742:10;52722:9;;:31;;;;;-1:-1:-1::0;;;;;52722:31:0::1;;;;;-1:-1:-1::0;;;;;52722:31:0::1;;;;;;52788:11;52764:10;;:36;;;;;-1:-1:-1::0;;;;;52764:36:0::1;;;;;-1:-1:-1::0;;;;;52764:36:0::1;;;;;;52837:13;52811:12;;:40;;;;;-1:-1:-1::0;;;;;52811:40:0::1;;;;;-1:-1:-1::0;;;;;52811:40:0::1;;;;;;52887:12;52862:11;;:38;;;;;-1:-1:-1::0;;;;;52862:38:0::1;;;;;-1:-1:-1::0;;;;;52862:38:0::1;;;;;;52922:20;52911:8;;:31;;;;;;;;;;;;;;;;;;52974:9;52953;:18;;:30;;;;53009:1;52997:9;:13;52994:139;;;53049:1;53035:11;:15;53027:94;;;::::0;-1:-1:-1;;;53027:94:0;;21522:2:1;53027:94:0::1;::::0;::::1;21504:21:1::0;21561:2;21541:18;;;21534:30;21600:34;21580:18;;;21573:62;21671:34;21651:18;;;21644:62;-1:-1:-1;;;21722:19:1;;;21715:33;21765:19;;53027:94:0::1;21320:470:1::0;53027:94:0::1;53146:15:::0;;53143:118:::1;;53178:10;:24:::0;;;53217:25;:32;;-1:-1:-1;;53217:32:0::1;53245:4;53217:32;::::0;;53143:118:::1;-1:-1:-1::0;;53271:22:0;:42;53351:2:::1;53324:24:::0;:29;;;53364:21;:36;;;53271:22:::1;53411:16;:20:::0;;;53444:13;;;;::::1;::::0;;;;;::::1;;::::0;::::1;::::0;:7:::1;::::0;:13:::1;::::0;:7;:13:::1;:::i;:::-;-1:-1:-1::0;53468:11:0::1;:18:::0;;-1:-1:-1;;53468:18:0::1;53482:4;53468:18;::::0;;5240:104;;;;5275:23;;-1:-1:-1;;5275:23:0;;;5318:14;;-1:-1:-1;21948:50:1;;5318:14:0;;21936:2:1;21921:18;5318:14:0;;;;;;;5240:104;4242:1109;;;;;52235:1259;;;;;;;;;:::o;56729:435::-;50502:13;:11;:13::i;:::-;50494:56;;;;-1:-1:-1;;;50494:56:0;;17245:2:1;50494:56:0;;;17227:21:1;17284:2;17264:18;;;17257:30;17323:32;17303:18;;;17296:60;17373:18;;50494:56:0;17043:354:1;50494:56:0;50316:9:::1;:22:::0;56900:7;;50305:33;::::1;::::0;::::1;::::0;:70:::1;;-1:-1:-1::0;50353:22:0;;50342:33;::::1;;50305:70;50283:154;;;::::0;-1:-1:-1;;;50283:154:0;;17604:2:1;50283:154:0::1;::::0;::::1;17586:21:1::0;17643:2;17623:18;;;17616:30;17682:34;17662:18;;;17655:62;-1:-1:-1;;;17733:18:1;;;17726:32;17775:19;;50283:154:0::1;17402:398:1::0;50283:154:0::1;11762:21:::2;:19;:21::i;:::-;56933:10:::3;::::0;-1:-1:-1;;;;;56933:10:0::3;:17;13927:10:::0;56933:74:::3;::::0;-1:-1:-1;;;;;;56933:74:0::3;::::0;;;;;;-1:-1:-1;;;;;22399:15:1;;;56933:74:0::3;::::0;::::3;22381:34:1::0;56973:4:0::3;22431:18:1::0;;;22424:43;22483:18;;;22476:34;;;22526:18;;;22519:34;;;22602:4;22590:17;;22569:19;;;22562:46;22624:19;;;22617:35;;;22668:19;;;22661:35;;;22292:19;;56933:74:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;-1:-1:-1::0;;57018:55:0::3;::::0;-1:-1:-1;;;57018:55:0;;18007:2:1;57018:55:0::3;::::0;::::3;17989:21:1::0;18046:2;18026:18;;;18019:30;18085:34;18065:18;;;18058:62;-1:-1:-1;;;18136:18:1;;;18129:43;18189:19;;;-1:-1:-1;57018:55:0::3;::::0;-1:-1:-1;17805:409:1;11806:20:0::2;50561:1:::1;56729:435:::0;;;;;:::o;17589:220::-;16482:13;:11;:13::i;:::-;-1:-1:-1;;;;;17674:22:0;::::1;17670:93;;17720:31;::::0;::::1;::::0;;17748:1:::1;17720:31;::::0;::::1;3706:74:1::0;3679:18;;17720:31:0::1;3541:245:1::0;17670:93:0::1;17773:28;17792:8;17773:18;:28::i;56022:359::-:0;16482:13;:11;:13::i;:::-;56136:1:::1;56123:10;;:14;56115:93;;;::::0;-1:-1:-1;;;56115:93:0;;21522:2:1;56115:93:0::1;::::0;::::1;21504:21:1::0;21561:2;21541:18;;;21534:30;21600:34;21580:18;;;21573:62;21671:34;21651:18;;;21644:62;-1:-1:-1;;;21722:19:1;;;21715:33;21765:19;;56115:93:0::1;21320:470:1::0;56115:93:0::1;56219:18:::0;:32;;;56262:25;:32;;-1:-1:-1;;56262:32:0::1;56290:4;56262:32;::::0;;56305:10:::1;:24:::0;;;56345:28:::1;::::0;::::1;::::0;::::1;::::0;56357:15:::1;1157:25:1::0;;1145:2;1130:18;;1011:177;66062:1109:0;-1:-1:-1;;;;;66204:19:0;;66132:22;66204:19;;;:5;:19;;;;;66247:30;;66132:22;;66204:19;66247:270;;66516:1;66247:270;;;66284:229;66326:30;;66307:1;:16;;;:49;:101;;66378:30;;66307:101;;;66359:1;:16;;;66307:101;66442:1;66423:16;;:20;:79;;66487:15;66284:8;:229::i;66423:79::-;66446:38;66450:15;66467:16;;66446:3;:38::i;:::-;66284:8;:229::i;:::-;66234:283;-1:-1:-1;66528:49:0;;66640:14;;66636:388;;66776:25;;66715:120;;66776:25;;:33;;:25;:33;:43;;66817:2;66776:43;;;66812:2;66776:43;66771:49;;:2;:49;:::i;:::-;66735:12;;;;66715:15;;:33;;:19;:33::i;:::-;:37;;:120::i;:::-;66953:25;;66671:164;;-1:-1:-1;66874:138:0;;66953:25;;:33;;:25;:33;:43;;66994:2;66953:43;;;66989:2;66953:43;66948:49;;:2;:49;:::i;:::-;66874:51;66894:30;66909:14;66922:1;66909:10;:14;:::i;:::-;66894:10;;;:14;:30::i;:::-;66874:15;;;:19;:51::i;:138::-;66850:162;;66636:388;67145:16;;67051:112;;67072:90;;:68;:21;67098:41;67072:25;:68::i;:::-;:72;;:90::i;:::-;67051:16;;;;;:20;:112::i;:::-;67034:129;;66176:995;;;66062:1109;;;:::o;34875:162::-;16482:13;:11;:13::i;:::-;34947:24:::1;:9;34964:6:::0;34947:16:::1;:24::i;:::-;34943:87;;;34993:25;::::0;-1:-1:-1;;;;;34993:25:0;::::1;::::0;::::1;::::0;;;::::1;34875:162:::0;:::o;33366:294::-;16482:13;:11;:13::i;:::-;33509:9:::1;33504:109;33520:20:::0;;::::1;33504:109;;;33595:6;33562:16;:30;33579:9;;33589:1;33579:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;33562:30:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;33562:30:0;:39;;-1:-1:-1;;33562:39:0::1;::::0;::::1;;::::0;;;::::1;::::0;;33542:3:::1;::::0;::::1;:::i;:::-;;;33504:109;;;-1:-1:-1::0;33628:24:0::1;::::0;984:14:1;;977:22;959:41;;33628:24:0::1;::::0;947:2:1;932:18;33628:24:0::1;819:187:1::0;16821:166:0;13927:10;16881:7;15427:22;16727:8;-1:-1:-1;;;;;16727:8:0;;16596:147;16881:7;-1:-1:-1;;;;;16881:23:0;;16877:103;;16928:40;;;;;13927:10;16928:40;;;3706:74:1;3679:18;;16928:40:0;3541:245:1;70342:185:0;70396:25;;;;:33;;:25;:33;70393:71;;70342:185::o;70393:71::-;70487:32;70507:11;70487:15;:13;:15::i;:32::-;70474:10;:45;70342:185::o;71529:388::-;71577:7;71601:24;:22;:24::i;:::-;:29;;:49;;-1:-1:-1;71634:11:0;;:16;71601:49;71597:90;;;-1:-1:-1;71674:1:0;;71529:388::o;71597:90::-;71703:18;;:22;71699:88;;71749:18;;:26;;71770:5;71749:26;:::i;71699:88::-;71799:11;71876;;71815:48;71838:24;:22;:24::i;:::-;71815:22;:48::i;:::-;:57;;71866:6;71815:57;:::i;:::-;71814:73;;;;:::i;11842:293::-;11067:1;11976:7;;:19;11968:63;;;;-1:-1:-1;;;11968:63:0;;24621:2:1;11968:63:0;;;24603:21:1;24660:2;24640:18;;;24633:30;24699:33;24679:18;;;24672:61;24750:18;;11968:63:0;24419:355:1;11968:63:0;11067:1;12109:7;:18;11842:293::o;69787:423::-;-1:-1:-1;;;;;69868:19:0;;69851:14;69868:19;;;:5;:19;;;;;69898:21;:19;:21::i;:::-;69967:11;;:15;69963:132;;70022:31;70040:12;70022:17;:31::i;:::-;-1:-1:-1;70000:16:0;;;69999:54;69963:132;70124:15;70105:16;;;:34;70192:10;;70177:12;;;;:25;-1:-1:-1;69787:423:0:o;72399:442::-;72518:7;72567:15;72547:16;:35;;:60;;;-1:-1:-1;72586:21:0;;72547:60;:84;;;-1:-1:-1;72611:20:0;;72547:84;72543:125;;;-1:-1:-1;72655:1:0;72648:8;;72543:125;72678:17;72698:34;72716:16;72698:15;:34;:::i;:::-;72678:54;-1:-1:-1;72743:21:0;72767:33;72797:2;72767:25;72789:2;72767:25;72678:54;72789:2;72767:13;:17::i;:33::-;72743:57;72399:442;-1:-1:-1;;;;;72399:442:0:o;68590:646::-;-1:-1:-1;;;;;68675:19:0;;68658:14;68675:19;;;:5;:19;;;;;68722:16;;;;68753:10;;68749:480;;68799:1;68780:16;;;:20;68841:8;;;;68837:332;;;68879:34;68883:6;68891:21;68879:3;:34::i;:::-;68870:43;;68932:37;68948:12;68962:6;68932:15;:37::i;:::-;68837:332;;;69019:73;69023:30;69046:6;69023:22;:30::i;:::-;69055:11;;:36;;-1:-1:-1;;;69055:36:0;;69085:4;69055:36;;;3706:74:1;-1:-1:-1;;;;;69055:11:0;;;;:21;;3679:18:1;;69055:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69019:3;:73::i;:::-;69111:11;;69010:82;;-1:-1:-1;;;;;;69111:11:0;:20;13927:10;69111:42;;-1:-1:-1;;;;;;69111:42:0;;;;;;;-1:-1:-1;;;;;8820:55:1;;;69111:42:0;;;8802:74:1;8892:18;;;8885:34;;;8775:18;;69111:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;68837:332;69196:12;-1:-1:-1;;;;;69188:29:0;;69210:6;69188:29;;;;1157:25:1;;1145:2;1130:18;;1011:177;69188:29:0;;;;;;;;68647:589;;68590:646;:::o;27396:167::-;-1:-1:-1;;;;;27530:23:0;;27476:4;22746:21;;;:14;;;:21;;;;;;:26;;27500:55;27493:62;27396:167;-1:-1:-1;;;27396:167:0:o;27152:158::-;27225:4;27249:53;27257:3;-1:-1:-1;;;;;27277:23:0;;27249:7;:53::i;28828:310::-;28891:16;28920:22;28945:19;28953:3;28945:7;:19::i;17969:253::-;15427:22;18120:8;;-1:-1:-1;;18139:19:0;;-1:-1:-1;;;;;18139:19:0;;;;;;;;18174:40;;18120:8;;;;;18174:40;;18043:24;;18174:40;18032:190;;17969:253;:::o;67998:450::-;-1:-1:-1;;;;;68141:19:0;;;68124:14;68141:19;;;:5;:19;;;;;;;68171:10;;:56;;;;;16505:15:1;;;68171:56:0;;;16487:34:1;68212:4:0;16537:18:1;;;16530:43;16589:18;;;16582:34;;;68141:19:0;;68171:10;;;;;:23;;16399:18:1;;68171:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;68253:7;68238:11;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;68271:26:0;;68290:7;;68271:1;;:15;;:26;;68290:7;;68271:26;:::i;:::-;;;;-1:-1:-1;;68327:15:0;68308:16;;;:34;68355:12;;:40;;;;;-1:-1:-1;;;;;8820:55:1;;;68355:40:0;;;8802:74:1;8892:18;;;8885:34;;;68355:12:0;;;;:17;;8775:18:1;;68355:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68418:12;-1:-1:-1;;;;;68411:29:0;;68432:7;68411:29;;;;1157:25:1;;1145:2;1130:18;;1011:177;68411:29:0;;;;;;;;68113:335;67998:450;;;:::o;26824:152::-;26894:4;26918:50;26923:3;-1:-1:-1;;;;;26943:23:0;;26918:4;:50::i;33049:113::-;33125:29;33140:13;33125:14;:29::i;72103:106::-;72161:7;72192:1;72188;:5;:13;;72200:1;72188:13;;;-1:-1:-1;72196:1:0;;72103:106;-1:-1:-1;72103:106:0:o;40131:98::-;40189:7;40216:5;40220:1;40216;:5;:::i;40530:98::-;40588:7;40615:5;40619:1;40615;:5;:::i;39393:98::-;39451:7;39478:5;39482:1;39478;:5;:::i;71137:260::-;71322:8;;71208:18;;71322:8;;:38;;71338:11;;;;;;;;;-1:-1:-1;;;;;71338:11:0;-1:-1:-1;;;;;71338:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71322:38;;;71333:2;71322:38;71317:44;;:2;:44;:::i;:::-;71279:10;;;;;;;;;-1:-1:-1;;;;;71279:10:0;-1:-1:-1;;;;;71279:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71275:25;;:2;:25;:::i;:::-;71266:34;;:6;:34;:::i;69432:174::-;69515:9;69538:10;-1:-1:-1;;;;;69530:24:0;69562:7;69530:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69514:60;;;69593:4;69585:13;;;;;70699:260;70902:10;;:21;;;;;;;;70770:18;;-1:-1:-1;;;;;70902:10:0;;:19;;:21;;;;;;;;;;;;;;:10;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70898:25;;:2;:25;:::i;:::-;70842:8;;;;:38;;70858:11;;;;;;;;;-1:-1:-1;;;;;70858:11:0;-1:-1:-1;;;;;70858:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70842:38;;;70837:44;70853:2;70837;:44;:::i;21163:1400::-;21229:4;21360:21;;;:14;;;:21;;;;;;21398:13;;21394:1162;;21771:18;21792:12;21803:1;21792:8;:12;:::i;:::-;21839:18;;21771:33;;-1:-1:-1;21819:17:0;;21839:22;;21860:1;;21839:22;:::i;:::-;21819:42;;21896:9;21882:10;:23;21878:385;;21926:17;21946:3;:11;;21958:9;21946:22;;;;;;;;:::i;:::-;;;;;;;;;21926:42;;22096:9;22070:3;:11;;22082:10;22070:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;22211:25;;;:14;;;:25;;;;;:36;;;21878:385;22344:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;22450:3;:14;;:21;22465:5;22450:21;;;;;;;;;;;22443:28;;;22495:4;22488:11;;;;;;;21394:1162;22539:5;22532:12;;;;;23999:111;24055:16;24091:3;:11;;24084:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23999:111;;;:::o;20571:416::-;20634:4;22746:21;;;:14;;;:21;;;;;;20651:329;;-1:-1:-1;20694:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;20879:18;;20855:21;;;:14;;;:21;;;;;;:42;;;;20912:11;;20651:329;-1:-1:-1;20963:5:0;20956:12;;15980:129;7148:20;:18;:20::i;:::-;16063:38:::1;16088:12;16063:24;:38::i;7308:145::-:0;9141:21;8822:40;;;;;;7371:75;;7417:17;;;;;;;;;;;;;;16117:240;7148:20;:18;:20::i;14:180:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;199:248::-;267:6;275;328:2;316:9;307:7;303:23;299:32;296:52;;;344:1;341;334:12;296:52;-1:-1:-1;;367:23:1;;;437:2;422:18;;;409:32;;-1:-1:-1;199:248:1:o;452:114::-;536:4;529:5;525:16;518:5;515:27;505:55;;556:1;553;546:12;571:243;628:6;681:2;669:9;660:7;656:23;652:32;649:52;;;697:1;694;687:12;649:52;736:9;723:23;755:29;778:5;755:29;:::i;1193:196::-;1261:20;;-1:-1:-1;;;;;1310:54:1;;1300:65;;1290:93;;1379:1;1376;1369:12;1290:93;1193:196;;;:::o;1394:186::-;1453:6;1506:2;1494:9;1485:7;1481:23;1477:32;1474:52;;;1522:1;1519;1512:12;1474:52;1545:29;1564:9;1545:29;:::i;1585:316::-;1662:6;1670;1678;1731:2;1719:9;1710:7;1706:23;1702:32;1699:52;;;1747:1;1744;1737:12;1699:52;-1:-1:-1;;1770:23:1;;;1840:2;1825:18;;1812:32;;-1:-1:-1;1891:2:1;1876:18;;;1863:32;;1585:316;-1:-1:-1;1585:316:1:o;1906:548::-;2018:4;2047:2;2076;2065:9;2058:21;2108:6;2102:13;2151:6;2146:2;2135:9;2131:18;2124:34;2176:1;2186:140;2200:6;2197:1;2194:13;2186:140;;;2295:14;;;2291:23;;2285:30;2261:17;;;2280:2;2257:26;2250:66;2215:10;;2186:140;;;2190:3;2375:1;2370:2;2361:6;2350:9;2346:22;2342:31;2335:42;2445:2;2438;2434:7;2429:2;2421:6;2417:15;2413:29;2402:9;2398:45;2394:54;2386:62;;;;1906:548;;;;:::o;2855:681::-;3026:2;3078:21;;;3148:13;;3051:18;;;3170:22;;;2997:4;;3026:2;3249:15;;;;3223:2;3208:18;;;2997:4;3292:218;3306:6;3303:1;3300:13;3292:218;;;3371:13;;-1:-1:-1;;;;;3367:62:1;3355:75;;3485:15;;;;3450:12;;;;3328:1;3321:9;3292:218;;;-1:-1:-1;3527:3:1;;2855:681;-1:-1:-1;;;;;;2855:681:1:o;4572:254::-;4640:6;4648;4701:2;4689:9;4680:7;4676:23;4672:32;4669:52;;;4717:1;4714;4707:12;4669:52;4753:9;4740:23;4730:33;;4782:38;4816:2;4805:9;4801:18;4782:38;:::i;:::-;4772:48;;4572:254;;;;;:::o;4831:::-;4899:6;4907;4960:2;4948:9;4939:7;4935:23;4931:32;4928:52;;;4976:1;4973;4966:12;4928:52;4999:29;5018:9;4999:29;:::i;:::-;4989:39;5075:2;5060:18;;;;5047:32;;-1:-1:-1;;;4831:254:1:o;5090:118::-;5176:5;5169:13;5162:21;5155:5;5152:32;5142:60;;5198:1;5195;5188:12;5213:821;5341:6;5349;5357;5365;5373;5381;5389;5397;5405;5458:3;5446:9;5437:7;5433:23;5429:33;5426:53;;;5475:1;5472;5465:12;5426:53;5498:29;5517:9;5498:29;:::i;:::-;5488:39;;5546:38;5580:2;5569:9;5565:18;5546:38;:::i;:::-;5536:48;;5603:38;5637:2;5626:9;5622:18;5603:38;:::i;:::-;5593:48;;5660:38;5694:2;5683:9;5679:18;5660:38;:::i;:::-;5650:48;;5717:39;5751:3;5740:9;5736:19;5717:39;:::i;:::-;5707:49;;5806:3;5795:9;5791:19;5778:33;5820:28;5842:5;5820:28;:::i;:::-;5867:5;5857:15;;;5919:3;5908:9;5904:19;5891:33;5881:43;;5971:3;5960:9;5956:19;5943:33;5933:43;;6023:3;6012:9;6008:19;5995:33;5985:43;;5213:821;;;;;;;;;;;:::o;6039:517::-;6132:6;6140;6148;6156;6164;6217:3;6205:9;6196:7;6192:23;6188:33;6185:53;;;6234:1;6231;6224:12;6185:53;6270:9;6257:23;6247:33;;6327:2;6316:9;6312:18;6299:32;6289:42;;6381:2;6370:9;6366:18;6353:32;6394:29;6417:5;6394:29;:::i;:::-;6039:517;;;;-1:-1:-1;6442:5:1;;6494:2;6479:18;;6466:32;;-1:-1:-1;6545:3:1;6530:19;6517:33;;6039:517;-1:-1:-1;;6039:517:1:o;7061:750::-;7153:6;7161;7169;7222:2;7210:9;7201:7;7197:23;7193:32;7190:52;;;7238:1;7235;7228:12;7190:52;7278:9;7265:23;7307:18;7348:2;7340:6;7337:14;7334:34;;;7364:1;7361;7354:12;7334:34;7402:6;7391:9;7387:22;7377:32;;7447:7;7440:4;7436:2;7432:13;7428:27;7418:55;;7469:1;7466;7459:12;7418:55;7509:2;7496:16;7535:2;7527:6;7524:14;7521:34;;;7551:1;7548;7541:12;7521:34;7606:7;7599:4;7589:6;7586:1;7582:14;7578:2;7574:23;7570:34;7567:47;7564:67;;;7627:1;7624;7617:12;7564:67;7658:4;7650:13;;;;-1:-1:-1;7682:6:1;-1:-1:-1;;7723:20:1;;7710:34;7753:28;7710:34;7753:28;:::i;:::-;7800:5;7790:15;;;7061:750;;;;;:::o;8439:184::-;8509:6;8562:2;8550:9;8541:7;8537:23;8533:32;8530:52;;;8578:1;8575;8568:12;8530:52;-1:-1:-1;8601:16:1;;8439:184;-1:-1:-1;8439:184:1:o;8930:245::-;8997:6;9050:2;9038:9;9029:7;9025:23;9021:32;9018:52;;;9066:1;9063;9056:12;9018:52;9098:9;9092:16;9117:28;9139:5;9117:28;:::i;9586:184::-;-1:-1:-1;;;9635:1:1;9628:88;9735:4;9732:1;9725:15;9759:4;9756:1;9749:15;9775:168;9848:9;;;9879;;9896:15;;;9890:22;;9876:37;9866:71;;9917:18;;:::i;9948:125::-;10013:9;;;10034:10;;;10031:36;;;10047:18;;:::i;13426:274::-;13466:1;13492;13482:189;;-1:-1:-1;;;13524:1:1;13517:88;13628:4;13625:1;13618:15;13656:4;13653:1;13646:15;13482:189;-1:-1:-1;13685:9:1;;13426:274::o;13705:128::-;13772:9;;;13793:11;;;13790:37;;;13807:18;;:::i;14550:437::-;14629:1;14625:12;;;;14672;;;14693:61;;14747:4;14739:6;14735:17;14725:27;;14693:61;14800:2;14792:6;14789:14;14769:18;14766:38;14763:218;;-1:-1:-1;;;14834:1:1;14827:88;14938:4;14935:1;14928:15;14966:4;14963:1;14956:15;14763:218;;14550:437;;;:::o;18927:184::-;-1:-1:-1;;;18976:1:1;18969:88;19076:4;19073:1;19066:15;19100:4;19097:1;19090:15;19242:545;19344:2;19339:3;19336:11;19333:448;;;19380:1;19405:5;19401:2;19394:17;19450:4;19446:2;19436:19;19520:2;19508:10;19504:19;19501:1;19497:27;19491:4;19487:38;19556:4;19544:10;19541:20;19538:47;;;-1:-1:-1;19579:4:1;19538:47;19634:2;19629:3;19625:12;19622:1;19618:20;19612:4;19608:31;19598:41;;19689:82;19707:2;19700:5;19697:13;19689:82;;;19752:17;;;19733:1;19722:13;19689:82;;19963:1352;20089:3;20083:10;20116:18;20108:6;20105:30;20102:56;;;20138:18;;:::i;:::-;20167:97;20257:6;20217:38;20249:4;20243:11;20217:38;:::i;:::-;20211:4;20167:97;:::i;:::-;20319:4;;20383:2;20372:14;;20400:1;20395:663;;;;21102:1;21119:6;21116:89;;;-1:-1:-1;21171:19:1;;;21165:26;21116:89;-1:-1:-1;;19920:1:1;19916:11;;;19912:24;19908:29;19898:40;19944:1;19940:11;;;19895:57;21218:81;;20365:944;;20395:663;19189:1;19182:14;;;19226:4;19213:18;;-1:-1:-1;;20431:20:1;;;20549:236;20563:7;20560:1;20557:14;20549:236;;;20652:19;;;20646:26;20631:42;;20744:27;;;;20712:1;20700:14;;;;20579:19;;20549:236;;;20553:3;20813:6;20804:7;20801:19;20798:201;;;20874:19;;;20868:26;-1:-1:-1;;20957:1:1;20953:14;;;20969:3;20949:24;20945:37;20941:42;20926:58;20911:74;;20798:201;-1:-1:-1;;;;;21045:1:1;21029:14;;;21025:22;21012:36;;-1:-1:-1;19963:1352:1:o;22707:422::-;22796:1;22839:5;22796:1;22853:270;22874:7;22864:8;22861:21;22853:270;;;22933:4;22929:1;22925:6;22921:17;22915:4;22912:27;22909:53;;;22942:18;;:::i;:::-;22992:7;22982:8;22978:22;22975:55;;;23012:16;;;;22975:55;23091:22;;;;23051:15;;;;22853:270;;;22857:3;22707:422;;;;;:::o;23134:806::-;23183:5;23213:8;23203:80;;-1:-1:-1;23254:1:1;23268:5;;23203:80;23302:4;23292:76;;-1:-1:-1;23339:1:1;23353:5;;23292:76;23384:4;23402:1;23397:59;;;;23470:1;23465:130;;;;23377:218;;23397:59;23427:1;23418:10;;23441:5;;;23465:130;23502:3;23492:8;23489:17;23486:43;;;23509:18;;:::i;:::-;-1:-1:-1;;23565:1:1;23551:16;;23580:5;;23377:218;;23679:2;23669:8;23666:16;23660:3;23654:4;23651:13;23647:36;23641:2;23631:8;23628:16;23623:2;23617:4;23614:12;23610:35;23607:77;23604:159;;;-1:-1:-1;23716:19:1;;;23748:5;;23604:159;23795:34;23820:8;23814:4;23795:34;:::i;:::-;23865:6;23861:1;23857:6;23853:19;23844:7;23841:32;23838:58;;;23876:18;;:::i;:::-;23914:20;;23134:806;-1:-1:-1;;;23134:806:1:o;23945:140::-;24003:5;24032:47;24073:4;24063:8;24059:19;24053:4;24032:47;:::i;24090:184::-;-1:-1:-1;;;24139:1:1;24132:88;24239:4;24236:1;24229:15;24263:4;24260:1;24253:15;24279:135;24318:3;24339:17;;;24336:43;;24359:18;;:::i;:::-;-1:-1:-1;24406:1:1;24395:13;;24279:135::o;24779:247::-;24847:6;24900:2;24888:9;24879:7;24875:23;24871:32;24868:52;;;24916:1;24913;24906:12;24868:52;24948:9;24942:16;24967:29;24990:5;24967:29;:::i;25031:184::-;-1:-1:-1;;;25080:1:1;25073:88;25180:4;25177:1;25170:15;25204:4;25201:1;25194:15
Swarm Source
ipfs://cba17edf99ca643d8d080d74a892478e47b55cfad642fa33c88fc5f15d7d791c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.