Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 725 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw LP | 21130722 | 47 days ago | IN | 0 ETH | 0.00178936 | ||||
Claim Rewards LP | 21130717 | 47 days ago | IN | 0 ETH | 0.00242883 | ||||
Claim Rewards MB... | 21130703 | 47 days ago | IN | 0 ETH | 0.00240927 | ||||
Stake MBLK | 21018443 | 63 days ago | IN | 0 ETH | 0.00179698 | ||||
Withdraw MBLK | 21008469 | 64 days ago | IN | 0 ETH | 0.00138363 | ||||
Claim Rewards MB... | 21008461 | 64 days ago | IN | 0 ETH | 0.00706112 | ||||
Withdraw MBLK | 20973685 | 69 days ago | IN | 0 ETH | 0.00184242 | ||||
Update Stake | 20973658 | 69 days ago | IN | 0 ETH | 0.00152787 | ||||
Withdraw MBLK | 20726916 | 103 days ago | IN | 0 ETH | 0.00025033 | ||||
Claim Rewards MB... | 20726908 | 103 days ago | IN | 0 ETH | 0.00127121 | ||||
Withdraw LP | 20720255 | 104 days ago | IN | 0 ETH | 0.00091553 | ||||
Update Stake | 20720247 | 104 days ago | IN | 0 ETH | 0.00084055 | ||||
Stake MBLK | 20712813 | 105 days ago | IN | 0 ETH | 0.00098411 | ||||
Withdraw MBLK | 20637407 | 116 days ago | IN | 0 ETH | 0.00014413 | ||||
Withdraw MBLK | 20637396 | 116 days ago | IN | 0 ETH | 0.00014238 | ||||
Update Stake | 20637387 | 116 days ago | IN | 0 ETH | 0.00013537 | ||||
Withdraw LP | 20637380 | 116 days ago | IN | 0 ETH | 0.00014197 | ||||
Update Stake | 20637357 | 116 days ago | IN | 0 ETH | 0.00016903 | ||||
Update Stake | 20637332 | 116 days ago | IN | 0 ETH | 0.00016672 | ||||
Withdraw MBLK | 20615559 | 119 days ago | IN | 0 ETH | 0.00009684 | ||||
Update Stake | 20615546 | 119 days ago | IN | 0 ETH | 0.00011631 | ||||
Claim Rewards MB... | 20615544 | 119 days ago | IN | 0 ETH | 0.0006551 | ||||
Withdraw MBLK | 20590128 | 122 days ago | IN | 0 ETH | 0.00010106 | ||||
Withdraw LP | 20560999 | 126 days ago | IN | 0 ETH | 0.00011725 | ||||
Withdraw LP | 20560926 | 126 days ago | IN | 0 ETH | 0.00013838 |
Latest 2 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18793445 | 374 days ago | Contract Creation | 0 ETH | |||
18793445 | 374 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MBLKStakingPool
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-12-15 */ /** *Submitted for verification at Etherscan.io on 2023-12-15 */ /** *Submitted for verification at Etherscan.io on 2023-12-11 */ // SPDX-License-Identifier: MIT // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } } // File: @openzeppelin/contracts/access/IAccessControl.sol // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts/security/ReentrancyGuard.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 ReentrancyGuard { // 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; constructor() { _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; } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/contracts/access/AccessControl.sol // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) pragma solidity ^0.8.0; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } } // File: @openzeppelin/contracts/security/Pausable.sol // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @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. * * By default, the owner account will be the one that deploys the contract. 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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @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) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} } // File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.0; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { _spendAllowance(account, _msgSender(), amount); _burn(account, amount); } } // File: 1_sLP_1.sol pragma solidity ^0.8.0; contract LPStaked is ERC20, Ownable,Pausable, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); constructor() ERC20("LPStaked", "sLP") { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(MINTER_ROLE, msg.sender); } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } /** * @dev Burns a specific amount of tokens from the sender's balance. * @param amount The amount of tokens to be burned. */ function burn(uint256 amount) external { _burn(msg.sender, amount); } /** * @dev Burns a specific amount of tokens from the target address's balance. * @param account The address whose tokens will be burned. * @param amount The amount of tokens to be burned. */ function burnFrom(address account, uint256 amount) external onlyRole(MINTER_ROLE) { _burn(account, amount); } /** * @dev Mints new tokens and assigns them to the target address. * @param account The address to which new tokens will be minted. * @param amount The amount of tokens to be minted. */ function mint(address account, uint256 amount) public onlyRole(MINTER_ROLE) { _mint(account, amount); } /** * @dev Grants the minter role to a new address. * @param account The address to which the minter role will be granted. */ function grantMinterRole(address account) external onlyOwner { grantRole(MINTER_ROLE, account); } /** * @dev Revokes the minter role from an address. * @param account The address from which the minter role will be revoked. */ function revokeMinterRole(address account) external onlyOwner { revokeRole(MINTER_ROLE, account); } function _beforeTokenTransfer(address from, address to, uint256 amount) internal whenNotPaused override { super._beforeTokenTransfer(from, to, amount); } } // File: 1_sMBLK_1.sol pragma solidity ^0.8.0; contract MBLKStaked is ERC20, Ownable,Pausable, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); constructor() ERC20("MBLKStaked", "sMBLK") { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(MINTER_ROLE, msg.sender); } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } /** * @dev Burns a specific amount of tokens from the sender's balance. * @param amount The amount of tokens to be burned. */ function burn(uint256 amount) external { _burn(msg.sender, amount); } /** * @dev Burns a specific amount of tokens from the target address's balance. * @param account The address whose tokens will be burned. * @param amount The amount of tokens to be burned. */ function burnFrom(address account, uint256 amount) external onlyRole(MINTER_ROLE) { _burn(account, amount); } /** * @dev Mints new tokens and assigns them to the target address. * @param account The address to which new tokens will be minted. * @param amount The amount of tokens to be minted. */ function mint(address account, uint256 amount) public onlyRole(MINTER_ROLE) { _mint(account, amount); } /** * @dev Grants the minter role to a new address. * @param account The address to which the minter role will be granted. */ function grantMinterRole(address account) external onlyOwner { grantRole(MINTER_ROLE, account); } /** * @dev Revokes the minter role from an address. * @param account The address from which the minter role will be revoked. */ function revokeMinterRole(address account) external onlyOwner { revokeRole(MINTER_ROLE, account); } function _beforeTokenTransfer(address from, address to, uint256 amount) internal whenNotPaused override { super._beforeTokenTransfer(from, to, amount); } } // File: NewStakingCOntract.sol pragma solidity 0.8.23; contract MBLKStakingPool is Ownable,ReentrancyGuard { using SafeERC20 for IERC20; IERC20 public immutable mblkToken; MBLKStaked public immutable smblkToken; LPStaked public immutable slpToken; IERC20 public immutable lpToken; // Struct to represent MBLK staking details for a user struct MBLKStake { uint256 mblkAmount; // Amount of MBLK tokens staked uint256 startTimestamp; // Timestamp when the staking started uint256 endTime; // Timestamp when the staking ends uint256 claimedReward; // Amount of claimed rewards by the user uint256 lastClaimedTimeStamp; // Timestamp of the last claimed reward uint256 smblkMinted; // Amount of sMBLK (staking MBLK) tokens minted as rewards uint256 cycleId; // Identifier of the staking cycle // uint256 withdrawPeriod; uint256 lastEndTime; } // Struct representing the LP staking details for a user struct LPStake { uint256 lpAmount; // Amount of liquidity provider tokens staked uint256 startTimestamp; // Timestamp when the LP staking started uint256 endTime; // Timestamp when the LP staking ends uint256 claimedReward; // Amount of claimed rewards by the LP uint256 lastClaimedTimeStamp; // Timestamp of the last claimed reward by the LP uint256 slpMinted; // Amount of sLP (staking LP) tokens minted as rewards uint256 cycleId; // Identifier of the staking cycle for LPs // uint256 withdrawPeriod; uint256 lastEndTime; } // Struct representing information related to a staking cycle struct StakingInfo { uint256 cycleId; // Identifier for the staking cycle uint256 blockTimeStamp; // Timestamp of the block when the staking cycle was created uint256 totalReward; // Total reward allocated for current cycle uint256 totalLpStaked; // Total amount of Liquidity Provider (LP) tokens staked in this cycle uint256 totalMblkStaked; // Total amount of MBLK tokens staked in this cycle } // Mapping to store MBLKStake struct information associated with user addresses mapping(address => MBLKStake) public userMblkStakes; // Mapping to store LPStake struct information associated with user addresses mapping(address => LPStake) public userLpStakes; // Mapping to manage administrator privileges for specific addresses mapping(address => bool) public isAdmin; // Mapping to maintain StakingInfo struct data corresponding to specific cycle IDs mapping(uint256 => StakingInfo) public stakingInfo; // Total amount of MBLK tokens staked uint256 public totalMblkStaked; // Total amount of LP tokens staked uint256 public totalLpStaked; uint256 totalClaimedRewards; // Total amount of sMBLK tokens minted uint256 public totalSmblkMinted; // Total amount of sLP tokens minted uint256 public totalSlpMinted; // Current cycle identifier uint256 public currentCycleId; // Timestamp of the last dynamic reward set uint256 public lastDynamicRewardSet; // Minimum time required to calculate rewards uint256 public calculateRewardMinimumTime; // Time allocated for fixed rewards uint256 public timeForFixedReward; // Time allocated for dynamic rewards uint256 public timeForDynamicReward; // Timestamp of the last fixed reward setting uint256 public lastFixedRewardSet; // Timestamp of the last total reward setting uint256 public lastTotalRewardSetTimestamp; // Fixed reward amount uint256 public fixedReward; // Dynamic reward amount uint256 public dynamicReward; // Total rewards across the platform uint256 public totalRewards; // Minimum duration for stake locking uint256 public minimumStakeDuration; // Boolean to check if rewards are set or not //bool isRewardSent; //Boolean for Pause and unpause bool isPaused; // Wallet address for collecting fees address public feesCollectionWallet; // Percentage of fees charged uint256 public feesPercentage; // mblk Reward percentage uint256 public constant mblkRewardPercentage = 30; // Lp Reward Percentage uint256 public constant lpRewardPercentage = 70; uint256 public unstakingPeriod; //Events event StakeMblk(address indexed user,uint256 mblkAmount); event StakeLp(address indexed user,uint256 lpAmount); event ClaimedRewardsMblk(address indexed user,uint256 rewardsAmount); event ClaimedRewardsLp(address indexed user,uint256 rewardsAmount); event MblkStakeUpdated(address userAddress, uint256 amount); event LpStakeUpdated(address userAddress, uint256 amount); event WithdrawnMblk(address indexed user, uint256 rewardsAmount); event WithdrawnLp(address indexed user, uint256 rewardsAmount); event FeesPercentageSet(uint256 percentage); event TotalRewardSet(uint256 totalReward); event DynamicRewardSet(uint256 dynamicReward); event FixedRewardSet(uint256 newFixedReward); event MinimumStakeDurationSet(uint256 duration); event AdminRemoved( address adminToRemove); event AdminAdded( address adminAddress); event UpdatedCycleId(uint256 currentCycleId); event WithDrawnAll(address owner,uint256 BalanceMBLK); event FeesWalletSet(address feesCollectionWallet); event MinimumCalculateRewardTimeSet(uint256 time); event PausedStaking(); event UnpausedStaking(); /* * @dev Modifer which allows ADMIN LIST TO ACCESS THE FUNCTION */ modifier onlyAdmin() { require(isAdmin[msg.sender], "Only admins can call this function"); _; } constructor( address mblkTokenAddress, // Address of the MBLK token contract address lptokenAddress, // Address of the LP token contract address feesCollectionWalletAddress // Address to collect fees or rewards ) payable { mblkToken = IERC20(mblkTokenAddress); // Initializing MBLK token contract interface lpToken = IERC20(lptokenAddress); // Initializing LP token contract interface feesCollectionWallet = feesCollectionWalletAddress; // Assigning the fees collection wallet address smblkToken = new MBLKStaked(); // Deploying a new instance of MBLKStaked contract slpToken = new LPStaked(); // Deploying a new instance of LPStaked contract // isRewardSent = false; // Setting the initial state for isRewardSent //calculateRewardMinimumTime = 6 hours; // Setting the calculateRewardMinimumTime as 6 hours isPaused = false; feesPercentage = 30; unstakingPeriod = 3 days; isAdmin[msg.sender] = true; } /** * @dev Stake a specified amount of MBLK tokens. * @param mblkAmount The amount of MBLK tokens to stake. * * Requirements: * - The staked amount must be greater than 0. * - The user must not have an active MBLK stake (mblkAmount must be 0). * - Transfer MBLK tokens from the sender to the staking contract. * - Record stake-related information including start and end times, rewards, and cycle ID. * - Mint and distribute SMBLK tokens to the staker. * - Update the total MBLK staked and total SMBLK minted. * * Emits a StakeMBLK event to log the staking action. */ function stakeMBLK(uint256 mblkAmount) nonReentrant external { require(isPaused == false,"Contract is paused"); require(mblkAmount > 0, "Amount must be greater than 0"); require( mblkToken.balanceOf(msg.sender) >= mblkAmount, "Not enough Balance" ); require( userMblkStakes[msg.sender].mblkAmount == 0, "Existing active stake found" ); MBLKStake memory userStake = userMblkStakes[msg.sender]; mblkToken.safeTransferFrom(msg.sender, address(this), mblkAmount); uint256 blockTimeStamp = block.timestamp; totalMblkStaked += mblkAmount; userStake.mblkAmount = mblkAmount; userStake.startTimestamp = blockTimeStamp; userStake.endTime = blockTimeStamp + minimumStakeDuration; userStake.lastEndTime = blockTimeStamp + minimumStakeDuration; // userStake.withdrawPeriod = blockTimeStamp + minimumStakeDuration + unstakingPeriod; userStake.lastClaimedTimeStamp = blockTimeStamp; smblkToken.mint(msg.sender,mblkAmount); totalSmblkMinted += mblkAmount; userStake.cycleId = currentCycleId + 1; userStake.smblkMinted += mblkAmount; userMblkStakes[msg.sender] = userStake; emit StakeMblk(msg.sender,mblkAmount); } /** * @dev Stake a specified amount of LP (Liquidity Provider) tokens. * @param lpAmount The amount of LP tokens to stake. * * Requirements: * - The staked amount must be greater than 0. * - The sender must have a sufficient balance of LP tokens to stake. * - The user must not have an active LP stake (lpAmount must be 0). * - Transfer LP tokens from the sender to the staking contract. * - Record stake-related information including start and end times, rewards, and cycle ID. * - Mint and distribute SLP tokens to the staker. * - Update the total LP tokens staked and total SLP tokens minted. * * Emits a StakeLP event to log the staking action. */ function stakeLP(uint256 lpAmount) nonReentrant external { require(isPaused == false,"Contract is paused"); require(lpAmount > 0, "Amount must be greater than 0 " ); require( lpToken.balanceOf(msg.sender) >= lpAmount, "Not enough Balance" ); require( userLpStakes[msg.sender].lpAmount == 0, "Existing LP Stake Found" ); LPStake memory userStake = userLpStakes[msg.sender]; lpToken.safeTransferFrom(msg.sender,address(this), lpAmount); totalLpStaked += lpAmount; uint256 blockTimeStamp = block.timestamp; userStake.lpAmount += lpAmount; userStake.startTimestamp = blockTimeStamp; userStake.endTime = blockTimeStamp + minimumStakeDuration; userStake.lastEndTime = blockTimeStamp + minimumStakeDuration; // userStake.withdrawPeriod = blockTimeStamp + minimumStakeDuration + unstakingPeriod; userStake.lastClaimedTimeStamp = blockTimeStamp; slpToken.mint(msg.sender,lpAmount); //Staked LP Token MInted to User Address totalSlpMinted += lpAmount; userStake.slpMinted += lpAmount; userStake.cycleId = currentCycleId + 1; userLpStakes[msg.sender] = userStake; emit StakeLp(msg.sender, lpAmount); } /** * @dev Update a user's stake with additional tokens. * @param amount The amount of tokens to add to the user's stake. * @param isMblk A boolean indicating whether the stake is for MBLK (true) or LP (false). * * Requirements: * - The added amount must be greater than 0. * - The calculated rewards must be claimed first (calculatedRewards must be 0). * - If the stake is for MBLK, the user must have an existing active MBLK stake; if the stake is for LP, the user must have an existing active LP stake. * - Transfer tokens from the sender to the staking contract. * - Update stake-related information, including start and end times, rewards, and cycle ID. * * Emits an MblkStakeUpdated event if updating an MBLK stake, or an LpStakeUpdated event if updating an LP stake, to log the stake update. */ function updateStake(uint256 amount, bool isMblk) public { require(isPaused == false,"Contract is paused"); require(amount > 0, "Amount must be greater than 0"); if(isMblk){ require( mblkToken.balanceOf(msg.sender)>= amount, "Not enough balance" ); MBLKStake memory userStake = userMblkStakes[msg.sender]; uint256 calculatedRewards = calculateReward(msg.sender,0,true); require(calculatedRewards == 0, "Please claim the rewards first"); require(userStake.mblkAmount > 0,"Existing active stake not found"); mblkToken.safeTransferFrom(msg.sender, address(this), amount); totalMblkStaked += amount; userStake.mblkAmount += amount; uint256 blockTimeStamp = block.timestamp; userStake.startTimestamp = blockTimeStamp; userStake.endTime = blockTimeStamp + minimumStakeDuration; userStake.lastEndTime = blockTimeStamp + minimumStakeDuration; smblkToken.mint(msg.sender, amount); totalSmblkMinted += amount; //userStake.withdrawPeriod = blockTimeStamp + minimumStakeDuration + unstakingPeriod; userStake.smblkMinted += amount; userStake.cycleId = currentCycleId + 1; userMblkStakes[msg.sender] = userStake; emit MblkStakeUpdated(msg.sender,amount); } else { require( lpToken.balanceOf(msg.sender)>= amount, "Not enough balance" ); LPStake memory userStake = userLpStakes[msg.sender]; uint256 calculatedRewards = calculateReward(msg.sender,0,false); require(calculatedRewards == 0, "Please claim the rewards first"); require(userStake.lpAmount > 0, "Existing active stake not found"); lpToken.safeTransferFrom(msg.sender,address(this), amount); totalLpStaked += amount; userStake.lpAmount += amount; uint256 blockTimeStamp = block.timestamp; userStake.startTimestamp = blockTimeStamp; userStake.endTime = blockTimeStamp + minimumStakeDuration; userStake.lastEndTime = blockTimeStamp + minimumStakeDuration; // userStake.withdrawPeriod = blockTimeStamp + minimumStakeDuration + unstakingPeriod; slpToken.mint(msg.sender, amount); totalSlpMinted += amount; userStake.slpMinted += amount; userStake.cycleId = currentCycleId + 1; userLpStakes[msg.sender] = userStake; emit LpStakeUpdated(msg.sender,amount); } } /** * @dev Calculate the rewards for a user based on their staking Parcentage. * @param userAddress The address of the user. * @param isMblk A boolean indicating whether the user has MBLK staked (true) or LP staked (false). * @return The calculated reward amount for the user * * Requirements: * - The user must have a staking amount greater than 0. * - The owner/admin must have set the minimum time for calculating rewards (calculateRewardMinimumTime). * * The function calculates rewards by iterating through cycles, determining the user's stake percentage, and applying it to the total rewards. * The calculated reward is based on the User Stake Percentage each cycle. */ function calculateReward(address userAddress,uint256 uptoCycleId, bool isMblk) public view returns(uint256){ require(isPaused == false,"Contract is paused"); require( uptoCycleId <= currentCycleId, "uptoCycleId is out of range" ); // require( // calculateRewardMinimumTime > 0, // "Owner Haven't Set calculate Reward minimum Time" // ); uint256 totalRewardsCalculated; uint256 _iether = 10**18; uint256 terminationValue; // uint256 blockTimeStamp = block.timestamp; if( uptoCycleId == 0){ terminationValue = currentCycleId; }else{ terminationValue = uptoCycleId; } if(isMblk){ MBLKStake memory userStake = userMblkStakes[userAddress]; require( userStake.mblkAmount > 0, "No Stakes Found" ); //uint256 elapsedTimeFromLastClaimed = blockTimeStamp - userStake.lastClaimedTimeStamp; // if(elapsedTimeFromLastClaimed >= calculateRewardMinimumTime){ for(uint256 i = userStake.cycleId; i <= terminationValue; i++){ if(stakingInfo[i].totalMblkStaked == 0 ){ continue; } uint256 totalRewardFromStakeInfo = stakingInfo[i].totalReward; uint256 totalMblkStakedFromStakeInfo = stakingInfo[i].totalMblkStaked; uint256 mblkStakePercentage = (userStake.mblkAmount * 100 * _iether)/(totalMblkStakedFromStakeInfo); uint256 numerator = mblkStakePercentage * totalRewardFromStakeInfo * _iether * mblkRewardPercentage; uint256 denominator = _iether * 10000 * _iether; uint256 totalRewardsPerCycle = numerator/denominator; totalRewardsCalculated += totalRewardsPerCycle; } return totalRewardsCalculated; // } else { // return 0; // } } else { LPStake memory userStake = userLpStakes[userAddress]; require( userStake.lpAmount > 0, "No Stakes Found" ); // uint256 elapsedTimeFromLastClaimed = blockTimeStamp - userStake.lastClaimedTimeStamp; // if(elapsedTimeFromLastClaimed >= calculateRewardMinimumTime){ for(uint256 i = userStake.cycleId; i <= terminationValue; i++){ if(stakingInfo[i].totalLpStaked == 0 ) { continue; } uint256 totalRewardFromStakeInfo = stakingInfo[i].totalReward; uint256 totalLpStakedFromStakeInfo = stakingInfo[i].totalLpStaked; uint256 lpStakePercentage = ( userStake.lpAmount * 100 * _iether )/(totalLpStakedFromStakeInfo); uint256 numerator = lpStakePercentage * totalRewardFromStakeInfo * _iether * lpRewardPercentage; uint256 denominator = _iether * 10000 * _iether; uint256 totalRewardsPerCycle = numerator/denominator; totalRewardsCalculated += totalRewardsPerCycle; } return totalRewardsCalculated; // }else{ // return 0; // } } } function getUserFees(uint256 amount) public view returns(uint256) { if(amount == 0 ) return 0; uint256 numerator = (amount * feesPercentage * 1e18); uint256 denominator = ( 10000 * 1e18); uint256 feeAmount = numerator/denominator; return feeAmount; } function getMinimumWithdrawableAmount(bool isMblk) public view returns(uint256){ if(isMblk){ //MBLKStake memory userStake = userMblkStakes[msg.sender]; uint256 minimumWithdrawableAmount = (userMblkStakes[msg.sender].mblkAmount * 10)/ 100; return minimumWithdrawableAmount; }else{ // LPStake memory userStake = userLpStakes[msg.sender]; uint256 minimumWithdrawbleAmount = (userLpStakes[msg.sender].lpAmount * 10)/100; return minimumWithdrawbleAmount; } // if(userMblkStakes[msg.sender].mblkAmount > 0){ // return (userMblkStakes[msg.sender].mblkAmount * 10)/100; // }else if(userLpStakes[msg.sender].lpAmount > 0){ // return (userLpStakes[msg.sender].lpAmount / 10); // }else{ // return 0; // } } /** * @dev Claim MBLK rewards for a user. * * This function allows a user to claim their MBLK rewards based on their staking Parcentage. The rewards are calculated using the 'calculateReward' function. * A fee is deducted from the total rewards, and the remaining amount is transferred to the user. The fee amount is also transferred to a specified feesCollectionWallet. * * Requirements: * - The user must have an active MBLK stake. * - The calculated reward must be greater than 0. * * Emits a ClaimedRewardsMblk event to log the claimed rewards. * * * */ function claimRewardsMBLK(uint256 uptoCycleId) nonReentrant public{ require(isPaused == false,"Contract is paused"); uint256 cycleIdConsidered; MBLKStake memory userStake = userMblkStakes[msg.sender]; require( uptoCycleId <= currentCycleId, "uptoCycleId is greated than currentCycleId" ); require( userStake.mblkAmount > 0, "No single MBLK stake found" ); if( uptoCycleId == 0){ cycleIdConsidered = currentCycleId; }else { cycleIdConsidered = uptoCycleId; } uint256 blockTimeStamp = block.timestamp; if( userStake.endTime < blockTimeStamp){ if( (userStake.endTime + unstakingPeriod) == blockTimeStamp){ userStake.endTime = userStake.lastEndTime + minimumStakeDuration; userStake.lastEndTime = userStake.endTime; } if( (userStake.endTime + unstakingPeriod) > blockTimeStamp){ userStake.lastEndTime = userStake.endTime; userStake.endTime = userStake.lastEndTime + minimumStakeDuration; } if((userStake.endTime + unstakingPeriod) < blockTimeStamp){ uint256 diff = blockTimeStamp - userStake.endTime; uint256 res = (diff / minimumStakeDuration) + 1; uint256 daysPassed = minimumStakeDuration * res; userStake.endTime = userStake.endTime + daysPassed; uint256 value = userStake.endTime - minimumStakeDuration; if (blockTimeStamp >= (userStake.startTimestamp + value + unstakingPeriod)){ userStake.lastEndTime = userStake.endTime; }else{ userStake.lastEndTime = userStake.endTime - minimumStakeDuration; } } } uint256 rewards = calculateReward(msg.sender,uptoCycleId,true); require( rewards > 0, "No rewards to claim"); require( mblkToken.balanceOf(address(this)) - (totalMblkStaked) >= rewards, "not enough balance in the contract" ); mblkToken.safeTransfer(msg.sender, rewards); userStake.lastClaimedTimeStamp = blockTimeStamp; userStake.claimedReward += rewards; userStake.cycleId = cycleIdConsidered + 1; totalClaimedRewards += rewards; userMblkStakes[msg.sender] = userStake; emit ClaimedRewardsMblk(msg.sender, rewards); } /** * @dev Claim LP token rewards for a user. * * This function allows a user to claim their LP token rewards based on their staking Parcentage. The rewards are calculated using the 'calculateReward' function. * A fee is deducted from the total rewards, and the remaining amount is transferred to the user. The fee amount is also transferred to a specified feesCollectionWallet. * * Requirements: * - The user must have an active LP token stake. * - The calculated reward must be greater than 0. * - the rewards must be less then or equal to balanceOf totalRewards * * Emits a ClaimedRewardsLp event to log the claimed rewards. */ function claimRewardsLP(uint256 uptoCycleId) nonReentrant public{ require(isPaused == false,"Contract is paused"); uint256 cycleIdConsidered; LPStake memory userStake = userLpStakes[msg.sender]; require( uptoCycleId <= currentCycleId, "uptoCycleId is greated than currentCycleId" ); require( userStake.lpAmount > 0, "No LP Stake found" ); if(uptoCycleId == 0){ cycleIdConsidered = currentCycleId; }else { cycleIdConsidered = uptoCycleId; } uint256 blockTimeStamp = block.timestamp; if( userStake.endTime < blockTimeStamp){ if( (userStake.endTime + unstakingPeriod) == blockTimeStamp){ userStake.endTime = userStake.lastEndTime + minimumStakeDuration; userStake.lastEndTime = userStake.endTime; } if( (userStake.endTime + unstakingPeriod) > blockTimeStamp){ userStake.lastEndTime = userStake.endTime; userStake.endTime = userStake.lastEndTime + minimumStakeDuration; } if((userStake.endTime + unstakingPeriod) < blockTimeStamp){ uint256 diff = blockTimeStamp - userStake.endTime; uint256 res = (diff / minimumStakeDuration) + 1; uint256 daysPassed = minimumStakeDuration * res; userStake.endTime = userStake.endTime + daysPassed; uint256 value = userStake.endTime - minimumStakeDuration; if (blockTimeStamp >= (userStake.startTimestamp + value + unstakingPeriod)){ userStake.lastEndTime = userStake.endTime; }else{ userStake.lastEndTime = userStake.endTime - minimumStakeDuration; } } } uint256 rewards = calculateReward(msg.sender,cycleIdConsidered,false); require( rewards > 0 , "No rewards to claim"); require( mblkToken.balanceOf(address(this)) - totalMblkStaked >= rewards, "not enough balance in the contract" ); mblkToken.safeTransfer(msg.sender, rewards); userStake.claimedReward += rewards; userStake.cycleId = cycleIdConsidered + 1; userStake.lastClaimedTimeStamp = block.timestamp; totalClaimedRewards += rewards; userLpStakes[msg.sender] = userStake; emit ClaimedRewardsLp(msg.sender, rewards); } /** * @dev Withdraw a specified amount of MBLK tokens from the user's stake. * @param amountTowithdraw The amount of MBLK tokens to withdraw. * * Requirements: * - The user must have an active MBLK stake. * - The calculated rewards must be claimed first (calculatedRewards must be 0). * - The withdrawal can only occur after the minimum stake duration has passed. * - The contract must have a sufficient balance of MBLK tokens. * * Effects: * - Transfers the specified amount of MBLK tokens to the user. * - Burns an equivalent amount of SMBLK tokens from the user's balance. * - Updates the user's stake and total MBLK and SMBLK minted values. * * Emits a WithdrawnMblk event to log the MBLK withdrawal. */ function withdrawMBLK(uint256 amountTowithdraw) nonReentrant external { MBLKStake memory userStake = userMblkStakes[msg.sender]; uint256 blockTimeStamp = block.timestamp; require(blockTimeStamp >= userStake.lastEndTime && blockTimeStamp <= (userStake.lastEndTime + unstakingPeriod),"Can withdraw only in unstaking period"); require(amountTowithdraw > 0,"Amount to withdraw should be greater than 0"); if( isPaused == false){ require( userStake.lastEndTime < block.timestamp, "Can not withdraw before Minimum Stake Duration" ); uint256 calculatedRewards = calculateReward(msg.sender,0,true); require(calculatedRewards == 0,"Please claim the rewards first"); } require(userStake.mblkAmount > 0,"No active stake found"); require( userStake.mblkAmount >= amountTowithdraw, "Not enough MBLK Staked" ); require( mblkToken.balanceOf(address(this)) >= amountTowithdraw, "Contract balance is not enough" ); uint256 feeAmount = getUserFees(amountTowithdraw); require(feeAmount > 0, "Please add more Amount to withdraw"); require(amountTowithdraw > ((userStake.mblkAmount * 9) / 100),"Cannot withdraw less than 10 %"); uint256 amountToSend = amountTowithdraw - feeAmount; mblkToken.safeTransfer(msg.sender, amountToSend); mblkToken.safeTransfer(feesCollectionWallet,feeAmount); // mblkToken.safeTransfer(msg.sender, amountTowithdraw); smblkToken.burnFrom(msg.sender, amountTowithdraw); userStake.mblkAmount -= amountTowithdraw; userStake.smblkMinted -= amountTowithdraw; totalSmblkMinted -= amountTowithdraw; totalMblkStaked -= amountTowithdraw; userMblkStakes[msg.sender] = userStake; emit WithdrawnMblk(msg.sender,amountTowithdraw); } /** * @dev Withdraw a specified amount of LP (Liquidity Provider) tokens from the user's stake. * @param amountToWithdraw The amount of LP tokens to withdraw. * * Requirements: * - The user must have an active LP token stake. * - The calculated rewards must be claimed first (calculatedRewards must be 0). * - The withdrawal can only occur after the minimum stake duration has passed. * - The contract must have a sufficient balance of LP tokens and SMBLK tokens. * * Effects: * - Transfers the specified amount of LP tokens to the user. * - Burns an equivalent amount of SMBLK tokens from the user's balance. * - Updates the user's stake, total LP staked, and total SLP minted values. * * Emits a WithdrawnLp event to log the LP token withdrawal. */ function withdrawLP(uint256 amountToWithdraw) nonReentrant external { LPStake memory userStake = userLpStakes[msg.sender]; uint256 blockTimeStamp = block.timestamp; require(blockTimeStamp >= userStake.lastEndTime && blockTimeStamp <= (userStake.lastEndTime + unstakingPeriod),"Can withdraw only in unstaking period"); require(amountToWithdraw > 0,"Amount to withdraw should be greater than 0"); if( isPaused == false){ require( userStake.lastEndTime < block.timestamp, "Can not withdraw before Minimum Stake Duration" ); uint256 calculatedRewards = calculateReward(msg.sender,0,false); require(calculatedRewards == 0,"Please claim the rewards first"); } require(userStake.lpAmount > 0,"No active stake found"); require(userStake.lpAmount >= amountToWithdraw,"Not enough LP Staked"); require( userStake.lpAmount >= amountToWithdraw, "Contract balance is not enough" ); require( slpToken.balanceOf(msg.sender) >= amountToWithdraw, "user smblk Balance is not enough" ); require( lpToken.balanceOf(address(this)) >= amountToWithdraw, "Contract Balance is not enough" ); slpToken.burnFrom(msg.sender,amountToWithdraw); uint256 feeAmount = getUserFees(amountToWithdraw); require(feeAmount > 0, "Please add more Amount to withdraw"); require(amountToWithdraw > ((userStake.lpAmount * 9) / 100),"Cannot withdraw less than 10 %"); uint256 amountToSend = amountToWithdraw - feeAmount; lpToken.safeTransfer(msg.sender, amountToSend); lpToken.safeTransfer(feesCollectionWallet,feeAmount); userStake.lpAmount -= amountToWithdraw; totalLpStaked -= amountToWithdraw; totalSlpMinted -= amountToWithdraw; userStake.slpMinted -= amountToWithdraw; userLpStakes[msg.sender] = userStake; emit WithdrawnLp(msg.sender, amountToWithdraw); } /** * @dev Update the current staking cycle information. * * This function increments the currentCycleId, records the block timestamp, and updates the staking information for the new cycle, including total rewards, LP tokens staked, and MBLK tokens staked. * * Requirements: * - Only the admin can call this function. * * Emits an UpdatedCycleId event with the new cycle's identifier. */ function updateCycleId() public onlyAdmin{ // require(isRewardSent == true,"Rewards are not set"); currentCycleId++; uint256 blockTimeStamp = block.timestamp; StakingInfo memory currentStakeInfo = stakingInfo[currentCycleId]; currentStakeInfo.cycleId = currentCycleId; currentStakeInfo.blockTimeStamp = blockTimeStamp; currentStakeInfo.totalReward = totalRewards; currentStakeInfo.totalLpStaked = totalLpStaked; currentStakeInfo.totalMblkStaked = totalMblkStaked; stakingInfo[currentCycleId] = currentStakeInfo; // isRewardSent = false; emit UpdatedCycleId(currentCycleId); } /** * @dev Set a fixed reward value for staking. * @param newFixedReward The fixed reward value to be set. * * Requirements: * - Only the admin can call this function. * - The time since the last fixed reward update must be greater than or equal to 'timeForFixedReward'. * * Effects: * - Updates the 'fixedReward' value. * - Calls 'setTotalRewards' to set total rewards based on the fixed reward. * * Emits a FixedRewardSet event to log the update of the fixed reward value. */ function setFixedReward(address vestingAddress, uint256 newFixedReward) external onlyAdmin{ uint256 blocktimeStamp = block.timestamp; uint256 timeSpent = blocktimeStamp - lastFixedRewardSet; require(timeSpent >= timeForFixedReward, "Can not set before Minimum Time"); mblkToken.safeTransferFrom(vestingAddress,address(this),newFixedReward); lastFixedRewardSet = blocktimeStamp; fixedReward = newFixedReward; setTotalRewards(); emit FixedRewardSet(newFixedReward); } /** * @dev Set the dynamic reward value, but only if enough time has passed since the last update. * @param newDynamicReward The new dynamic reward value to set. * * Requirements: * - The function can only be called by the admin. * - The time elapsed since the last dynamic reward update must be greater than or equal to ` timeForDynamicReward`. * - If the time requirement is met, the dynamic reward value is updated, and `setTotalRewards` is called. * * Emits a DynamicRewardSet event with the new dynamic reward value. */ function setDynamicReward(address vestingAddress, uint256 newDynamicReward) external onlyAdmin{ uint256 blocktimeStamp = block.timestamp; uint256 timeSpent = blocktimeStamp - lastDynamicRewardSet; require(timeSpent >= timeForDynamicReward,"Can not set Before minimum time"); mblkToken.safeTransferFrom(vestingAddress,address(this),newDynamicReward); lastDynamicRewardSet = blocktimeStamp; dynamicReward = newDynamicReward; setTotalRewards(); emit DynamicRewardSet(newDynamicReward); } /** * @dev Set the total rewards for staking. * * Effects: * - Calculates the 'totalRewards' by adding the 'fixedReward' and 'dynamicReward'. * - Records the timestamp when the total rewards were last set. * * Emits a TotalRewardSet event to log the update of the total rewards. */ function setTotalRewards() internal { totalRewards = fixedReward + dynamicReward; lastTotalRewardSetTimestamp = block.timestamp; emit TotalRewardSet(totalRewards); } function setRewards(uint256 newFixedReward, uint256 newDynamicReward) public onlyAdmin{ require(newFixedReward > 0 , "newFixedReward cannot be 0"); require(newDynamicReward > 0 , "newDynamicReward cannot be 0"); fixedReward = newFixedReward; dynamicReward = newDynamicReward; totalRewards = fixedReward + dynamicReward; emit TotalRewardSet(totalRewards); } function setRewardTime(uint256 timeForRewards) public onlyOwner{ timeForDynamicReward = timeForRewards; timeForFixedReward = timeForRewards; } /** * @dev Set the fees percentage for reward distribution. * @param percentage The fees percentage to be set (0-10000, where 10000 represents 100%). * * Requirements: * - Only the admin can call this function. * - The provided percentage must be within the valid range (0-10000). * * Effects: * - Updates the 'feesPercentage' for fee calculations. * * Emits a FeesPercentageSet event to log the update of the fees percentage. */ function setFeesPercentage(uint256 percentage) external onlyOwner{ require(percentage > 0 && percentage <= 1500, "Percentage out of range (0-1500)"); feesPercentage = percentage; emit FeesPercentageSet(percentage); } /** * @dev Add a new address as an admin. * @param newAdmin The address to be added as a new admin. * * Requirements: * - Only the contract owner can call this function. * * Effects: * - Grants administrative privileges to the specified address by setting 'isAdmin[newAdmin]' to true. * * Emits an AdminAdded event to log the addition of a new admin. */ function addAdmin(address newAdmin) public onlyOwner { isAdmin[newAdmin] = true; emit AdminAdded(newAdmin); } /** * @dev Remove an address from the list of admins. * @param adminAddress The address to be removed from the list of admins. * * Requirements: * - Only the contract owner can call this function. * * Effects: * - Revokes administrative privileges from the specified address by setting 'isAdmin[adminAddress]' to false. * * Emits an AdminRemoved event to log the removal of an admin. */ function removeAdmin(address adminAddress) public onlyOwner{ isAdmin[adminAddress] = false; emit AdminRemoved(adminAddress); } /** * @dev Set the minimum stake duration in minutes. * @param durationInMinutes The minimum stake duration in minutes to be set. * * Requirements: * - The provided duration must be greater than 0. * * Effects: * - Converts the input duration in minutes to seconds and updates the 'minimumStakeDuration' variable. * * Emits a MinimumStakeDurationSet event to log the update of the minimum stake duration. */ function setMinimumStakeDuration(uint256 durationInMinutes) external onlyOwner{ require(durationInMinutes > 0, "Given Value is 0"); minimumStakeDuration = durationInMinutes * 60; emit MinimumStakeDurationSet(durationInMinutes); } /** * @dev Set the address where collected fees will be sent. * @param walletAddress The address where collected fees will be transferred to. * * Requirements: * - Only the contract owner can call this function. * * Effects: * - Updates the 'feesCollectionWallet' with the provided wallet address. */ function setFeeWalletAddress(address walletAddress) public onlyOwner{ feesCollectionWallet = walletAddress; emit FeesWalletSet(walletAddress); } /** * @dev Set the minimum time duration for calculating rewards. * @param durationInMinutes The minimum time duration in minutes for calculating rewards. * * Requirements: * - Only the contract owner can call this function. * * Effects: * - Converts the input duration in minutes to seconds and updates 'calculateRewardMinimumTime'. */ function setMinimumCalculateRewardTime(uint256 durationInMinutes) public onlyOwner{ require(durationInMinutes > 0, "calculate reward minimum time can not be 0"); calculateRewardMinimumTime = durationInMinutes * 60; emit MinimumCalculateRewardTimeSet(calculateRewardMinimumTime); } function setUnStakingPeriod(uint256 durationInMinutes) public onlyOwner{ require(durationInMinutes > 0,"cannot be 0"); unstakingPeriod = durationInMinutes * 60; } /** * @dev Withdraw MBLK from the contract by the owner. * * Requirements: * - Only the contract owner can call this function. * * Effects: * - Transfers the amount of Rewards Deposited of MBLK by owner from the contract to the owner's address. * * Emits a WithDrawnAll event to log the withdrawal of MBLK */ function withdrawOnlyOwner() public onlyOwner{ uint256 ownersDepositedFundsAsRewards = mblkToken.balanceOf(address(this)) - totalMblkStaked; mblkToken.safeTransfer(msg.sender, ownersDepositedFundsAsRewards); emit WithDrawnAll(msg.sender,ownersDepositedFundsAsRewards ); } function pauseStaking() public onlyOwner{ require( isPaused == false, "Already Paused"); isPaused = true; emit PausedStaking(); } function unPauseStaking() public onlyOwner { require( isPaused == true,"Already Unpaused"); isPaused = false; emit UnpausedStaking(); } /** * @dev Get the total amount of SMBLK (Staked MBLK) minted. * @return The total number of SMBLK tokens that have been minted as rewards. */ function totalSMBLK()public view returns(uint256){ return totalSmblkMinted; } /** * @dev Get the total amount of SLP (Staked LP) tokens minted. * @return The total number of SLP tokens that have been minted as rewards. */ function totalSLP()public view returns(uint256){ return totalSlpMinted; } /** * @dev Get information about a user's MBLK stake. * @param userAddress The address of the user. * @return ( * 1. The amount of MBLK staked by the user, * 2. The start timestamp of the stake, * 3. The end timestamp of the stake, * 4. The claimed reward amount, * 5. The last claimed timestamp, * 6. The amount of Staked MBLK minted, * ) */ function userMBLKStakeInformation( address userAddress ) public view returns( uint256, uint256, uint256, uint256, uint256, uint256 ) { MBLKStake memory userStake = userMblkStakes[userAddress]; return( userStake.mblkAmount, userStake.startTimestamp, userStake.endTime, userStake.claimedReward, userStake.lastClaimedTimeStamp, userStake.smblkMinted ); } /** * @dev Get information about a user's LP stake. * @param userAddress The address of the user. * @return ( * 1. The amount of LP tokens staked by the user, * 2. The start timestamp of the stake, * 3. The end timestamp of the stake, * 4. The claimed reward amount, * 5. The last claimed timestamp, * 6. The amount of Staked LP tokens minted, * ) */ function userLPStakesInformation( address userAddress ) public view returns( uint256, uint256, uint256, uint256, uint256, uint256 ) { LPStake memory userStake = userLpStakes[userAddress]; return( userStake.lpAmount, userStake.startTimestamp, userStake.endTime, userStake.claimedReward, userStake.lastClaimedTimeStamp, userStake.slpMinted ); } /** * @dev Get the total amount of rewards available for distribution. * @return The total number of rewards */ function getTotalRewards()public view returns(uint256) { return totalRewards; } function getTotalClaimedRewards() public view returns (uint256 ){ return totalClaimedRewards; } /** * @dev Get staking information for a specific cycle. * @param _cycleId The identifier of the staking cycle to retrieve information for. * @return ( * 1. The cycle ID, * 2. The block timestamp when the cycle was updated, * 3. The total amount of MBLK tokens staked in the cycle, * 4. The total reward associated with the cycle, * 5. The total amount of LP tokens staked in the cycle. * ) * * Requirements: * - The provided _cycleId must be within a valid range (not exceeding currentCycleId). */ function getStakingInfo( uint256 _cycleId ) public view returns( uint256, uint256, uint256, uint256, uint256 ) { require(_cycleId <= currentCycleId, "Cycle Id is out of Range"); return( stakingInfo[_cycleId].cycleId, stakingInfo[_cycleId].blockTimeStamp, stakingInfo[_cycleId].totalMblkStaked, stakingInfo[_cycleId].totalReward, stakingInfo[_cycleId].totalLpStaked ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"mblkTokenAddress","type":"address"},{"internalType":"address","name":"lptokenAddress","type":"address"},{"internalType":"address","name":"feesCollectionWalletAddress","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"adminAddress","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"adminToRemove","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"ClaimedRewardsLp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"ClaimedRewardsMblk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dynamicReward","type":"uint256"}],"name":"DynamicRewardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"FeesPercentageSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feesCollectionWallet","type":"address"}],"name":"FeesWalletSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFixedReward","type":"uint256"}],"name":"FixedRewardSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LpStakeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MblkStakeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"MinimumCalculateRewardTimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"MinimumStakeDurationSet","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":[],"name":"PausedStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"lpAmount","type":"uint256"}],"name":"StakeLp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"mblkAmount","type":"uint256"}],"name":"StakeMblk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalReward","type":"uint256"}],"name":"TotalRewardSet","type":"event"},{"anonymous":false,"inputs":[],"name":"UnpausedStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentCycleId","type":"uint256"}],"name":"UpdatedCycleId","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"BalanceMBLK","type":"uint256"}],"name":"WithDrawnAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"WithdrawnLp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"WithdrawnMblk","type":"event"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"uint256","name":"uptoCycleId","type":"uint256"},{"internalType":"bool","name":"isMblk","type":"bool"}],"name":"calculateReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateRewardMinimumTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"uptoCycleId","type":"uint256"}],"name":"claimRewardsLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"uptoCycleId","type":"uint256"}],"name":"claimRewardsMBLK","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentCycleId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dynamicReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesCollectionWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isMblk","type":"bool"}],"name":"getMinimumWithdrawableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cycleId","type":"uint256"}],"name":"getStakingInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalClaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getUserFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastDynamicRewardSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastFixedRewardSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTotalRewardSetTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpRewardPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mblkRewardPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mblkToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumStakeDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adminAddress","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vestingAddress","type":"address"},{"internalType":"uint256","name":"newDynamicReward","type":"uint256"}],"name":"setDynamicReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"walletAddress","type":"address"}],"name":"setFeeWalletAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setFeesPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vestingAddress","type":"address"},{"internalType":"uint256","name":"newFixedReward","type":"uint256"}],"name":"setFixedReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"durationInMinutes","type":"uint256"}],"name":"setMinimumCalculateRewardTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"durationInMinutes","type":"uint256"}],"name":"setMinimumStakeDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timeForRewards","type":"uint256"}],"name":"setRewardTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFixedReward","type":"uint256"},{"internalType":"uint256","name":"newDynamicReward","type":"uint256"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"durationInMinutes","type":"uint256"}],"name":"setUnStakingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slpToken","outputs":[{"internalType":"contract LPStaked","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"smblkToken","outputs":[{"internalType":"contract MBLKStaked","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpAmount","type":"uint256"}],"name":"stakeLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mblkAmount","type":"uint256"}],"name":"stakeMBLK","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingInfo","outputs":[{"internalType":"uint256","name":"cycleId","type":"uint256"},{"internalType":"uint256","name":"blockTimeStamp","type":"uint256"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"uint256","name":"totalLpStaked","type":"uint256"},{"internalType":"uint256","name":"totalMblkStaked","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeForDynamicReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeForFixedReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLpStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMblkStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSLP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSMBLK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSlpMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSmblkMinted","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":[],"name":"unPauseStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateCycleId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"isMblk","type":"bool"}],"name":"updateStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"userLPStakesInformation","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userLpStakes","outputs":[{"internalType":"uint256","name":"lpAmount","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"claimedReward","type":"uint256"},{"internalType":"uint256","name":"lastClaimedTimeStamp","type":"uint256"},{"internalType":"uint256","name":"slpMinted","type":"uint256"},{"internalType":"uint256","name":"cycleId","type":"uint256"},{"internalType":"uint256","name":"lastEndTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"userMBLKStakeInformation","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMblkStakes","outputs":[{"internalType":"uint256","name":"mblkAmount","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"claimedReward","type":"uint256"},{"internalType":"uint256","name":"lastClaimedTimeStamp","type":"uint256"},{"internalType":"uint256","name":"smblkMinted","type":"uint256"},{"internalType":"uint256","name":"cycleId","type":"uint256"},{"internalType":"uint256","name":"lastEndTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToWithdraw","type":"uint256"}],"name":"withdrawLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountTowithdraw","type":"uint256"}],"name":"withdrawMBLK","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawOnlyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610100604052604051620078cc380380620078cc833981016040819052620000279162000193565b62000032336200010c565b600180556001600160a01b0380841660805282811660e0526016805491831661010002610100600160a81b031990921691909117905560405162000076906200015b565b604051809103905ff08015801562000090573d5f803e3d5ffd5b506001600160a01b031660a052604051620000ab9062000169565b604051809103905ff080158015620000c5573d5f803e3d5ffd5b506001600160a01b031660c05250506016805460ff19908116909155601e6017556203f480601855335f9081526004602052604090208054909116600117905550620001da565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6118a7806200478283390190565b6118a3806200602983390190565b80516001600160a01b03811681146200018e575f80fd5b919050565b5f805f60608486031215620001a6575f80fd5b620001b18462000177565b9250620001c16020850162000177565b9150620001d16040850162000177565b90509250925092565b60805160a05160c05160e0516144a9620002d95f395f81816106c901528181612320015281816124c301528181612ae001528181612cc701528181612cff01528181613290015261341001525f81816103ea0152818161255801528181612a0a01528181612bb601526134b501525f8181610432015281816121c8015281816130bb0152613a2a01525f818161092a01528181610e2f01528181610ecd0152818161107d015281816113c90152818161146701528181611d8d01528181611e0f01528181611f90015281816121330152818161272a01528181612ea70152818161302501528181613841015281816139ad01526139e501526144a95ff3fe608060405234801561000f575f80fd5b50600436106103b4575f3560e01c8063819ddb74116101f5578063d505c27411610114578063e9c4aa6a116100a9578063f2fde38b11610079578063f2fde38b146109e0578063f3b5d4af146109f3578063f4c8ad14146109fc578063f999c50614610a0f575f80fd5b8063e9c4aa6a146109a9578063ec498861146109bc578063f21c783b146109c4578063f24dbfd3146109cd575f80fd5b8063e4456ecb116100e4578063e4456ecb14610968578063e5cd3a951461097b578063e5da2cb21461098e578063e627f2db146109a1575f80fd5b8063d505c27414610912578063d940ff0e14610925578063db825df21461094c578063e14767b514610955575f80fd5b80639ef048c31161018a578063bdcaf1ca1161015a578063bdcaf1ca146108dc578063bff5f9c9146108e4578063c9cb1405146108ec578063cd250f42146108ff575f80fd5b80639ef048c3146108af578063a8bd7300146108b7578063aaacdda0146108c0578063ba41795f146108c9575f80fd5b8063983d90b4116101c5578063983d90b4146108725780639afd38a11461087b5780639c80984a1461088e5780639cabbab4146108a6575f80fd5b8063819ddb74146107e357806389dd64f7146108475780638da5cb5b1461085a57806396f62ab71461086a575f80fd5b80633be71728116102e157806363f009b6116102765780636d0d2bd9116102465780636d0d2bd9146107ac57806370480275146107b5578063715018a6146107c857806374ac7baa146107d0575f80fd5b806363f009b6146106eb578063654e51e7146106fe5780636ae02ae6146107115780636b9f545814610719575f80fd5b80634f84198f116102b15780634f84198f146106a057806357305920146106b35780635e5ef0ac146106bc5780635fcbd285146106c4575f80fd5b80633be71728146105bb5780633e695aba146105ce57806340e2bd0a146105d757806343e0567214610697575f80fd5b806315520c561161035757806324d7806c1161032757806324d7806c1461055a57806327c875151461058c57806331503ec414610595578063392cb1c2146105a8575f80fd5b806315520c561461045d5780631785f53c146104ea57806319954e54146104ff578063213ecbba14610551575f80fd5b806307ab47c91161039257806307ab47c9146103e557806307cdc3ea1461042457806308892d8f1461042d5780630e15561a14610454575f80fd5b806301daf12e146103b857806305efcba1146103d457806306d60427146103dc575b5f80fd5b6103c1600c5481565b6040519081526020015b60405180910390f35b6009546103c1565b6103c160095481565b61040c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103cb565b6103c1600a5481565b61040c7f000000000000000000000000000000000000000000000000000000000000000081565b6103c160145481565b6104af61046b366004614018565b6002602052805f5260405f205f91509050805f0154908060010154908060020154908060030154908060040154908060050154908060060154908060070154905088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016103cb565b6104fd6104f8366004614018565b610a17565b005b6104af61050d366004614018565b6003602052805f5260405f205f91509050805f0154908060010154908060020154908060030154908060040154908060050154908060060154908060070154905088565b6103c160175481565b61057c610568366004614018565b60046020525f908152604090205460ff1681565b60405190151581526020016103cb565b6103c160105481565b6104fd6105a3366004614018565b610a76565b6104fd6105b6366004614031565b610ad4565b6104fd6105c9366004614031565b610b61565b6103c1600e5481565b61066a6105e5366004614018565b6001600160a01b0381165f908152600260208181526040928390208351610100810185528154808252600183015493820184905293820154948101859052600382015460608201819052600483015460808301819052600584015460a08401819052600685015460c085015260079094015460e0909301929092529394929550919395565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103cb565b6103c1600d5481565b6104fd6106ae366004614048565b610fdd565b6103c160125481565b6103c1604681565b61040c7f000000000000000000000000000000000000000000000000000000000000000081565b6104fd6106f9366004614031565b6110f1565b6104fd61070c366004614070565b611562565b6104fd61167f565b61066a610727366004614018565b6001600160a01b0381165f908152600360208181526040928390208351610100810185528154808252600183015493820184905260028301549582018690529382015460608201819052600483015460808301819052600584015460a08401819052600685015460c085015260079094015460e0909301929092529394929550919395565b6103c160065481565b6104fd6107c3366004614018565b611705565b6104fd611760565b6104fd6107de366004614031565b611773565b61081f6107f1366004614031565b60056020525f9081526040902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a0016103cb565b6104fd610855366004614031565b61181d565b5f546001600160a01b031661040c565b600a546103c1565b6103c160075481565b6103c161088936600461409d565b611873565b60165461040c9061010090046001600160a01b031681565b6103c160115481565b6103c1601e81565b6103c160155481565b6103c1600b5481565b6103c16108d73660046140b8565b6118ca565b6104fd611c81565b6104fd611d62565b6104fd6108fa366004614031565b611e67565b6104fd61090d3660046140f5565b611f01565b6104fd610920366004614048565b61268a565b61040c7f000000000000000000000000000000000000000000000000000000000000000081565b6103c1600f5481565b6103c1610963366004614031565b612794565b6104fd610976366004614031565b6127e5565b6104fd610989366004614031565b612e16565b6104fd61099c366004614031565b6131ff565b6014546103c1565b61081f6109b7366004614031565b6135e2565b6008546103c1565b6103c160185481565b6104fd6109db366004614031565b61366c565b6104fd6109ee366004614018565b613b77565b6103c160135481565b6104fd610a0a366004614031565b613bed565b6104fd613bff565b610a1f613c82565b6001600160a01b0381165f81815260046020908152604091829020805460ff1916905590519182527fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f91015b60405180910390a150565b610a7e613c82565b60168054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f8c88aa723c2c1b75bec5bada66c3a346c71a7d59cd5a437e4240cfcc294a112b90602001610a6b565b610adc613c82565b5f8111610b235760405162461bcd60e51b815260206004820152601060248201526f0476976656e2056616c756520697320360841b60448201526064015b60405180910390fd5b610b2e81603c614137565b6015556040518181527ffe90761a9ba2f93e0d1b35de720c14bfedcae16e9d485d7e87c9eac57abce64890602001610a6b565b610b69613cdb565b60165460ff1615610b8c5760405162461bcd60e51b8152600401610b1a9061414e565b335f9081526003602081815260408084208151610100810183528154815260018201549381019390935260028101549183019190915291820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152600b54831115610c165760405162461bcd60e51b8152600401610b1a9061417a565b8051610c585760405162461bcd60e51b8152602060048201526011602482015270139bc813140814dd185ad948199bdd5b99607a1b6044820152606401610b1a565b825f03610c6957600b549150610c6d565b8291505b60408101514290811115610db957806018548360400151610c8e91906141c4565b03610cb2576015548260e00151610ca591906141c4565b6040830181905260e08301525b806018548360400151610cc591906141c4565b1115610ce957604082015160e08301819052601554610ce3916141c4565b60408301525b806018548360400151610cfc91906141c4565b1015610db9575f826040015182610d1391906141d7565b90505f60155482610d2491906141ea565b610d2f9060016141c4565b90505f81601554610d409190614137565b9050808560400151610d5291906141c4565b604086018190526015545f91610d6891906141d7565b9050601854818760200151610d7d91906141c4565b610d8791906141c4565b8510610d9c57604086015160e0870152610db4565b6015548660400151610dae91906141d7565b60e08701525b505050505b5f610dc533855f6118ca565b90505f8111610e0c5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610b1a565b6006546040516370a0823160e01b81523060048201528291906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610e74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e989190614209565b610ea291906141d7565b1015610ec05760405162461bcd60e51b8152600401610b1a90614220565b610ef46001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613d34565b8083606001818151610f0691906141c4565b905250610f148460016141c4565b60c0840152426080840152600880548291905f90610f339084906141c4565b9091555050335f81815260036020818152604092839020875181559087015160018201558287015160028201556060870151918101919091556080860151600482015560a0860151600582015560c0860151600682015560e0860151600790910155517fc788999b5ab7d1442929ec826e8e2ceccbbb29ad0750ac2ea5621010d6b0c2ea90610fc59084815260200190565b60405180910390a250505050610fda60018055565b50565b335f9081526004602052604090205460ff1661100b5760405162461bcd60e51b8152600401610b1a90614262565b60105442905f9061101c90836141d7565b9050600e548110156110705760405162461bcd60e51b815260206004820152601f60248201527f43616e206e6f7420736574206265666f7265204d696e696d756d2054696d65006044820152606401610b1a565b6110a56001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016853086613d91565b601082905560128390556110b7613dd0565b6040518381527f6b5bbca76259bd455d33d91433b33726ad33ac77c07aa858707dafc6726b8e2c906020015b60405180910390a150505050565b6110f9613cdb565b60165460ff161561111c5760405162461bcd60e51b8152600401610b1a9061414e565b335f9081526002602081815260408084208151610100810183528154815260018201549381019390935292830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152600b548311156111a35760405162461bcd60e51b8152600401610b1a9061417a565b80516111f15760405162461bcd60e51b815260206004820152601a60248201527f4e6f2073696e676c65204d424c4b207374616b6520666f756e640000000000006044820152606401610b1a565b825f0361120257600b549150611206565b8291505b604081015142908111156113525780601854836040015161122791906141c4565b0361124b576015548260e0015161123e91906141c4565b6040830181905260e08301525b80601854836040015161125e91906141c4565b111561128257604082015160e0830181905260155461127c916141c4565b60408301525b80601854836040015161129591906141c4565b1015611352575f8260400151826112ac91906141d7565b90505f601554826112bd91906141ea565b6112c89060016141c4565b90505f816015546112d99190614137565b90508085604001516112eb91906141c4565b604086018190526015545f9161130191906141d7565b905060185481876020015161131691906141c4565b61132091906141c4565b851061133557604086015160e087015261134d565b601554866040015161134791906141d7565b60e08701525b505050505b5f61135f338660016118ca565b90505f81116113a65760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610b1a565b6006546040516370a0823160e01b81523060048201528291906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561140e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114329190614209565b61143c91906141d7565b101561145a5760405162461bcd60e51b8152600401610b1a90614220565b61148e6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613d34565b608083018290526060830180518291906114a99083906141c4565b9052506114b78460016141c4565b60c0840152600880548291905f906114d09084906141c4565b9091555050335f81815260026020818152604092839020875181559087015160018201558287015191810191909155606086015160038201556080860151600482015560a0860151600582015560c0860151600682015560e0860151600790910155517f452ab7b11b9332913dac104f40627bb3daff6d29e63b4c09375854b43f04504b90610fc59084815260200190565b335f9081526004602052604090205460ff166115905760405162461bcd60e51b8152600401610b1a90614262565b5f82116115df5760405162461bcd60e51b815260206004820152601a60248201527f6e657746697865645265776172642063616e6e6f7420626520300000000000006044820152606401610b1a565b5f811161162e5760405162461bcd60e51b815260206004820152601c60248201527f6e657744796e616d69635265776172642063616e6e6f742062652030000000006044820152606401610b1a565b6012829055601381905561164281836141c4565b60148190556040519081527f09b40d736756e459b135fb3464351809a39241892fad0ebd5b0a6f77fa7fbb6d906020015b60405180910390a15050565b611687613c82565b60165460ff1615156001146116d15760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48155b9c185d5cd95960821b6044820152606401610b1a565b6016805460ff191690556040517fa2106ad60d1d654271167779d587dd39e2bb262d48d632f2d0b3d0262ce4d614905f90a1565b61170d613c82565b6001600160a01b0381165f81815260046020908152604091829020805460ff1916600117905590519182527f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e3399101610a6b565b611768613c82565b6117715f613e1e565b565b61177b613c82565b5f81116117dd5760405162461bcd60e51b815260206004820152602a60248201527f63616c63756c61746520726577617264206d696e696d756d2074696d6520636160448201526906e206e6f7420626520360b41b6064820152608401610b1a565b6117e881603c614137565b600d8190556040519081527fb4f3782ffaf0fb340d2d601843d3d490371e16abb7d5ce88283153c82729f47690602001610a6b565b611825613c82565b5f81116118625760405162461bcd60e51b815260206004820152600b60248201526a063616e6e6f7420626520360ac1b6044820152606401610b1a565b61186d81603c614137565b60185550565b5f81156118a857335f9081526002602052604081205460649061189790600a614137565b6118a191906141ea565b9392505050565b335f9081526003602052604081205460649061189790600a614137565b919050565b6016545f9060ff16156118ef5760405162461bcd60e51b8152600401610b1a9061414e565b600b548311156119415760405162461bcd60e51b815260206004820152601b60248201527f7570746f4379636c654964206973206f7574206f662072616e676500000000006044820152606401610b1a565b5f670de0b6b3a76400008185810361195c5750600b5461195f565b50845b8415611afa576001600160a01b0387165f90815260026020818152604092839020835161010081018552815480825260018301549382019390935292810154938301939093526003830154606083015260048301546080830152600583015460a0830152600683015460c083015260079092015460e082015290611a175760405162461bcd60e51b815260206004820152600f60248201526e139bc814dd185ad95cc8119bdd5b99608a1b6044820152606401610b1a565b60c08101515b828111611aed575f8181526005602052604090206004015415611adb575f818152600560205260408120600281015460049091015484519192909182908890611a67906064614137565b611a719190614137565b611a7b91906141ea565b90505f601e88611a8b8685614137565b611a959190614137565b611a9f9190614137565b90505f88611aaf81612710614137565b611ab99190614137565b90505f611ac682846141ea565b9050611ad2818c6141c4565b9a505050505050505b80611ae5816142a4565b915050611a1d565b50839450505050506118a1565b6001600160a01b0387165f90815260036020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945291820154606084015260048201546080840152600582015460a0840152600682015460c084015260079091015460e0830152611bab5760405162461bcd60e51b815260206004820152600f60248201526e139bc814dd185ad95cc8119bdd5b99608a1b6044820152606401610b1a565b60c08101515b828111611aed575f8181526005602052604090206003015415611c6f575f818152600560205260408120600281015460039091015484519192909182908890611bfb906064614137565b611c059190614137565b611c0f91906141ea565b90505f604688611c1f8685614137565b611c299190614137565b611c339190614137565b90505f88611c4381612710614137565b611c4d9190614137565b90505f611c5a82846141ea565b9050611c66818c6141c4565b9a505050505050505b80611c79816142a4565b915050611bb1565b335f9081526004602052604090205460ff16611caf5760405162461bcd60e51b8152600401610b1a90614262565b600b8054905f611cbe836142a4565b9091555050600b80545f818152600560208181526040808420815160a0810183528681524281850181815260145483860190815260075460608501908152600654608086019081529a9099529686528251845551600184015594516002830155945160038201559451600490950194909455935492519283529290917f35a0fd92ce75e29a94acce9d5ff19d1f7b3799fbfd719af21085c53f43c41bc79101611673565b611d6a613c82565b6006546040516370a0823160e01b81523060048201525f91906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611dd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611df69190614209565b611e0091906141d7565b9050611e366001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613d34565b7fab755d4e14947719135717c1f0951e324a1098f8514c61b42a4d3e81029541223382604051610a6b9291906142bc565b611e6f613c82565b5f81118015611e8057506105dc8111155b611ecc5760405162461bcd60e51b815260206004820181905260248201527f50657263656e74616765206f7574206f662072616e67652028302d31353030296044820152606401610b1a565b60178190556040518181527ff93a2bff8a3c568ccb95a18d15460f2059078dc8aba428120b9ed6ff8cb0a42d90602001610a6b565b60165460ff1615611f245760405162461bcd60e51b8152600401610b1a9061414e565b5f8211611f735760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610b1a565b8015612309576040516370a0823160e01b815233600482015282907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611fdd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120019190614209565b10156120445760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610b1a565b335f818152600260208181526040808420815161010081018352815481526001808301549482019490945293810154918401919091526003810154606084015260048101546080840152600581015460a0840152600681015460c08401526007015460e083015290926120b89183906118ca565b905080156120d85760405162461bcd60e51b8152600401610b1a906142d5565b81516121265760405162461bcd60e51b815260206004820152601f60248201527f4578697374696e6720616374697665207374616b65206e6f7420666f756e64006044820152606401610b1a565b61215b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087613d91565b8360065f82825461216c91906141c4565b90915550508151849083906121829083906141c4565b905250426020830181905260155461219a90826141c4565b60408401526015546121ac90826141c4565b60e08401526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f19906121ff90339089906004016142bc565b5f604051808303815f87803b158015612216575f80fd5b505af1158015612228573d5f803e3d5ffd5b505050508460095f82825461223d91906141c4565b92505081905550848360a00181815161225691906141c4565b905250600b546122679060016141c4565b60c08401908152335f81815260026020818152604092839020885181559088015160018201558288015191810191909155606087015160038201556080870151600482015560a087015160058201559251600684015560e086015160079093019290925590517f73b0b5c0996e7f0c8afb37970ee70e464754a234c0091a1f4322f69ad87241ce916122fa9188906142bc565b60405180910390a15050505050565b6040516370a0823160e01b815233600482015282907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561236d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123919190614209565b10156123d45760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610b1a565b335f8181526003602081815260408084208151610100810183528154815260018201549381019390935260028101549183019190915291820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152916124489082806118ca565b905080156124685760405162461bcd60e51b8152600401610b1a906142d5565b81516124b65760405162461bcd60e51b815260206004820152601f60248201527f4578697374696e6720616374697665207374616b65206e6f7420666f756e64006044820152606401610b1a565b6124eb6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087613d91565b8360075f8282546124fc91906141c4565b90915550508151849083906125129083906141c4565b905250426020830181905260155461252a90826141c4565b604084015260155461253c90826141c4565b60e08401526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f199061258f90339089906004016142bc565b5f604051808303815f87803b1580156125a6575f80fd5b505af11580156125b8573d5f803e3d5ffd5b5050505084600a5f8282546125cd91906141c4565b92505081905550848360a0018181516125e691906141c4565b905250600b546125f79060016141c4565b60c08401908152335f81815260036020818152604092839020885181559088015160018201558288015160028201556060880151918101919091556080870151600482015560a087015160058201559251600684015560e086015160079093019290925590517f14e36089f7e987ed3e8d4b78c4a603bdbf29b638926c926ecdcecef7651a6106916122fa9188906142bc565b335f9081526004602052604090205460ff166126b85760405162461bcd60e51b8152600401610b1a90614262565b600c5442905f906126c990836141d7565b9050600f5481101561271d5760405162461bcd60e51b815260206004820152601f60248201527f43616e206e6f7420736574204265666f7265206d696e696d756d2074696d65006044820152606401610b1a565b6127526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016853086613d91565b600c8290556013839055612764613dd0565b6040518381527f279ff15a10868910415b0a71a45f53299309ddb40ee84a738da2c6a1ae1e3531906020016110e3565b5f815f036127a357505f919050565b5f601754836127b29190614137565b6127c490670de0b6b3a7640000614137565b905069021e19e0c9bab24000005f6127dc82846141ea565b95945050505050565b6127ed613cdb565b335f908152600360208181526040928390208351610100810185528154815260018201549281019290925260028101549382019390935290820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e082018190524290811080159061287a57506018548260e0015161287691906141c4565b8111155b6128965760405162461bcd60e51b8152600401610b1a9061430c565b5f83116128b55760405162461bcd60e51b8152600401610b1a90614351565b60165460ff1615155f0361291457428260e00151106128e65760405162461bcd60e51b8152600401610b1a9061439c565b5f6128f2335f806118ca565b905080156129125760405162461bcd60e51b8152600401610b1a906142d5565b505b815161295a5760405162461bcd60e51b8152602060048201526015602482015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b6044820152606401610b1a565b81518311156129a25760405162461bcd60e51b8152602060048201526014602482015273139bdd08195b9bdd59da0813140814dd185ad95960621b6044820152606401610b1a565b81518311156129f35760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742062616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b6040516370a0823160e01b815233600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612a57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7b9190614209565b1015612ac95760405162461bcd60e51b815260206004820181905260248201527f7573657220736d626c6b2042616c616e6365206973206e6f7420656e6f7567686044820152606401610b1a565b6040516370a0823160e01b815230600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612b2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b519190614209565b1015612b9f5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742042616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b60405163079cc67960e41b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906379cc679090612bed90339087906004016142bc565b5f604051808303815f87803b158015612c04575f80fd5b505af1158015612c16573d5f803e3d5ffd5b505050505f612c2484612794565b90505f8111612c455760405162461bcd60e51b8152600401610b1a906143ea565b8251606490612c55906009614137565b612c5f91906141ea565b8411612cad5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74207769746864726177206c657373207468616e203130202500006044820152606401610b1a565b5f612cb882866141d7565b9050612cee6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613d34565b601654612d2d906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169161010090041684613d34565b84845f01818151612d3e91906141d7565b905250600780548691905f90612d559084906141d7565b9250508190555084600a5f828254612d6d91906141d7565b92505081905550848460a001818151612d8691906141d7565b905250335f81815260036020818152604092839020885181559088015160018201558288015160028201556060880151918101919091556080870151600482015560a0870151600582015560c0870151600682015560e0870151600790910155517ffed681a46cfeef8cdae4ae212ac4a61c0f801c7f8cf6015a58af69852130391d90610fc59088815260200190565b612e1e613cdb565b60165460ff1615612e415760405162461bcd60e51b8152600401610b1a9061414e565b5f8111612e905760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610b1a565b6040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612ef4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f189190614209565b1015612f5b5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682042616c616e636560701b6044820152606401610b1a565b335f9081526002602052604090205415612fb75760405162461bcd60e51b815260206004820152601b60248201527f4578697374696e6720616374697665207374616b6520666f756e6400000000006044820152606401610b1a565b335f818152600260208181526040928390208351610100810185528154815260018201549281019290925291820154928101929092526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460e082015290613055907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316903085613d91565b5f4290508260065f82825461306a91906141c4565b90915550508282526020820181905260155461308690826141c4565b604083015260155461309890826141c4565b60e0830152608082018190526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f19906130f290339087906004016142bc565b5f604051808303815f87803b158015613109575f80fd5b505af115801561311b573d5f803e3d5ffd5b505050508260095f82825461313091906141c4565b9091555050600b546131439060016141c4565b60c083015260a08201805184919061315c9083906141c4565b905250335f81815260026020818152604092839020865181559086015160018201558286015191810191909155606085015160038201556080850151600482015560a0850151600582015560c0850151600682015560e0850151600790910155517f9ea5f65ec30df4bcf385f5bbb6b825eda3af68bf05c9931dbb4528ce589ca887906131ec9086815260200190565b60405180910390a25050610fda60018055565b613207613cdb565b60165460ff161561322a5760405162461bcd60e51b8152600401610b1a9061414e565b5f81116132795760405162461bcd60e51b815260206004820152601e60248201527f416d6f756e74206d7573742062652067726561746572207468616e20302000006044820152606401610b1a565b6040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156132dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133019190614209565b10156133445760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682042616c616e636560701b6044820152606401610b1a565b335f90815260036020526040902054156133a05760405162461bcd60e51b815260206004820152601760248201527f4578697374696e67204c50205374616b6520466f756e640000000000000000006044820152606401610b1a565b335f818152600360208181526040928390208351610100810185528154815260018201549281019290925260028101549382019390935290820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e082015290613440907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316903085613d91565b8160075f82825461345191906141c4565b909155505080514290839083906134699083906141c4565b9052506020820181905260155461348090826141c4565b604083015260155461349290826141c4565b60e0830152608082018190526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f19906134ec90339087906004016142bc565b5f604051808303815f87803b158015613503575f80fd5b505af1158015613515573d5f803e3d5ffd5b5050505082600a5f82825461352a91906141c4565b92505081905550828260a00181815161354391906141c4565b905250600b546135549060016141c4565b60c08301908152335f81815260036020818152604092839020875181558188015160018201558388015160028201556060880151928101929092556080870151600483015560a087015160058301559351600682015560e08601516007909101555185815290917ec9f551bf78c05cb9aad786a9fb31581b9b78ab8180af56172424ccb1d014cd91016131ec565b5f805f805f600b548611156136395760405162461bcd60e51b815260206004820152601860248201527f4379636c65204964206973206f7574206f662052616e676500000000000000006044820152606401610b1a565b5050505f928352505060056020526040902080546001820154600483015460028401546003909401549294919390929091565b613674613cdb565b335f908152600260208181526040928390208351610100810185528154815260018201549281019290925291820154928101929092526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460e08201819052429081108015906136ff57506018548260e001516136fb91906141c4565b8111155b61371b5760405162461bcd60e51b8152600401610b1a9061430c565b5f831161373a5760405162461bcd60e51b8152600401610b1a90614351565b60165460ff1615155f0361379a57428260e001511061376b5760405162461bcd60e51b8152600401610b1a9061439c565b5f613778335f60016118ca565b905080156137985760405162461bcd60e51b8152600401610b1a906142d5565b505b81516137e05760405162461bcd60e51b8152602060048201526015602482015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b6044820152606401610b1a565b815183111561382a5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da0813509312c814dd185ad95960521b6044820152606401610b1a565b6040516370a0823160e01b815230600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561388e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138b29190614209565b10156139005760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742062616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b5f61390a84612794565b90505f811161392b5760405162461bcd60e51b8152600401610b1a906143ea565b825160649061393b906009614137565b61394591906141ea565b84116139935760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74207769746864726177206c657373207468616e203130202500006044820152606401610b1a565b5f61399e82866141d7565b90506139d46001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383613d34565b601654613a13906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169161010090041684613d34565b60405163079cc67960e41b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906379cc679090613a6190339089906004016142bc565b5f604051808303815f87803b158015613a78575f80fd5b505af1158015613a8a573d5f803e3d5ffd5b5050505084845f01818151613a9f91906141d7565b90525060a084018051869190613ab69083906141d7565b905250600980548691905f90613acd9084906141d7565b925050819055508460065f828254613ae591906141d7565b9091555050335f81815260026020818152604092839020885181559088015160018201558288015191810191909155606087015160038201556080870151600482015560a0870151600582015560c0870151600682015560e0870151600790910155517fef952877a2840f9e65b3398ff63ea5b7cd10c5b9300a7ee47c29359a5c07c24d90610fc59088815260200190565b613b7f613c82565b6001600160a01b038116613be45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b1a565b610fda81613e1e565b613bf5613c82565b600f819055600e55565b613c07613c82565b60165460ff1615613c4b5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4814185d5cd95960921b6044820152606401610b1a565b6016805460ff191660011790556040517f9ad0836c45d4ddec16a057e89fa5e103f2c9e2a92644bf8e5c0bbe0aa0b06733905f90a1565b5f546001600160a01b031633146117715760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b1a565b600260015403613d2d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b1a565b6002600155565b613d8c83846001600160a01b031663a9059cbb8585604051602401613d5a9291906142bc565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613e6d565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052613dca9186918216906323b872dd90608401613d5a565b50505050565b601354601254613de091906141c4565b6014819055426011556040519081527f09b40d736756e459b135fb3464351809a39241892fad0ebd5b0a6f77fa7fbb6d9060200160405180910390a1565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f613e816001600160a01b03841683613ece565b905080515f14158015613ea5575080806020019051810190613ea3919061442c565b155b15613d8c57604051635274afe760e01b81526001600160a01b0384166004820152602401610b1a565b6060613edb83835f613ee4565b90505b92915050565b606081471015613f095760405163cd78605960e01b8152306004820152602401610b1a565b5f80856001600160a01b03168486604051613f249190614447565b5f6040518083038185875af1925050503d805f8114613f5e576040519150601f19603f3d011682016040523d82523d5f602084013e613f63565b606091505b5091509150613f73868383613f7d565b9695505050505050565b606082613f9257613f8d82613fd9565b6118a1565b8151158015613fa957506001600160a01b0384163b155b15613fd257604051639996b31560e01b81526001600160a01b0385166004820152602401610b1a565b50806118a1565b805115613fe95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146118c5575f80fd5b5f60208284031215614028575f80fd5b613edb82614002565b5f60208284031215614041575f80fd5b5035919050565b5f8060408385031215614059575f80fd5b61406283614002565b946020939093013593505050565b5f8060408385031215614081575f80fd5b50508035926020909101359150565b8015158114610fda575f80fd5b5f602082840312156140ad575f80fd5b81356118a181614090565b5f805f606084860312156140ca575f80fd5b6140d384614002565b92506020840135915060408401356140ea81614090565b809150509250925092565b5f8060408385031215614106575f80fd5b82359150602083013561411881614090565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417613ede57613ede614123565b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b6020808252602a908201527f7570746f4379636c6549642069732067726561746564207468616e2063757272604082015269195b9d10de58db19525960b21b606082015260800190565b80820180821115613ede57613ede614123565b81810381811115613ede57613ede614123565b5f8261420457634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215614219575f80fd5b5051919050565b60208082526022908201527f6e6f7420656e6f7567682062616c616e636520696e2074686520636f6e74726160408201526118dd60f21b606082015260800190565b60208082526022908201527f4f6e6c792061646d696e732063616e2063616c6c20746869732066756e63746960408201526137b760f11b606082015260800190565b5f600182016142b5576142b5614123565b5060010190565b6001600160a01b03929092168252602082015260400190565b6020808252601e908201527f506c6561736520636c61696d2074686520726577617264732066697273740000604082015260600190565b60208082526025908201527f43616e207769746864726177206f6e6c7920696e20756e7374616b696e672070604082015264195c9a5bd960da1b606082015260800190565b6020808252602b908201527f416d6f756e7420746f2077697468647261772073686f756c642062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b6020808252602e908201527f43616e206e6f74207769746864726177206265666f7265204d696e696d756d2060408201526d29ba30b5b290223ab930ba34b7b760911b606082015260800190565b60208082526022908201527f506c6561736520616464206d6f726520416d6f756e7420746f20776974686472604082015261617760f01b606082015260800190565b5f6020828403121561443c575f80fd5b81516118a181614090565b5f82515f5b81811015614466576020818601810151858301520161444c565b505f92019182525091905056fea2646970667358221220291ffad9e947697ebb6448a69467c7197bd970ca6a99153fb06b9ac1e347723264736f6c63430008170033608060405234801562000010575f80fd5b506040518060400160405280600a81526020016913509312d4dd185ad95960b21b81525060405180604001604052806005815260200164734d424c4b60d81b81525081600390816200006391906200027f565b5060046200007282826200027f565b5050506200008f62000089620000da60201b60201c565b620000de565b6005805460ff60a01b19169055620000a85f336200012f565b620000d47f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200012f565b6200034b565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6200013b82826200013f565b5050565b5f8281526006602090815260408083206001600160a01b038516845290915290205460ff166200013b575f8281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556200019d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200020a57607f821691505b6020821081036200022957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200027a57805f5260205f20601f840160051c81016020851015620002565750805b601f840160051c820191505b8181101562000277575f815560010162000262565b50505b505050565b81516001600160401b038111156200029b576200029b620001e1565b620002b381620002ac8454620001f5565b846200022f565b602080601f831160018114620002e9575f8415620002d15750858301515b5f19600386901b1c1916600185901b17855562000343565b5f85815260208120601f198616915b828110156200031957888601518255948401946001909101908401620002f8565b50858210156200033757878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b61154e80620003595f395ff3fe608060405234801561000f575f80fd5b50600436106101d1575f3560e01c806369e2f0fb116100fe57806395d89b411161009e578063d53913931161006e578063d5391393146103ca578063d547741f146103de578063dd62ed3e146103f1578063f2fde38b14610404575f80fd5b806395d89b4114610395578063a217fddf1461039d578063a457c2d7146103a4578063a9059cbb146103b7575f80fd5b806379cc6790116100d957806379cc67901461034c5780638456cb591461035f5780638da5cb5b1461036757806391d1485414610382575f80fd5b806369e2f0fb1461030957806370a082311461031c578063715018a614610344575f80fd5b8063313ce567116101745780633f4ba83a116101445780633f4ba83a146102c957806340c10f19146102d157806342966c68146102e45780635c975abb146102f7575f80fd5b8063313ce5671461028157806336568abe1461029057806339509351146102a35780633dd1eb61146102b6575f80fd5b806318160ddd116101af57806318160ddd1461022557806323b872dd14610237578063248a9ca31461024a5780632f2ff15d1461026c575f80fd5b806301ffc9a7146101d557806306fdde03146101fd578063095ea7b314610212575b5f80fd5b6101e86101e3366004611258565b610417565b60405190151581526020015b60405180910390f35b61020561044d565b6040516101f491906112a1565b6101e86102203660046112ee565b6104dd565b6002545b6040519081526020016101f4565b6101e8610245366004611316565b6104f4565b61022961025836600461134f565b5f9081526006602052604090206001015490565b61027f61027a366004611366565b610517565b005b604051601281526020016101f4565b61027f61029e366004611366565b610540565b6101e86102b13660046112ee565b6105c3565b61027f6102c4366004611390565b6105e4565b61027f610606565b61027f6102df3660046112ee565b610618565b61027f6102f236600461134f565b610639565b600554600160a01b900460ff166101e8565b61027f610317366004611390565b610643565b61022961032a366004611390565b6001600160a01b03165f9081526020819052604090205490565b61027f610662565b61027f61035a3660046112ee565b610673565b61027f610694565b6005546040516001600160a01b0390911681526020016101f4565b6101e8610390366004611366565b6106a4565b6102056106ce565b6102295f81565b6101e86103b23660046112ee565b6106dd565b6101e86103c53660046112ee565b610757565b6102295f805160206114f983398151915281565b61027f6103ec366004611366565b610764565b6102296103ff3660046113a9565b610788565b61027f610412366004611390565b6107b2565b5f6001600160e01b03198216637965db0b60e01b148061044757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606003805461045c906113d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610488906113d1565b80156104d35780601f106104aa576101008083540402835291602001916104d3565b820191905f5260205f20905b8154815290600101906020018083116104b657829003601f168201915b5050505050905090565b5f336104ea818585610828565b5060019392505050565b5f3361050185828561094b565b61050c8585856109c3565b506001949350505050565b5f8281526006602052604090206001015461053181610b70565b61053b8383610b7a565b505050565b6001600160a01b03811633146105b55760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105bf8282610bff565b5050565b5f336104ea8185856105d58383610788565b6105df919061141d565b610828565b6105ec610c65565b6106035f805160206114f983398151915282610517565b50565b61060e610c65565b610616610cbf565b565b5f805160206114f983398151915261062f81610b70565b61053b8383610d14565b6106033382610ddc565b61064b610c65565b6106035f805160206114f983398151915282610764565b61066a610c65565b6106165f610f17565b5f805160206114f983398151915261068a81610b70565b61053b8383610ddc565b61069c610c65565b610616610f68565b5f9182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606004805461045c906113d1565b5f33816106ea8286610788565b90508381101561074a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105ac565b61050c8286868403610828565b5f336104ea8185856109c3565b5f8281526006602052604090206001015461077e81610b70565b61053b8383610bff565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6107ba610c65565b6001600160a01b03811661081f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105ac565b61060381610f17565b6001600160a01b03831661088a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105ac565b6001600160a01b0382166108eb5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105ac565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f6109568484610788565b90505f1981146109bd57818110156109b05760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105ac565b6109bd8484848403610828565b50505050565b6001600160a01b038316610a275760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105ac565b6001600160a01b038216610a895760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105ac565b610a94838383610fab565b6001600160a01b0383165f9081526020819052604090205481811015610b0b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105ac565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36109bd565b6106038133610fb3565b610b8482826106a4565b6105bf575f8281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610bbb3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b610c0982826106a4565b156105bf575f8281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6005546001600160a01b031633146106165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b610cc761100c565b6005805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610d6a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105ac565b610d755f8383610fab565b8060025f828254610d86919061141d565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038216610e3c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105ac565b610e47825f83610fab565b6001600160a01b0382165f9081526020819052604090205481811015610eba5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105ac565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b610f7061105c565b6005805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cf73390565b61053b61105c565b610fbd82826106a4565b6105bf57610fca816110a9565b610fd58360206110bb565b604051602001610fe6929190611430565b60408051601f198184030181529082905262461bcd60e51b82526105ac916004016112a1565b600554600160a01b900460ff166106165760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105ac565b600554600160a01b900460ff16156106165760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105ac565b60606104476001600160a01b03831660145b60605f6110c98360026114a4565b6110d490600261141d565b67ffffffffffffffff8111156110ec576110ec6114bb565b6040519080825280601f01601f191660200182016040528015611116576020820181803683370190505b509050600360fc1b815f81518110611130576111306114cf565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061115e5761115e6114cf565b60200101906001600160f81b03191690815f1a9053505f6111808460026114a4565b61118b90600161141d565b90505b6001811115611202576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106111bf576111bf6114cf565b1a60f81b8282815181106111d5576111d56114cf565b60200101906001600160f81b03191690815f1a90535060049490941c936111fb816114e3565b905061118e565b5083156112515760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105ac565b9392505050565b5f60208284031215611268575f80fd5b81356001600160e01b031981168114611251575f80fd5b5f5b83811015611299578181015183820152602001611281565b50505f910152565b602081525f82518060208401526112bf81604085016020870161127f565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146112e9575f80fd5b919050565b5f80604083850312156112ff575f80fd5b611308836112d3565b946020939093013593505050565b5f805f60608486031215611328575f80fd5b611331846112d3565b925061133f602085016112d3565b9150604084013590509250925092565b5f6020828403121561135f575f80fd5b5035919050565b5f8060408385031215611377575f80fd5b82359150611387602084016112d3565b90509250929050565b5f602082840312156113a0575f80fd5b611251826112d3565b5f80604083850312156113ba575f80fd5b6113c3836112d3565b9150611387602084016112d3565b600181811c908216806113e557607f821691505b60208210810361140357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561044757610447611409565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161146781601785016020880161127f565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161149881602884016020880161127f565b01602801949350505050565b808202811582820484141761044757610447611409565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f816114f1576114f1611409565b505f19019056fe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220f720ee2f49f3e2049eabb0eb64fd1d06ef2f2c2ee6e7665b7135d93e73b8fae564736f6c63430008170033608060405234801562000010575f80fd5b5060405180604001604052806008815260200167131414dd185ad95960c21b815250604051806040016040528060038152602001620734c560ec1b81525081600390816200005f91906200027b565b5060046200006e82826200027b565b5050506200008b62000085620000d660201b60201c565b620000da565b6005805460ff60a01b19169055620000a45f336200012b565b620000d07f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200012b565b62000347565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6200013782826200013b565b5050565b5f8281526006602090815260408083206001600160a01b038516845290915290205460ff1662000137575f8281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001993390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200020657607f821691505b6020821081036200022557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200027657805f5260205f20601f840160051c81016020851015620002525750805b601f840160051c820191505b8181101562000273575f81556001016200025e565b50505b505050565b81516001600160401b03811115620002975762000297620001dd565b620002af81620002a88454620001f1565b846200022b565b602080601f831160018114620002e5575f8415620002cd5750858301515b5f19600386901b1c1916600185901b1785556200033f565b5f85815260208120601f198616915b828110156200031557888601518255948401946001909101908401620002f4565b50858210156200033357878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b61154e80620003555f395ff3fe608060405234801561000f575f80fd5b50600436106101d1575f3560e01c806369e2f0fb116100fe57806395d89b411161009e578063d53913931161006e578063d5391393146103ca578063d547741f146103de578063dd62ed3e146103f1578063f2fde38b14610404575f80fd5b806395d89b4114610395578063a217fddf1461039d578063a457c2d7146103a4578063a9059cbb146103b7575f80fd5b806379cc6790116100d957806379cc67901461034c5780638456cb591461035f5780638da5cb5b1461036757806391d1485414610382575f80fd5b806369e2f0fb1461030957806370a082311461031c578063715018a614610344575f80fd5b8063313ce567116101745780633f4ba83a116101445780633f4ba83a146102c957806340c10f19146102d157806342966c68146102e45780635c975abb146102f7575f80fd5b8063313ce5671461028157806336568abe1461029057806339509351146102a35780633dd1eb61146102b6575f80fd5b806318160ddd116101af57806318160ddd1461022557806323b872dd14610237578063248a9ca31461024a5780632f2ff15d1461026c575f80fd5b806301ffc9a7146101d557806306fdde03146101fd578063095ea7b314610212575b5f80fd5b6101e86101e3366004611258565b610417565b60405190151581526020015b60405180910390f35b61020561044d565b6040516101f491906112a1565b6101e86102203660046112ee565b6104dd565b6002545b6040519081526020016101f4565b6101e8610245366004611316565b6104f4565b61022961025836600461134f565b5f9081526006602052604090206001015490565b61027f61027a366004611366565b610517565b005b604051601281526020016101f4565b61027f61029e366004611366565b610540565b6101e86102b13660046112ee565b6105c3565b61027f6102c4366004611390565b6105e4565b61027f610606565b61027f6102df3660046112ee565b610618565b61027f6102f236600461134f565b610639565b600554600160a01b900460ff166101e8565b61027f610317366004611390565b610643565b61022961032a366004611390565b6001600160a01b03165f9081526020819052604090205490565b61027f610662565b61027f61035a3660046112ee565b610673565b61027f610694565b6005546040516001600160a01b0390911681526020016101f4565b6101e8610390366004611366565b6106a4565b6102056106ce565b6102295f81565b6101e86103b23660046112ee565b6106dd565b6101e86103c53660046112ee565b610757565b6102295f805160206114f983398151915281565b61027f6103ec366004611366565b610764565b6102296103ff3660046113a9565b610788565b61027f610412366004611390565b6107b2565b5f6001600160e01b03198216637965db0b60e01b148061044757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606003805461045c906113d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610488906113d1565b80156104d35780601f106104aa576101008083540402835291602001916104d3565b820191905f5260205f20905b8154815290600101906020018083116104b657829003601f168201915b5050505050905090565b5f336104ea818585610828565b5060019392505050565b5f3361050185828561094b565b61050c8585856109c3565b506001949350505050565b5f8281526006602052604090206001015461053181610b70565b61053b8383610b7a565b505050565b6001600160a01b03811633146105b55760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105bf8282610bff565b5050565b5f336104ea8185856105d58383610788565b6105df919061141d565b610828565b6105ec610c65565b6106035f805160206114f983398151915282610517565b50565b61060e610c65565b610616610cbf565b565b5f805160206114f983398151915261062f81610b70565b61053b8383610d14565b6106033382610ddc565b61064b610c65565b6106035f805160206114f983398151915282610764565b61066a610c65565b6106165f610f17565b5f805160206114f983398151915261068a81610b70565b61053b8383610ddc565b61069c610c65565b610616610f68565b5f9182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606004805461045c906113d1565b5f33816106ea8286610788565b90508381101561074a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105ac565b61050c8286868403610828565b5f336104ea8185856109c3565b5f8281526006602052604090206001015461077e81610b70565b61053b8383610bff565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6107ba610c65565b6001600160a01b03811661081f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105ac565b61060381610f17565b6001600160a01b03831661088a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105ac565b6001600160a01b0382166108eb5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105ac565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f6109568484610788565b90505f1981146109bd57818110156109b05760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105ac565b6109bd8484848403610828565b50505050565b6001600160a01b038316610a275760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105ac565b6001600160a01b038216610a895760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105ac565b610a94838383610fab565b6001600160a01b0383165f9081526020819052604090205481811015610b0b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105ac565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36109bd565b6106038133610fb3565b610b8482826106a4565b6105bf575f8281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610bbb3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b610c0982826106a4565b156105bf575f8281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6005546001600160a01b031633146106165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b610cc761100c565b6005805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610d6a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105ac565b610d755f8383610fab565b8060025f828254610d86919061141d565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038216610e3c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105ac565b610e47825f83610fab565b6001600160a01b0382165f9081526020819052604090205481811015610eba5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105ac565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b610f7061105c565b6005805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cf73390565b61053b61105c565b610fbd82826106a4565b6105bf57610fca816110a9565b610fd58360206110bb565b604051602001610fe6929190611430565b60408051601f198184030181529082905262461bcd60e51b82526105ac916004016112a1565b600554600160a01b900460ff166106165760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016105ac565b600554600160a01b900460ff16156106165760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016105ac565b60606104476001600160a01b03831660145b60605f6110c98360026114a4565b6110d490600261141d565b67ffffffffffffffff8111156110ec576110ec6114bb565b6040519080825280601f01601f191660200182016040528015611116576020820181803683370190505b509050600360fc1b815f81518110611130576111306114cf565b60200101906001600160f81b03191690815f1a905350600f60fb1b8160018151811061115e5761115e6114cf565b60200101906001600160f81b03191690815f1a9053505f6111808460026114a4565b61118b90600161141d565b90505b6001811115611202576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106111bf576111bf6114cf565b1a60f81b8282815181106111d5576111d56114cf565b60200101906001600160f81b03191690815f1a90535060049490941c936111fb816114e3565b905061118e565b5083156112515760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016105ac565b9392505050565b5f60208284031215611268575f80fd5b81356001600160e01b031981168114611251575f80fd5b5f5b83811015611299578181015183820152602001611281565b50505f910152565b602081525f82518060208401526112bf81604085016020870161127f565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146112e9575f80fd5b919050565b5f80604083850312156112ff575f80fd5b611308836112d3565b946020939093013593505050565b5f805f60608486031215611328575f80fd5b611331846112d3565b925061133f602085016112d3565b9150604084013590509250925092565b5f6020828403121561135f575f80fd5b5035919050565b5f8060408385031215611377575f80fd5b82359150611387602084016112d3565b90509250929050565b5f602082840312156113a0575f80fd5b611251826112d3565b5f80604083850312156113ba575f80fd5b6113c3836112d3565b9150611387602084016112d3565b600181811c908216806113e557607f821691505b60208210810361140357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561044757610447611409565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161146781601785016020880161127f565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161149881602884016020880161127f565b01602801949350505050565b808202811582820484141761044757610447611409565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f816114f1576114f1611409565b505f19019056fe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220b5238863d9c7280935da6daa40f884a82c3d1c9fa091414489cad77bcd9417f364736f6c63430008170033000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a520000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de000000000000000000000000f56c9be0c43fef3b648f5b63a1274b12eeb945d6
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106103b4575f3560e01c8063819ddb74116101f5578063d505c27411610114578063e9c4aa6a116100a9578063f2fde38b11610079578063f2fde38b146109e0578063f3b5d4af146109f3578063f4c8ad14146109fc578063f999c50614610a0f575f80fd5b8063e9c4aa6a146109a9578063ec498861146109bc578063f21c783b146109c4578063f24dbfd3146109cd575f80fd5b8063e4456ecb116100e4578063e4456ecb14610968578063e5cd3a951461097b578063e5da2cb21461098e578063e627f2db146109a1575f80fd5b8063d505c27414610912578063d940ff0e14610925578063db825df21461094c578063e14767b514610955575f80fd5b80639ef048c31161018a578063bdcaf1ca1161015a578063bdcaf1ca146108dc578063bff5f9c9146108e4578063c9cb1405146108ec578063cd250f42146108ff575f80fd5b80639ef048c3146108af578063a8bd7300146108b7578063aaacdda0146108c0578063ba41795f146108c9575f80fd5b8063983d90b4116101c5578063983d90b4146108725780639afd38a11461087b5780639c80984a1461088e5780639cabbab4146108a6575f80fd5b8063819ddb74146107e357806389dd64f7146108475780638da5cb5b1461085a57806396f62ab71461086a575f80fd5b80633be71728116102e157806363f009b6116102765780636d0d2bd9116102465780636d0d2bd9146107ac57806370480275146107b5578063715018a6146107c857806374ac7baa146107d0575f80fd5b806363f009b6146106eb578063654e51e7146106fe5780636ae02ae6146107115780636b9f545814610719575f80fd5b80634f84198f116102b15780634f84198f146106a057806357305920146106b35780635e5ef0ac146106bc5780635fcbd285146106c4575f80fd5b80633be71728146105bb5780633e695aba146105ce57806340e2bd0a146105d757806343e0567214610697575f80fd5b806315520c561161035757806324d7806c1161032757806324d7806c1461055a57806327c875151461058c57806331503ec414610595578063392cb1c2146105a8575f80fd5b806315520c561461045d5780631785f53c146104ea57806319954e54146104ff578063213ecbba14610551575f80fd5b806307ab47c91161039257806307ab47c9146103e557806307cdc3ea1461042457806308892d8f1461042d5780630e15561a14610454575f80fd5b806301daf12e146103b857806305efcba1146103d457806306d60427146103dc575b5f80fd5b6103c1600c5481565b6040519081526020015b60405180910390f35b6009546103c1565b6103c160095481565b61040c7f000000000000000000000000826c770fdfdb5e2661e337feb5c1ce53cea3739281565b6040516001600160a01b0390911681526020016103cb565b6103c1600a5481565b61040c7f000000000000000000000000104285168b7abe29686c56416e805f486536383781565b6103c160145481565b6104af61046b366004614018565b6002602052805f5260405f205f91509050805f0154908060010154908060020154908060030154908060040154908060050154908060060154908060070154905088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016103cb565b6104fd6104f8366004614018565b610a17565b005b6104af61050d366004614018565b6003602052805f5260405f205f91509050805f0154908060010154908060020154908060030154908060040154908060050154908060060154908060070154905088565b6103c160175481565b61057c610568366004614018565b60046020525f908152604090205460ff1681565b60405190151581526020016103cb565b6103c160105481565b6104fd6105a3366004614018565b610a76565b6104fd6105b6366004614031565b610ad4565b6104fd6105c9366004614031565b610b61565b6103c1600e5481565b61066a6105e5366004614018565b6001600160a01b0381165f908152600260208181526040928390208351610100810185528154808252600183015493820184905293820154948101859052600382015460608201819052600483015460808301819052600584015460a08401819052600685015460c085015260079094015460e0909301929092529394929550919395565b604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103cb565b6103c1600d5481565b6104fd6106ae366004614048565b610fdd565b6103c160125481565b6103c1604681565b61040c7f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de81565b6104fd6106f9366004614031565b6110f1565b6104fd61070c366004614070565b611562565b6104fd61167f565b61066a610727366004614018565b6001600160a01b0381165f908152600360208181526040928390208351610100810185528154808252600183015493820184905260028301549582018690529382015460608201819052600483015460808301819052600584015460a08401819052600685015460c085015260079094015460e0909301929092529394929550919395565b6103c160065481565b6104fd6107c3366004614018565b611705565b6104fd611760565b6104fd6107de366004614031565b611773565b61081f6107f1366004614031565b60056020525f9081526040902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a0016103cb565b6104fd610855366004614031565b61181d565b5f546001600160a01b031661040c565b600a546103c1565b6103c160075481565b6103c161088936600461409d565b611873565b60165461040c9061010090046001600160a01b031681565b6103c160115481565b6103c1601e81565b6103c160155481565b6103c1600b5481565b6103c16108d73660046140b8565b6118ca565b6104fd611c81565b6104fd611d62565b6104fd6108fa366004614031565b611e67565b6104fd61090d3660046140f5565b611f01565b6104fd610920366004614048565b61268a565b61040c7f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5281565b6103c1600f5481565b6103c1610963366004614031565b612794565b6104fd610976366004614031565b6127e5565b6104fd610989366004614031565b612e16565b6104fd61099c366004614031565b6131ff565b6014546103c1565b61081f6109b7366004614031565b6135e2565b6008546103c1565b6103c160185481565b6104fd6109db366004614031565b61366c565b6104fd6109ee366004614018565b613b77565b6103c160135481565b6104fd610a0a366004614031565b613bed565b6104fd613bff565b610a1f613c82565b6001600160a01b0381165f81815260046020908152604091829020805460ff1916905590519182527fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f91015b60405180910390a150565b610a7e613c82565b60168054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f8c88aa723c2c1b75bec5bada66c3a346c71a7d59cd5a437e4240cfcc294a112b90602001610a6b565b610adc613c82565b5f8111610b235760405162461bcd60e51b815260206004820152601060248201526f0476976656e2056616c756520697320360841b60448201526064015b60405180910390fd5b610b2e81603c614137565b6015556040518181527ffe90761a9ba2f93e0d1b35de720c14bfedcae16e9d485d7e87c9eac57abce64890602001610a6b565b610b69613cdb565b60165460ff1615610b8c5760405162461bcd60e51b8152600401610b1a9061414e565b335f9081526003602081815260408084208151610100810183528154815260018201549381019390935260028101549183019190915291820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152600b54831115610c165760405162461bcd60e51b8152600401610b1a9061417a565b8051610c585760405162461bcd60e51b8152602060048201526011602482015270139bc813140814dd185ad948199bdd5b99607a1b6044820152606401610b1a565b825f03610c6957600b549150610c6d565b8291505b60408101514290811115610db957806018548360400151610c8e91906141c4565b03610cb2576015548260e00151610ca591906141c4565b6040830181905260e08301525b806018548360400151610cc591906141c4565b1115610ce957604082015160e08301819052601554610ce3916141c4565b60408301525b806018548360400151610cfc91906141c4565b1015610db9575f826040015182610d1391906141d7565b90505f60155482610d2491906141ea565b610d2f9060016141c4565b90505f81601554610d409190614137565b9050808560400151610d5291906141c4565b604086018190526015545f91610d6891906141d7565b9050601854818760200151610d7d91906141c4565b610d8791906141c4565b8510610d9c57604086015160e0870152610db4565b6015548660400151610dae91906141d7565b60e08701525b505050505b5f610dc533855f6118ca565b90505f8111610e0c5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610b1a565b6006546040516370a0823160e01b81523060048201528291906001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216906370a0823190602401602060405180830381865afa158015610e74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e989190614209565b610ea291906141d7565b1015610ec05760405162461bcd60e51b8152600401610b1a90614220565b610ef46001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a52163383613d34565b8083606001818151610f0691906141c4565b905250610f148460016141c4565b60c0840152426080840152600880548291905f90610f339084906141c4565b9091555050335f81815260036020818152604092839020875181559087015160018201558287015160028201556060870151918101919091556080860151600482015560a0860151600582015560c0860151600682015560e0860151600790910155517fc788999b5ab7d1442929ec826e8e2ceccbbb29ad0750ac2ea5621010d6b0c2ea90610fc59084815260200190565b60405180910390a250505050610fda60018055565b50565b335f9081526004602052604090205460ff1661100b5760405162461bcd60e51b8152600401610b1a90614262565b60105442905f9061101c90836141d7565b9050600e548110156110705760405162461bcd60e51b815260206004820152601f60248201527f43616e206e6f7420736574206265666f7265204d696e696d756d2054696d65006044820152606401610b1a565b6110a56001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216853086613d91565b601082905560128390556110b7613dd0565b6040518381527f6b5bbca76259bd455d33d91433b33726ad33ac77c07aa858707dafc6726b8e2c906020015b60405180910390a150505050565b6110f9613cdb565b60165460ff161561111c5760405162461bcd60e51b8152600401610b1a9061414e565b335f9081526002602081815260408084208151610100810183528154815260018201549381019390935292830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152600b548311156111a35760405162461bcd60e51b8152600401610b1a9061417a565b80516111f15760405162461bcd60e51b815260206004820152601a60248201527f4e6f2073696e676c65204d424c4b207374616b6520666f756e640000000000006044820152606401610b1a565b825f0361120257600b549150611206565b8291505b604081015142908111156113525780601854836040015161122791906141c4565b0361124b576015548260e0015161123e91906141c4565b6040830181905260e08301525b80601854836040015161125e91906141c4565b111561128257604082015160e0830181905260155461127c916141c4565b60408301525b80601854836040015161129591906141c4565b1015611352575f8260400151826112ac91906141d7565b90505f601554826112bd91906141ea565b6112c89060016141c4565b90505f816015546112d99190614137565b90508085604001516112eb91906141c4565b604086018190526015545f9161130191906141d7565b905060185481876020015161131691906141c4565b61132091906141c4565b851061133557604086015160e087015261134d565b601554866040015161134791906141d7565b60e08701525b505050505b5f61135f338660016118ca565b90505f81116113a65760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610b1a565b6006546040516370a0823160e01b81523060048201528291906001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216906370a0823190602401602060405180830381865afa15801561140e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114329190614209565b61143c91906141d7565b101561145a5760405162461bcd60e51b8152600401610b1a90614220565b61148e6001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a52163383613d34565b608083018290526060830180518291906114a99083906141c4565b9052506114b78460016141c4565b60c0840152600880548291905f906114d09084906141c4565b9091555050335f81815260026020818152604092839020875181559087015160018201558287015191810191909155606086015160038201556080860151600482015560a0860151600582015560c0860151600682015560e0860151600790910155517f452ab7b11b9332913dac104f40627bb3daff6d29e63b4c09375854b43f04504b90610fc59084815260200190565b335f9081526004602052604090205460ff166115905760405162461bcd60e51b8152600401610b1a90614262565b5f82116115df5760405162461bcd60e51b815260206004820152601a60248201527f6e657746697865645265776172642063616e6e6f7420626520300000000000006044820152606401610b1a565b5f811161162e5760405162461bcd60e51b815260206004820152601c60248201527f6e657744796e616d69635265776172642063616e6e6f742062652030000000006044820152606401610b1a565b6012829055601381905561164281836141c4565b60148190556040519081527f09b40d736756e459b135fb3464351809a39241892fad0ebd5b0a6f77fa7fbb6d906020015b60405180910390a15050565b611687613c82565b60165460ff1615156001146116d15760405162461bcd60e51b815260206004820152601060248201526f105b1c9958591e48155b9c185d5cd95960821b6044820152606401610b1a565b6016805460ff191690556040517fa2106ad60d1d654271167779d587dd39e2bb262d48d632f2d0b3d0262ce4d614905f90a1565b61170d613c82565b6001600160a01b0381165f81815260046020908152604091829020805460ff1916600117905590519182527f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e3399101610a6b565b611768613c82565b6117715f613e1e565b565b61177b613c82565b5f81116117dd5760405162461bcd60e51b815260206004820152602a60248201527f63616c63756c61746520726577617264206d696e696d756d2074696d6520636160448201526906e206e6f7420626520360b41b6064820152608401610b1a565b6117e881603c614137565b600d8190556040519081527fb4f3782ffaf0fb340d2d601843d3d490371e16abb7d5ce88283153c82729f47690602001610a6b565b611825613c82565b5f81116118625760405162461bcd60e51b815260206004820152600b60248201526a063616e6e6f7420626520360ac1b6044820152606401610b1a565b61186d81603c614137565b60185550565b5f81156118a857335f9081526002602052604081205460649061189790600a614137565b6118a191906141ea565b9392505050565b335f9081526003602052604081205460649061189790600a614137565b919050565b6016545f9060ff16156118ef5760405162461bcd60e51b8152600401610b1a9061414e565b600b548311156119415760405162461bcd60e51b815260206004820152601b60248201527f7570746f4379636c654964206973206f7574206f662072616e676500000000006044820152606401610b1a565b5f670de0b6b3a76400008185810361195c5750600b5461195f565b50845b8415611afa576001600160a01b0387165f90815260026020818152604092839020835161010081018552815480825260018301549382019390935292810154938301939093526003830154606083015260048301546080830152600583015460a0830152600683015460c083015260079092015460e082015290611a175760405162461bcd60e51b815260206004820152600f60248201526e139bc814dd185ad95cc8119bdd5b99608a1b6044820152606401610b1a565b60c08101515b828111611aed575f8181526005602052604090206004015415611adb575f818152600560205260408120600281015460049091015484519192909182908890611a67906064614137565b611a719190614137565b611a7b91906141ea565b90505f601e88611a8b8685614137565b611a959190614137565b611a9f9190614137565b90505f88611aaf81612710614137565b611ab99190614137565b90505f611ac682846141ea565b9050611ad2818c6141c4565b9a505050505050505b80611ae5816142a4565b915050611a1d565b50839450505050506118a1565b6001600160a01b0387165f90815260036020818152604092839020835161010081018552815480825260018301549382019390935260028201549481019490945291820154606084015260048201546080840152600582015460a0840152600682015460c084015260079091015460e0830152611bab5760405162461bcd60e51b815260206004820152600f60248201526e139bc814dd185ad95cc8119bdd5b99608a1b6044820152606401610b1a565b60c08101515b828111611aed575f8181526005602052604090206003015415611c6f575f818152600560205260408120600281015460039091015484519192909182908890611bfb906064614137565b611c059190614137565b611c0f91906141ea565b90505f604688611c1f8685614137565b611c299190614137565b611c339190614137565b90505f88611c4381612710614137565b611c4d9190614137565b90505f611c5a82846141ea565b9050611c66818c6141c4565b9a505050505050505b80611c79816142a4565b915050611bb1565b335f9081526004602052604090205460ff16611caf5760405162461bcd60e51b8152600401610b1a90614262565b600b8054905f611cbe836142a4565b9091555050600b80545f818152600560208181526040808420815160a0810183528681524281850181815260145483860190815260075460608501908152600654608086019081529a9099529686528251845551600184015594516002830155945160038201559451600490950194909455935492519283529290917f35a0fd92ce75e29a94acce9d5ff19d1f7b3799fbfd719af21085c53f43c41bc79101611673565b611d6a613c82565b6006546040516370a0823160e01b81523060048201525f91906001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216906370a0823190602401602060405180830381865afa158015611dd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611df69190614209565b611e0091906141d7565b9050611e366001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a52163383613d34565b7fab755d4e14947719135717c1f0951e324a1098f8514c61b42a4d3e81029541223382604051610a6b9291906142bc565b611e6f613c82565b5f81118015611e8057506105dc8111155b611ecc5760405162461bcd60e51b815260206004820181905260248201527f50657263656e74616765206f7574206f662072616e67652028302d31353030296044820152606401610b1a565b60178190556040518181527ff93a2bff8a3c568ccb95a18d15460f2059078dc8aba428120b9ed6ff8cb0a42d90602001610a6b565b60165460ff1615611f245760405162461bcd60e51b8152600401610b1a9061414e565b5f8211611f735760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610b1a565b8015612309576040516370a0823160e01b815233600482015282907f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a526001600160a01b0316906370a0823190602401602060405180830381865afa158015611fdd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120019190614209565b10156120445760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610b1a565b335f818152600260208181526040808420815161010081018352815481526001808301549482019490945293810154918401919091526003810154606084015260048101546080840152600581015460a0840152600681015460c08401526007015460e083015290926120b89183906118ca565b905080156120d85760405162461bcd60e51b8152600401610b1a906142d5565b81516121265760405162461bcd60e51b815260206004820152601f60248201527f4578697374696e6720616374697665207374616b65206e6f7420666f756e64006044820152606401610b1a565b61215b6001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216333087613d91565b8360065f82825461216c91906141c4565b90915550508151849083906121829083906141c4565b905250426020830181905260155461219a90826141c4565b60408401526015546121ac90826141c4565b60e08401526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000104285168b7abe29686c56416e805f486536383716906340c10f19906121ff90339089906004016142bc565b5f604051808303815f87803b158015612216575f80fd5b505af1158015612228573d5f803e3d5ffd5b505050508460095f82825461223d91906141c4565b92505081905550848360a00181815161225691906141c4565b905250600b546122679060016141c4565b60c08401908152335f81815260026020818152604092839020885181559088015160018201558288015191810191909155606087015160038201556080870151600482015560a087015160058201559251600684015560e086015160079093019290925590517f73b0b5c0996e7f0c8afb37970ee70e464754a234c0091a1f4322f69ad87241ce916122fa9188906142bc565b60405180910390a15050505050565b6040516370a0823160e01b815233600482015282907f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de6001600160a01b0316906370a0823190602401602060405180830381865afa15801561236d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123919190614209565b10156123d45760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b6044820152606401610b1a565b335f8181526003602081815260408084208151610100810183528154815260018201549381019390935260028101549183019190915291820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e0820152916124489082806118ca565b905080156124685760405162461bcd60e51b8152600401610b1a906142d5565b81516124b65760405162461bcd60e51b815260206004820152601f60248201527f4578697374696e6720616374697665207374616b65206e6f7420666f756e64006044820152606401610b1a565b6124eb6001600160a01b037f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de16333087613d91565b8360075f8282546124fc91906141c4565b90915550508151849083906125129083906141c4565b905250426020830181905260155461252a90826141c4565b604084015260155461253c90826141c4565b60e08401526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000826c770fdfdb5e2661e337feb5c1ce53cea3739216906340c10f199061258f90339089906004016142bc565b5f604051808303815f87803b1580156125a6575f80fd5b505af11580156125b8573d5f803e3d5ffd5b5050505084600a5f8282546125cd91906141c4565b92505081905550848360a0018181516125e691906141c4565b905250600b546125f79060016141c4565b60c08401908152335f81815260036020818152604092839020885181559088015160018201558288015160028201556060880151918101919091556080870151600482015560a087015160058201559251600684015560e086015160079093019290925590517f14e36089f7e987ed3e8d4b78c4a603bdbf29b638926c926ecdcecef7651a6106916122fa9188906142bc565b335f9081526004602052604090205460ff166126b85760405162461bcd60e51b8152600401610b1a90614262565b600c5442905f906126c990836141d7565b9050600f5481101561271d5760405162461bcd60e51b815260206004820152601f60248201527f43616e206e6f7420736574204265666f7265206d696e696d756d2074696d65006044820152606401610b1a565b6127526001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5216853086613d91565b600c8290556013839055612764613dd0565b6040518381527f279ff15a10868910415b0a71a45f53299309ddb40ee84a738da2c6a1ae1e3531906020016110e3565b5f815f036127a357505f919050565b5f601754836127b29190614137565b6127c490670de0b6b3a7640000614137565b905069021e19e0c9bab24000005f6127dc82846141ea565b95945050505050565b6127ed613cdb565b335f908152600360208181526040928390208351610100810185528154815260018201549281019290925260028101549382019390935290820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e082018190524290811080159061287a57506018548260e0015161287691906141c4565b8111155b6128965760405162461bcd60e51b8152600401610b1a9061430c565b5f83116128b55760405162461bcd60e51b8152600401610b1a90614351565b60165460ff1615155f0361291457428260e00151106128e65760405162461bcd60e51b8152600401610b1a9061439c565b5f6128f2335f806118ca565b905080156129125760405162461bcd60e51b8152600401610b1a906142d5565b505b815161295a5760405162461bcd60e51b8152602060048201526015602482015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b6044820152606401610b1a565b81518311156129a25760405162461bcd60e51b8152602060048201526014602482015273139bdd08195b9bdd59da0813140814dd185ad95960621b6044820152606401610b1a565b81518311156129f35760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742062616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b6040516370a0823160e01b815233600482015283907f000000000000000000000000826c770fdfdb5e2661e337feb5c1ce53cea373926001600160a01b0316906370a0823190602401602060405180830381865afa158015612a57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7b9190614209565b1015612ac95760405162461bcd60e51b815260206004820181905260248201527f7573657220736d626c6b2042616c616e6365206973206e6f7420656e6f7567686044820152606401610b1a565b6040516370a0823160e01b815230600482015283907f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de6001600160a01b0316906370a0823190602401602060405180830381865afa158015612b2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b519190614209565b1015612b9f5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742042616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b60405163079cc67960e41b81526001600160a01b037f000000000000000000000000826c770fdfdb5e2661e337feb5c1ce53cea3739216906379cc679090612bed90339087906004016142bc565b5f604051808303815f87803b158015612c04575f80fd5b505af1158015612c16573d5f803e3d5ffd5b505050505f612c2484612794565b90505f8111612c455760405162461bcd60e51b8152600401610b1a906143ea565b8251606490612c55906009614137565b612c5f91906141ea565b8411612cad5760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74207769746864726177206c657373207468616e203130202500006044820152606401610b1a565b5f612cb882866141d7565b9050612cee6001600160a01b037f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de163383613d34565b601654612d2d906001600160a01b037f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de81169161010090041684613d34565b84845f01818151612d3e91906141d7565b905250600780548691905f90612d559084906141d7565b9250508190555084600a5f828254612d6d91906141d7565b92505081905550848460a001818151612d8691906141d7565b905250335f81815260036020818152604092839020885181559088015160018201558288015160028201556060880151918101919091556080870151600482015560a0870151600582015560c0870151600682015560e0870151600790910155517ffed681a46cfeef8cdae4ae212ac4a61c0f801c7f8cf6015a58af69852130391d90610fc59088815260200190565b612e1e613cdb565b60165460ff1615612e415760405162461bcd60e51b8152600401610b1a9061414e565b5f8111612e905760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610b1a565b6040516370a0823160e01b815233600482015281907f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a526001600160a01b0316906370a0823190602401602060405180830381865afa158015612ef4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f189190614209565b1015612f5b5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682042616c616e636560701b6044820152606401610b1a565b335f9081526002602052604090205415612fb75760405162461bcd60e51b815260206004820152601b60248201527f4578697374696e6720616374697665207374616b6520666f756e6400000000006044820152606401610b1a565b335f818152600260208181526040928390208351610100810185528154815260018201549281019290925291820154928101929092526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460e082015290613055907f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a526001600160a01b0316903085613d91565b5f4290508260065f82825461306a91906141c4565b90915550508282526020820181905260155461308690826141c4565b604083015260155461309890826141c4565b60e0830152608082018190526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000104285168b7abe29686c56416e805f486536383716906340c10f19906130f290339087906004016142bc565b5f604051808303815f87803b158015613109575f80fd5b505af115801561311b573d5f803e3d5ffd5b505050508260095f82825461313091906141c4565b9091555050600b546131439060016141c4565b60c083015260a08201805184919061315c9083906141c4565b905250335f81815260026020818152604092839020865181559086015160018201558286015191810191909155606085015160038201556080850151600482015560a0850151600582015560c0850151600682015560e0850151600790910155517f9ea5f65ec30df4bcf385f5bbb6b825eda3af68bf05c9931dbb4528ce589ca887906131ec9086815260200190565b60405180910390a25050610fda60018055565b613207613cdb565b60165460ff161561322a5760405162461bcd60e51b8152600401610b1a9061414e565b5f81116132795760405162461bcd60e51b815260206004820152601e60248201527f416d6f756e74206d7573742062652067726561746572207468616e20302000006044820152606401610b1a565b6040516370a0823160e01b815233600482015281907f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de6001600160a01b0316906370a0823190602401602060405180830381865afa1580156132dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133019190614209565b10156133445760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682042616c616e636560701b6044820152606401610b1a565b335f90815260036020526040902054156133a05760405162461bcd60e51b815260206004820152601760248201527f4578697374696e67204c50205374616b6520466f756e640000000000000000006044820152606401610b1a565b335f818152600360208181526040928390208351610100810185528154815260018201549281019290925260028101549382019390935290820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460e082015290613440907f0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de6001600160a01b0316903085613d91565b8160075f82825461345191906141c4565b909155505080514290839083906134699083906141c4565b9052506020820181905260155461348090826141c4565b604083015260155461349290826141c4565b60e0830152608082018190526040516340c10f1960e01b81526001600160a01b037f000000000000000000000000826c770fdfdb5e2661e337feb5c1ce53cea3739216906340c10f19906134ec90339087906004016142bc565b5f604051808303815f87803b158015613503575f80fd5b505af1158015613515573d5f803e3d5ffd5b5050505082600a5f82825461352a91906141c4565b92505081905550828260a00181815161354391906141c4565b905250600b546135549060016141c4565b60c08301908152335f81815260036020818152604092839020875181558188015160018201558388015160028201556060880151928101929092556080870151600483015560a087015160058301559351600682015560e08601516007909101555185815290917ec9f551bf78c05cb9aad786a9fb31581b9b78ab8180af56172424ccb1d014cd91016131ec565b5f805f805f600b548611156136395760405162461bcd60e51b815260206004820152601860248201527f4379636c65204964206973206f7574206f662052616e676500000000000000006044820152606401610b1a565b5050505f928352505060056020526040902080546001820154600483015460028401546003909401549294919390929091565b613674613cdb565b335f908152600260208181526040928390208351610100810185528154815260018201549281019290925291820154928101929092526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460e08201819052429081108015906136ff57506018548260e001516136fb91906141c4565b8111155b61371b5760405162461bcd60e51b8152600401610b1a9061430c565b5f831161373a5760405162461bcd60e51b8152600401610b1a90614351565b60165460ff1615155f0361379a57428260e001511061376b5760405162461bcd60e51b8152600401610b1a9061439c565b5f613778335f60016118ca565b905080156137985760405162461bcd60e51b8152600401610b1a906142d5565b505b81516137e05760405162461bcd60e51b8152602060048201526015602482015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b6044820152606401610b1a565b815183111561382a5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da0813509312c814dd185ad95960521b6044820152606401610b1a565b6040516370a0823160e01b815230600482015283907f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a526001600160a01b0316906370a0823190602401602060405180830381865afa15801561388e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138b29190614209565b10156139005760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742062616c616e6365206973206e6f7420656e6f75676800006044820152606401610b1a565b5f61390a84612794565b90505f811161392b5760405162461bcd60e51b8152600401610b1a906143ea565b825160649061393b906009614137565b61394591906141ea565b84116139935760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f74207769746864726177206c657373207468616e203130202500006044820152606401610b1a565b5f61399e82866141d7565b90506139d46001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a52163383613d34565b601654613a13906001600160a01b037f000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a5281169161010090041684613d34565b60405163079cc67960e41b81526001600160a01b037f000000000000000000000000104285168b7abe29686c56416e805f486536383716906379cc679090613a6190339089906004016142bc565b5f604051808303815f87803b158015613a78575f80fd5b505af1158015613a8a573d5f803e3d5ffd5b5050505084845f01818151613a9f91906141d7565b90525060a084018051869190613ab69083906141d7565b905250600980548691905f90613acd9084906141d7565b925050819055508460065f828254613ae591906141d7565b9091555050335f81815260026020818152604092839020885181559088015160018201558288015191810191909155606087015160038201556080870151600482015560a0870151600582015560c0870151600682015560e0870151600790910155517fef952877a2840f9e65b3398ff63ea5b7cd10c5b9300a7ee47c29359a5c07c24d90610fc59088815260200190565b613b7f613c82565b6001600160a01b038116613be45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b1a565b610fda81613e1e565b613bf5613c82565b600f819055600e55565b613c07613c82565b60165460ff1615613c4b5760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e4814185d5cd95960921b6044820152606401610b1a565b6016805460ff191660011790556040517f9ad0836c45d4ddec16a057e89fa5e103f2c9e2a92644bf8e5c0bbe0aa0b06733905f90a1565b5f546001600160a01b031633146117715760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b1a565b600260015403613d2d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b1a565b6002600155565b613d8c83846001600160a01b031663a9059cbb8585604051602401613d5a9291906142bc565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613e6d565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052613dca9186918216906323b872dd90608401613d5a565b50505050565b601354601254613de091906141c4565b6014819055426011556040519081527f09b40d736756e459b135fb3464351809a39241892fad0ebd5b0a6f77fa7fbb6d9060200160405180910390a1565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f613e816001600160a01b03841683613ece565b905080515f14158015613ea5575080806020019051810190613ea3919061442c565b155b15613d8c57604051635274afe760e01b81526001600160a01b0384166004820152602401610b1a565b6060613edb83835f613ee4565b90505b92915050565b606081471015613f095760405163cd78605960e01b8152306004820152602401610b1a565b5f80856001600160a01b03168486604051613f249190614447565b5f6040518083038185875af1925050503d805f8114613f5e576040519150601f19603f3d011682016040523d82523d5f602084013e613f63565b606091505b5091509150613f73868383613f7d565b9695505050505050565b606082613f9257613f8d82613fd9565b6118a1565b8151158015613fa957506001600160a01b0384163b155b15613fd257604051639996b31560e01b81526001600160a01b0385166004820152602401610b1a565b50806118a1565b805115613fe95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146118c5575f80fd5b5f60208284031215614028575f80fd5b613edb82614002565b5f60208284031215614041575f80fd5b5035919050565b5f8060408385031215614059575f80fd5b61406283614002565b946020939093013593505050565b5f8060408385031215614081575f80fd5b50508035926020909101359150565b8015158114610fda575f80fd5b5f602082840312156140ad575f80fd5b81356118a181614090565b5f805f606084860312156140ca575f80fd5b6140d384614002565b92506020840135915060408401356140ea81614090565b809150509250925092565b5f8060408385031215614106575f80fd5b82359150602083013561411881614090565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417613ede57613ede614123565b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b6020808252602a908201527f7570746f4379636c6549642069732067726561746564207468616e2063757272604082015269195b9d10de58db19525960b21b606082015260800190565b80820180821115613ede57613ede614123565b81810381811115613ede57613ede614123565b5f8261420457634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215614219575f80fd5b5051919050565b60208082526022908201527f6e6f7420656e6f7567682062616c616e636520696e2074686520636f6e74726160408201526118dd60f21b606082015260800190565b60208082526022908201527f4f6e6c792061646d696e732063616e2063616c6c20746869732066756e63746960408201526137b760f11b606082015260800190565b5f600182016142b5576142b5614123565b5060010190565b6001600160a01b03929092168252602082015260400190565b6020808252601e908201527f506c6561736520636c61696d2074686520726577617264732066697273740000604082015260600190565b60208082526025908201527f43616e207769746864726177206f6e6c7920696e20756e7374616b696e672070604082015264195c9a5bd960da1b606082015260800190565b6020808252602b908201527f416d6f756e7420746f2077697468647261772073686f756c642062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b6020808252602e908201527f43616e206e6f74207769746864726177206265666f7265204d696e696d756d2060408201526d29ba30b5b290223ab930ba34b7b760911b606082015260800190565b60208082526022908201527f506c6561736520616464206d6f726520416d6f756e7420746f20776974686472604082015261617760f01b606082015260800190565b5f6020828403121561443c575f80fd5b81516118a181614090565b5f82515f5b81811015614466576020818601810151858301520161444c565b505f92019182525091905056fea2646970667358221220291ffad9e947697ebb6448a69467c7197bd970ca6a99153fb06b9ac1e347723264736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a520000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de000000000000000000000000f56c9be0c43fef3b648f5b63a1274b12eeb945d6
-----Decoded View---------------
Arg [0] : mblkTokenAddress (address): 0xF47245e9A3Ba3dCa8B004E34afc1290B1d435a52
Arg [1] : lptokenAddress (address): 0x8180EB8d90023Fd91b7254eb442bf3d09d0042DE
Arg [2] : feesCollectionWalletAddress (address): 0xf56C9be0C43FEF3b648F5b63a1274b12eEB945D6
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000f47245e9a3ba3dca8b004e34afc1290b1d435a52
Arg [1] : 0000000000000000000000008180eb8d90023fd91b7254eb442bf3d09d0042de
Arg [2] : 000000000000000000000000f56c9be0c43fef3b648f5b63a1274b12eeb945d6
Deployed Bytecode Sourcemap
78839:46702:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82181:35;;;;;;;;;160:25:1;;;148:2;133:18;82181:35:0;;;;;;;;121538:91;121605:16;;121538:91;;81939:31;;;;;;79030:34;;;;;;;;-1:-1:-1;;;;;377:32:1;;;359:51;;347:2;332:18;79030:34:0;196:220:1;82023:29:0;;;;;;78983:38;;;;;82865:27;;;;;;81227:51;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1360:25:1;;;1416:2;1401:18;;1394:34;;;;1444:18;;;1437:34;;;;1502:2;1487:18;;1480:34;;;;1545:3;1530:19;;1523:35;1589:3;1574:19;;1567:35;1633:3;1618:19;;1611:35;1677:3;1662:19;;1655:35;1347:3;1332:19;81227:51:0;1017:679:1;117982:150:0;;;;;;:::i;:::-;;:::i;:::-;;81370:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83246:29;;;;;;81500:39;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1866:14:1;;1859:22;1841:41;;1829:2;1814:18;81500:39:0;1701:187:1;82549:33:0;;;;;;119247:167;;;;;;:::i;:::-;;:::i;118618:262::-;;;;;;:::i;:::-;;:::i;103110:2589::-;;;;;;:::i;:::-;;:::i;82367:34::-;;;;;;122324:600;;;;;;:::i;:::-;-1:-1:-1;;;;;122635:27:0;;122460:7;122635:27;;;:14;:27;;;;;;;;;122606:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122324:600;;;;;;;;;;2365:25:1;;;2421:2;2406:18;;2399:34;;;;2449:18;;;2442:34;;;;2507:2;2492:18;;2485:34;2550:3;2535:19;;2528:35;2594:3;2579:19;;2572:35;2352:3;2337:19;122324:600:0;2078:535:1;82276:41:0;;;;;;113344:545;;;;;;:::i;:::-;;:::i;82721:26::-;;;;;;83402:47;;83447:2;83402:47;;79073:31;;;;;99790:2600;;;;;;:::i;:::-;;:::i;115600:415::-;;;;;;:::i;:::-;;:::i;121200:167::-;;;:::i;123365:617::-;;;;;;:::i;:::-;-1:-1:-1;;;;;123683:25:0;;123500:7;123683:25;;;:12;:25;;;;;;;;;123656:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123365:617;;;;;;81739:30;;;;;;117384:132;;;;;;:::i;:::-;;:::i;49909:103::-;;;:::i;119817:318::-;;;;;;:::i;:::-;;:::i;81636:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3612:25:1;;;3668:2;3653:18;;3646:34;;;;3696:18;;;3689:34;;;;3754:2;3739:18;;3732:34;3797:3;3782:19;;3775:35;3599:3;3584:19;81636:50:0;3353:463:1;120145:192:0;;;;;;:::i;:::-;;:::i;49268:87::-;49314:7;49341:6;-1:-1:-1;;;;;49341:6:0;49268:87;;121804;121869:14;;121804:87;;81820:28;;;;;;98275:856;;;;;;:::i;:::-;;:::i;83165:35::-;;;;;;;;-1:-1:-1;;;;;83165:35:0;;;82642:42;;;;;;83315:49;;83362:2;83315:49;;82944:35;;;;;;82094:29;;;;;;94577:3381;;;;;;:::i;:::-;;:::i;112086:689::-;;;:::i;120720:303::-;;;:::i;116703:248::-;;;;;;:::i;:::-;;:::i;91060:2756::-;;;;;;:::i;:::-;;:::i;114490:562::-;;;;;;:::i;:::-;;:::i;78938:33::-;;;;;82453:36;;;;;;97966:301;;;;;;:::i;:::-;;:::i;109448:2181::-;;;;;;:::i;:::-;;:::i;86684:1376::-;;;;;;:::i;:::-;;:::i;88810:1357::-;;;;;;:::i;:::-;;:::i;124128:93::-;124201:12;;124128:93;;124940:592;;;;;;:::i;:::-;;:::i;124230:109::-;124312:19;;124230:109;;83458:30;;;;;;106515:2074;;;;;;:::i;:::-;;:::i;50167:201::-;;;;;;:::i;:::-;;:::i;82786:28::-;;;;;;116026:165;;;;;;:::i;:::-;;:::i;121031:161::-;;;:::i;117982:150::-;49154:13;:11;:13::i;:::-;-1:-1:-1;;;;;118052:21:0;::::1;118076:5;118052:21:::0;;;:7:::1;:21;::::0;;;;;;;;:29;;-1:-1:-1;;118052:29:0::1;::::0;;118098:26;;359:51:1;;;118098:26:0::1;::::0;332:18:1;118098:26:0::1;;;;;;;;117982:150:::0;:::o;119247:167::-;49154:13;:11;:13::i;:::-;119326:20:::1;:36:::0;;-1:-1:-1;;;;;;119326:36:0::1;;-1:-1:-1::0;;;;;119326:36:0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;119378:28:::1;::::0;359:51:1;;;119378:28:0::1;::::0;347:2:1;332:18;119378:28:0::1;196:220:1::0;118618:262:0;49154:13;:11;:13::i;:::-;118735:1:::1;118715:17;:21;118707:50;;;::::0;-1:-1:-1;;;118707:50:0;;5302:2:1;118707:50:0::1;::::0;::::1;5284:21:1::0;5341:2;5321:18;;;5314:30;-1:-1:-1;;;5360:18:1;;;5353:46;5416:18;;118707:50:0::1;;;;;;;;;118792:22;:17:::0;118812:2:::1;118792:22;:::i;:::-;118769:20;:45:::0;118830:42:::1;::::0;160:25:1;;;118830:42:0::1;::::0;148:2:1;133:18;118830:42:0::1;14:177:1::0;103110:2589:0;35217:21;:19;:21::i;:::-;103193:8:::1;::::0;::::1;;:17;103185:47;;;;-1:-1:-1::0;;;103185:47:0::1;;;;;;;:::i;:::-;103319:10;103243:25;103306:24:::0;;;:12:::1;:24;::::0;;;;;;;103279:51;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;103378:14:::1;::::0;103363:29;::::1;;103341:121;;;;-1:-1:-1::0;;;103341:121:0::1;;;;;;;:::i;:::-;103495:18:::0;;103473:89:::1;;;::::0;-1:-1:-1;;;103473:89:0;;6710:2:1;103473:89:0::1;::::0;::::1;6692:21:1::0;6749:2;6729:18;;;6722:30;-1:-1:-1;;;6768:18:1;;;6761:47;6825:18;;103473:89:0::1;6508:341:1::0;103473:89:0::1;103576:11;103591:1;103576:16:::0;103573:144:::1;;103628:14;;103608:34;;103573:144;;;103694:11;103674:31;;103573:144;103782:17;::::0;::::1;::::0;103752:15:::1;::::0;103782:34;-1:-1:-1;103778:1254:0::1;;;103877:14;103857:15;;103837:9;:17;;;:35;;;;:::i;:::-;103836:55:::0;103832:219:::1;;103955:20;;103931:9;:21;;;:44;;;;:::i;:::-;103911:17;::::0;::::1;:64:::0;;;103994:21:::1;::::0;::::1;:41:::0;103832:219:::1;104109:14;104090:15;;104070:9;:17;;;:35;;;;:::i;:::-;104069:54;104065:219;;;104167:17;::::0;::::1;::::0;104143:21:::1;::::0;::::1;:41:::0;;;104247:20:::1;::::0;104223:44:::1;::::0;::::1;:::i;:::-;104203:17;::::0;::::1;:64:::0;104065:219:::1;104341:14;104322:15;;104302:9;:17;;;:35;;;;:::i;:::-;104301:54;104298:723;;;104375:12;104407:9;:17;;;104390:14;:34;;;;:::i;:::-;104375:49;;104443:11;104465:20;;104458:4;:27;;;;:::i;:::-;104457:33;::::0;104489:1:::1;104457:33;:::i;:::-;104443:47;;104509:18;104553:3;104530:20;;:26;;;;:::i;:::-;104509:47;;104616:10;104596:9;:17;;;:30;;;;:::i;:::-;104576:17;::::0;::::1;:50:::0;;;104697:20:::1;::::0;104661:13:::1;::::0;104677:40:::1;::::0;104697:20;104677:40:::1;:::i;:::-;104661:56;;104794:15;;104786:5;104759:9;:24;;;:32;;;;:::i;:::-;:50;;;;:::i;:::-;104740:14;:70;104736:270;;104858:17;::::0;::::1;::::0;104834:21:::1;::::0;::::1;:41:::0;104736:270:::1;;;104966:20;;104946:9;:17;;;:40;;;;:::i;:::-;104922:21;::::0;::::1;:64:::0;104736:270:::1;104356:665;;;;104298:723;105042:15;105060:51;105076:10;105087:17;105105:5;105060:15;:51::i;:::-;105042:69;;105141:1;105131:7;:11;105122:45;;;::::0;-1:-1:-1;;;105122:45:0;;7541:2:1;105122:45:0::1;::::0;::::1;7523:21:1::0;7580:2;7560:18;;;7553:30;-1:-1:-1;;;7599:18:1;;;7592:49;7658:18;;105122:45:0::1;7339:343:1::0;105122:45:0::1;105237:15;::::0;105200:34:::1;::::0;-1:-1:-1;;;105200:34:0;;105228:4:::1;105200:34;::::0;::::1;359:51:1::0;105256:7:0;;105237:15;-1:-1:-1;;;;;105200:9:0::1;:19;::::0;::::1;::::0;332:18:1;;105200:34:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:52;;;;:::i;:::-;:63;;105178:147;;;;-1:-1:-1::0;;;105178:147:0::1;;;;;;;:::i;:::-;105348:43;-1:-1:-1::0;;;;;105348:9:0::1;:22;105371:10;105383:7:::0;105348:22:::1;:43::i;:::-;105430:7;105403:9;:23;;:34;;;;;;;:::i;:::-;::::0;;-1:-1:-1;105468:21:0::1;:17:::0;105488:1:::1;105468:21;:::i;:::-;105448:17;::::0;::::1;:41:::0;105533:15:::1;105500:30;::::0;::::1;:48:::0;105559:19:::1;:30:::0;;105582:7;;105559:19;-1:-1:-1;;105559:30:0::1;::::0;105582:7;;105559:30:::1;:::i;:::-;::::0;;;-1:-1:-1;;105613:10:0::1;105600:24;::::0;;;:12:::1;:24;::::0;;;;;;;;:36;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;105654:37;::::1;::::0;::::1;::::0;105683:7;160:25:1;;148:2;133:18;;14:177;105654:37:0::1;;;;;;;;103174:2525;;;;35261:20:::0;34655:1;35781:22;;35598:213;35261:20;103110:2589;:::o;113344:545::-;84832:10;84824:19;;;;:7;:19;;;;;;;;84816:66;;;;-1:-1:-1;;;84816:66:0;;;;;;;:::i;:::-;113533:18:::1;::::0;113470:15:::1;::::0;113445:22:::1;::::0;113516:35:::1;::::0;113470:15;113516:35:::1;:::i;:::-;113496:55;;113584:18;;113571:9;:31;;113563:75;;;::::0;-1:-1:-1;;;113563:75:0;;8884:2:1;113563:75:0::1;::::0;::::1;8866:21:1::0;8923:2;8903:18;;;8896:30;8962:33;8942:18;;;8935:61;9013:18;;113563:75:0::1;8682:355:1::0;113563:75:0::1;113649:71;-1:-1:-1::0;;;;;113649:9:0::1;:26;113676:14:::0;113699:4:::1;113705:14:::0;113649:26:::1;:71::i;:::-;113731:18;:35:::0;;;113777:11:::1;:28:::0;;;113816:17:::1;:15;:17::i;:::-;113851:30;::::0;160:25:1;;;113851:30:0::1;::::0;148:2:1;133:18;113851:30:0::1;;;;;;;;113434:455;;113344:545:::0;;:::o;99790:2600::-;35217:21;:19;:21::i;:::-;99875:8:::1;::::0;::::1;;:17;99867:47;;;;-1:-1:-1::0;;;99867:47:0::1;;;;;;;:::i;:::-;100005:10;99925:25;99990:26:::0;;;:14:::1;:26;::::0;;;;;;;99961:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;100064:14:::1;::::0;100049:29;::::1;;100027:121;;;;-1:-1:-1::0;;;100027:121:0::1;;;;;;;:::i;:::-;100181:20:::0;;100159:100:::1;;;::::0;-1:-1:-1;;;100159:100:0;;9244:2:1;100159:100:0::1;::::0;::::1;9226:21:1::0;9283:2;9263:18;;;9256:30;9322:28;9302:18;;;9295:56;9368:18;;100159:100:0::1;9042:350:1::0;100159:100:0::1;100274:11;100289:1;100274:16:::0;100270:145:::1;;100326:14;;100306:34;;100270:145;;;100392:11;100372:31;;100270:145;100482:17;::::0;::::1;::::0;100450:15:::1;::::0;100482:34;-1:-1:-1;100478:1254:0::1;;;100577:14;100557:15;;100537:9;:17;;;:35;;;;:::i;:::-;100536:55:::0;100532:219:::1;;100655:20;;100631:9;:21;;;:44;;;;:::i;:::-;100611:17;::::0;::::1;:64:::0;;;100694:21:::1;::::0;::::1;:41:::0;100532:219:::1;100809:14;100790:15;;100770:9;:17;;;:35;;;;:::i;:::-;100769:54;100765:219;;;100867:17;::::0;::::1;::::0;100843:21:::1;::::0;::::1;:41:::0;;;100947:20:::1;::::0;100923:44:::1;::::0;::::1;:::i;:::-;100903:17;::::0;::::1;:64:::0;100765:219:::1;101041:14;101022:15;;101002:9;:17;;;:35;;;;:::i;:::-;101001:54;100998:723;;;101075:12;101107:9;:17;;;101090:14;:34;;;;:::i;:::-;101075:49;;101143:11;101165:20;;101158:4;:27;;;;:::i;:::-;101157:33;::::0;101189:1:::1;101157:33;:::i;:::-;101143:47;;101209:18;101253:3;101230:20;;:26;;;;:::i;:::-;101209:47;;101316:10;101296:9;:17;;;:30;;;;:::i;:::-;101276:17;::::0;::::1;:50:::0;;;101397:20:::1;::::0;101361:13:::1;::::0;101377:40:::1;::::0;101397:20;101377:40:::1;:::i;:::-;101361:56;;101494:15;;101486:5;101459:9;:24;;;:32;;;;:::i;:::-;:50;;;;:::i;:::-;101440:14;:70;101436:270;;101558:17;::::0;::::1;::::0;101534:21:::1;::::0;::::1;:41:::0;101436:270:::1;;;101666:20;;101646:9;:17;;;:40;;;;:::i;:::-;101622:21;::::0;::::1;:64:::0;101436:270:::1;101056:665;;;;100998:723;101742:15;101760:44;101776:10;101787:11;101799:4;101760:15;:44::i;:::-;101742:62;;101834:1;101824:7;:11;101815:44;;;::::0;-1:-1:-1;;;101815:44:0;;7541:2:1;101815:44:0::1;::::0;::::1;7523:21:1::0;7580:2;7560:18;;;7553:30;-1:-1:-1;;;7599:18:1;;;7592:49;7658:18;;101815:44:0::1;7339:343:1::0;101815:44:0::1;101930:15;::::0;101892:34:::1;::::0;-1:-1:-1;;;101892:34:0;;101920:4:::1;101892:34;::::0;::::1;359:51:1::0;101950:7:0;;101930:15;-1:-1:-1;;;;;101892:9:0::1;:19;::::0;::::1;::::0;332:18:1;;101892:34:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;;:::i;:::-;:65;;101870:149;;;;-1:-1:-1::0;;;101870:149:0::1;;;;;;;:::i;:::-;102036:43;-1:-1:-1::0;;;;;102036:9:0::1;:22;102059:10;102071:7:::0;102036:22:::1;:43::i;:::-;102091:30;::::0;::::1;:47:::0;;;102149:23:::1;::::0;::::1;:34:::0;;102176:7;;102149:23;:34:::1;::::0;102176:7;;102149:34:::1;:::i;:::-;::::0;;-1:-1:-1;102214:21:0::1;:17:::0;102234:1:::1;102214:21;:::i;:::-;102194:17;::::0;::::1;:41:::0;102246:19:::1;:30:::0;;102269:7;;102246:19;::::1;::::0;:30:::1;::::0;102269:7;;102246:30:::1;:::i;:::-;::::0;;;-1:-1:-1;;102302:10:0::1;102287:26;::::0;;;:14:::1;:26;::::0;;;;;;;;:38;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;102343:39;::::1;::::0;::::1;::::0;102374:7;160:25:1;;148:2;133:18;;14:177;115600:415:0;84832:10;84824:19;;;;:7;:19;;;;;;;;84816:66;;;;-1:-1:-1;;;84816:66:0;;;;;;;:::i;:::-;115722:1:::1;115705:14;:18;115697:58;;;::::0;-1:-1:-1;;;115697:58:0;;9599:2:1;115697:58:0::1;::::0;::::1;9581:21:1::0;9638:2;9618:18;;;9611:30;9677:28;9657:18;;;9650:56;9723:18;;115697:58:0::1;9397:350:1::0;115697:58:0::1;115793:1;115774:16;:20;115766:62;;;::::0;-1:-1:-1;;;115766:62:0;;9954:2:1;115766:62:0::1;::::0;::::1;9936:21:1::0;9993:2;9973:18;;;9966:30;10032;10012:18;;;10005:58;10080:18;;115766:62:0::1;9752:352:1::0;115766:62:0::1;115839:11;:28:::0;;;115878:13:::1;:32:::0;;;115936:27:::1;115894:16:::0;115853:14;115936:27:::1;:::i;:::-;115921:12;:42:::0;;;115979:28:::1;::::0;160:25:1;;;115979:28:0::1;::::0;148:2:1;133:18;115979:28:0::1;;;;;;;;115600:415:::0;;:::o;121200:167::-;49154:13;:11;:13::i;:::-;121263:8:::1;::::0;::::1;;:16;;:8:::0;:16:::1;121254:45;;;::::0;-1:-1:-1;;;121254:45:0;;10311:2:1;121254:45:0::1;::::0;::::1;10293:21:1::0;10350:2;10330:18;;;10323:30;-1:-1:-1;;;10369:18:1;;;10362:46;10425:18;;121254:45:0::1;10109:340:1::0;121254:45:0::1;121310:8;:16:::0;;-1:-1:-1;;121310:16:0::1;::::0;;121342:17:::1;::::0;::::1;::::0;121321:5:::1;::::0;121342:17:::1;121200:167::o:0;117384:132::-;49154:13;:11;:13::i;:::-;-1:-1:-1;;;;;117448:17:0;::::1;;::::0;;;:7:::1;:17;::::0;;;;;;;;:24;;-1:-1:-1;;117448:24:0::1;117468:4;117448:24;::::0;;117488:20;;359:51:1;;;117488:20:0::1;::::0;332:18:1;117488:20:0::1;196:220:1::0;49909:103:0;49154:13;:11;:13::i;:::-;49974:30:::1;50001:1;49974:18;:30::i;:::-;49909:103::o:0;119817:318::-;49154:13;:11;:13::i;:::-;119940:1:::1;119920:17;:21;119912:76;;;::::0;-1:-1:-1;;;119912:76:0;;10656:2:1;119912:76:0::1;::::0;::::1;10638:21:1::0;10695:2;10675:18;;;10668:30;10734:34;10714:18;;;10707:62;-1:-1:-1;;;10785:18:1;;;10778:40;10835:19;;119912:76:0::1;10454:406:1::0;119912:76:0::1;120032:22;:17:::0;120052:2:::1;120032:22;:::i;:::-;120003:26;:51:::0;;;120070:57:::1;::::0;160:25:1;;;120070:57:0::1;::::0;148:2:1;133:18;120070:57:0::1;14:177:1::0;120145:192:0;49154:13;:11;:13::i;:::-;120255:1:::1;120235:17;:21;120227:44;;;::::0;-1:-1:-1;;;120227:44:0;;11067:2:1;120227:44:0::1;::::0;::::1;11049:21:1::0;11106:2;11086:18;;;11079:30;-1:-1:-1;;;11125:18:1;;;11118:41;11176:18;;120227:44:0::1;10865:335:1::0;120227:44:0::1;120300:22;:17:::0;120320:2:::1;120300:22;:::i;:::-;120282:15;:40:::0;-1:-1:-1;120145:192:0:o;98275:856::-;98347:7;98369:6;98366:441;;;98507:10;98455:33;98492:26;;;:14;:26;;;;;:37;98537:3;;98492:42;;98532:2;98492:42;:::i;:::-;98491:49;;;;:::i;:::-;98455:85;98275:856;-1:-1:-1;;;98275:856:0:o;98366:441::-;98723:10;98674:32;98710:24;;;:12;:24;;;;;:33;98750:3;;98710:38;;98746:2;98710:38;:::i;98366:441::-;98275:856;;;:::o;94577:3381::-;94704:8;;94676:7;;94704:8;;:17;94696:47;;;;-1:-1:-1;;;94696:47:0;;;;;;;:::i;:::-;94791:14;;94776:11;:29;;94754:106;;;;-1:-1:-1;;;94754:106:0;;11407:2:1;94754:106:0;;;11389:21:1;11446:2;11426:18;;;11419:30;11485:29;11465:18;;;11458:57;11532:18;;94754:106:0;11205:351:1;94754:106:0;95021:30;95080:6;95021:30;95191:16;;;95187:142;;-1:-1:-1;95242:14:0;;95187:142;;;-1:-1:-1;95306:11:0;95187:142;95344:6;95341:2610;;;-1:-1:-1;;;;;95395:27:0;;95366:26;95395:27;;;:14;:27;;;;;;;;;95366:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95437:101;;;;-1:-1:-1;;;95437:101:0;;11763:2:1;95437:101:0;;;11745:21:1;11802:2;11782:18;;;11775:30;-1:-1:-1;;;11821:18:1;;;11814:45;11876:18;;95437:101:0;11561:339:1;95437:101:0;95753:17;;;;95737:792;95777:16;95772:1;:21;95737:792;;95825:14;;;;:11;:14;;;;;:30;;;95822:53;95864:8;95822:53;95897:32;95932:14;;;:11;:14;;;;;:26;;;;96020:30;;;;;96104:20;;95932:26;;96020:30;;;;96133:7;;96104:26;;96127:3;96104:26;:::i;:::-;:36;;;;:::i;:::-;96103:69;;;;:::i;:::-;96073:99;-1:-1:-1;96195:17:0;83362:2;96264:7;96215:46;96237:24;96073:99;96215:46;:::i;:::-;:56;;;;:::i;:::-;:79;;;;:::i;:::-;96195:99;-1:-1:-1;96317:19:0;96357:7;96339:15;96357:7;96349:5;96339:15;:::i;:::-;:25;;;;:::i;:::-;96317:47;-1:-1:-1;96388:28:0;96419:21;96317:47;96419:9;:21;:::i;:::-;96388:52;-1:-1:-1;96463:46:0;96388:52;96463:46;;:::i;:::-;;;95799:730;;;;;;95737:792;95795:3;;;;:::i;:::-;;;;95737:792;;;;96554:22;96547:29;;;;;;;;95341:2610;-1:-1:-1;;;;;96709:25:0;;96682:24;96709:25;;;:12;:25;;;;;;;;;96682:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96749:99;;;;-1:-1:-1;;;96749:99:0;;11763:2:1;96749:99:0;;;11745:21:1;11802:2;11782:18;;;11775:30;-1:-1:-1;;;11821:18:1;;;11814:45;11876:18;;96749:99:0;11561:339:1;96749:99:0;97061:17;;;;97045:780;97085:16;97080:1;:21;97045:780;;97133:14;;;;:11;:14;;;;;:28;;;97130:52;97171:8;97130:52;97204:32;97239:14;;;:11;:14;;;;;:26;;;;97325:28;;;;;97406:18;;97239:26;;97325:28;;;;97433:7;;97406:24;;97427:3;97406:24;:::i;:::-;:34;;;;:::i;:::-;97404:67;;;;:::i;:::-;97376:95;-1:-1:-1;97494:17:0;83447:2;97561:7;97514:44;97534:24;97376:95;97514:44;:::i;:::-;:54;;;;:::i;:::-;:75;;;;:::i;:::-;97494:95;-1:-1:-1;97612:19:0;97652:7;97634:15;97652:7;97644:5;97634:15;:::i;:::-;:25;;;;:::i;:::-;97612:47;-1:-1:-1;97684:28:0;97715:21;97612:47;97715:9;:21;:::i;:::-;97684:52;-1:-1:-1;97759:46:0;97684:52;97759:46;;:::i;:::-;;;97107:718;;;;;;97045:780;97103:3;;;;:::i;:::-;;;;97045:780;;112086:689;84832:10;84824:19;;;;:7;:19;;;;;;;;84816:66;;;;-1:-1:-1;;;84816:66:0;;;;;;;:::i;:::-;112202:14:::1;:16:::0;;;:14:::1;:16;::::0;::::1;:::i;:::-;::::0;;;-1:-1:-1;;112330:14:0::1;::::0;;112229:22:::1;112318:27:::0;;;:11:::1;:27;::::0;;;;;;;112280:65;;::::1;::::0;::::1;::::0;;112356:42;;;112254:15:::1;112280:65:::0;;::::1;112409:48:::0;;;112499:12:::1;::::0;112280:65;;;112468:43;;;112555:13:::1;::::0;112280:65;;;112522:46;;;112614:15:::1;::::0;112280:65;;;112579:50;;;112640:27;;;;;;;:46;;;;;112280:65:::1;::::0;::::1;112640:46:::0;;;112280:65:::1;::::0;::::1;112640:46:::0;;;112280:65:::1;::::0;::::1;112640:46:::0;;;112280:65:::1;::::0;;::::1;112640:46:::0;;;;112752:14;;112737:30;;160:25:1;;;112254:15:0;112280:65;;112737:30:::1;::::0;133:18:1;112737:30:0::1;14:177:1::0;120720:303:0;49154:13;:11;:13::i;:::-;120853:15:::1;::::0;120816:34:::1;::::0;-1:-1:-1;;;120816:34:0;;120844:4:::1;120816:34;::::0;::::1;359:51:1::0;120776:37:0::1;::::0;120853:15;-1:-1:-1;;;;;120816:9:0::1;:19;::::0;::::1;::::0;332:18:1;;120816:34:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:52;;;;:::i;:::-;120776:92:::0;-1:-1:-1;120879:65:0::1;-1:-1:-1::0;;;;;120879:9:0::1;:22;120902:10;120776:92:::0;120879:22:::1;:65::i;:::-;120960:55;120973:10;120984:29;120960:55;;;;;;;:::i;116703:248::-:0;49154:13;:11;:13::i;:::-;116800:1:::1;116787:10;:14;:36;;;;;116819:4;116805:10;:18;;116787:36;116779:81;;;::::0;-1:-1:-1;;;116779:81:0;;12526:2:1;116779:81:0::1;::::0;::::1;12508:21:1::0;;;12545:18;;;12538:30;12604:34;12584:18;;;12577:62;12656:18;;116779:81:0::1;12324:356:1::0;116779:81:0::1;116871:14;:27:::0;;;116914:29:::1;::::0;160:25:1;;;116914:29:0::1;::::0;148:2:1;133:18;116914:29:0::1;14:177:1::0;91060:2756:0;91136:8;;;;:17;91128:47;;;;-1:-1:-1;;;91128:47:0;;;;;;;:::i;:::-;91203:1;91194:6;:10;91186:52;;;;-1:-1:-1;;;91186:52:0;;12887:2:1;91186:52:0;;;12869:21:1;12926:2;12906:18;;;12899:30;12965:31;12945:18;;;12938:59;13014:18;;91186:52:0;12685:353:1;91186:52:0;91252:6;91249:2560;;;91300:31;;-1:-1:-1;;;91300:31:0;;91320:10;91300:31;;;359:51:1;91334:6:0;;91300:9;-1:-1:-1;;;;;91300:19:0;;;;332:18:1;;91300:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;91274:120;;;;-1:-1:-1;;;91274:120:0;;13245:2:1;91274:120:0;;;13227:21:1;13284:2;13264:18;;;13257:30;-1:-1:-1;;;13303:18:1;;;13296:48;13361:18;;91274:120:0;13043:342:1;91274:120:0;91453:10;91409:26;91438;;;:14;:26;;;;;;;;91409:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91511:34;;91409:26;;91511:15;:34::i;:::-;91483:62;-1:-1:-1;91568:22:0;;91560:65;;;;-1:-1:-1;;;91560:65:0;;;;;;;:::i;:::-;91648:20;;91640:67;;;;-1:-1:-1;;;91640:67:0;;13951:2:1;91640:67:0;;;13933:21:1;13990:2;13970:18;;;13963:30;14029:33;14009:18;;;14002:61;14080:18;;91640:67:0;13749:355:1;91640:67:0;91722:61;-1:-1:-1;;;;;91722:9:0;:26;91749:10;91769:4;91776:6;91722:26;:61::i;:::-;91817:6;91798:15;;:25;;;;;;;:::i;:::-;;;;-1:-1:-1;;91838:30:0;;91862:6;;91838:9;;:30;;91862:6;;91838:30;:::i;:::-;;;-1:-1:-1;91908:15:0;91939:24;;;:41;;;92032:20;;92015:37;;91908:15;92015:37;:::i;:::-;91995:17;;;:57;92108:20;;92091:37;;:14;:37;:::i;:::-;92067:21;;;:61;92143:35;;-1:-1:-1;;;92143:35:0;;-1:-1:-1;;;;;92143:10:0;:15;;;;:35;;92159:10;;92171:6;;92143:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92216:6;92196:16;;:26;;;;;;;:::i;:::-;;;;;;;;92361:6;92336:9;:21;;:31;;;;;;;:::i;:::-;;;-1:-1:-1;92402:14:0;;:18;;92419:1;92402:18;:::i;:::-;92382:17;;;:38;;;92451:10;92436:26;;;;:14;:26;;;;;;;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92494:35;;;;;;92522:6;;92494:35;:::i;:::-;;;;;;;;91259:1285;;;91060:2756;;:::o;91249:2560::-;92591:29;;-1:-1:-1;;;92591:29:0;;92609:10;92591:29;;;359:51:1;92623:6:0;;92591:7;-1:-1:-1;;;;;92591:17:0;;;;332:18:1;;92591:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;;92565:118;;;;-1:-1:-1;;;92565:118:0;;13245:2:1;92565:118:0;;;13227:21:1;13284:2;13264:18;;;13257:30;-1:-1:-1;;;13303:18:1;;;13296:48;13361:18;;92565:118:0;13043:342:1;92565:118:0;92738:10;92698:24;92725;;;:12;:24;;;;;;;;92698:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92792:35;;92698:24;;92792:15;:35::i;:::-;92764:63;-1:-1:-1;92850:22:0;;92842:65;;;;-1:-1:-1;;;92842:65:0;;;;;;;:::i;:::-;92930:18;;92922:66;;;;-1:-1:-1;;;92922:66:0;;13951:2:1;92922:66:0;;;13933:21:1;13990:2;13970:18;;;13963:30;14029:33;14009:18;;;14002:61;14080:18;;92922:66:0;13749:355:1;92922:66:0;93003:58;-1:-1:-1;;;;;93003:7:0;:24;93028:10;93047:4;93054:6;93003:24;:58::i;:::-;93095:6;93078:13;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;;93116:28:0;;93138:6;;93116:9;;:28;;93138:6;;93116:28;:::i;:::-;;;-1:-1:-1;93184:15:0;93215:24;;;:41;;;93308:20;;93291:37;;93184:15;93291:37;:::i;:::-;93271:17;;;:57;93384:20;;93367:37;;:14;:37;:::i;:::-;93343:21;;;:61;93520:33;;-1:-1:-1;;;93520:33:0;;-1:-1:-1;;;;;93520:8:0;:13;;;;:33;;93534:10;;93546:6;;93520:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93588:6;93570:14;;:24;;;;;;;:::i;:::-;;;;;;;;93632:6;93609:9;:19;;:29;;;;;;;:::i;:::-;;;-1:-1:-1;93673:14:0;;:18;;93690:1;93673:18;:::i;:::-;93653:17;;;:38;;;93719:10;93706:24;;;;:12;:24;;;;;;;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93764:33;;;;;;93790:6;;93764:33;:::i;114490:562::-;84832:10;84824:19;;;;:7;:19;;;;;;;;84816:66;;;;-1:-1:-1;;;84816:66:0;;;;;;;:::i;:::-;114683:20:::1;::::0;114620:15:::1;::::0;114595:22:::1;::::0;114666:37:::1;::::0;114620:15;114666:37:::1;:::i;:::-;114646:57;;114735:20;;114722:9;:33;;114714:76;;;::::0;-1:-1:-1;;;114714:76:0;;14311:2:1;114714:76:0::1;::::0;::::1;14293:21:1::0;14350:2;14330:18;;;14323:30;14389:33;14369:18;;;14362:61;14440:18;;114714:76:0::1;14109:355:1::0;114714:76:0::1;114801:73;-1:-1:-1::0;;;;;114801:9:0::1;:26;114828:14:::0;114851:4:::1;114857:16:::0;114801:26:::1;:73::i;:::-;114885:20;:37:::0;;;114933:13:::1;:32:::0;;;114977:17:::1;:15;:17::i;:::-;115010:34;::::0;160:25:1;;;115010:34:0::1;::::0;148:2:1;133:18;115010:34:0::1;14:177:1::0;97966:301:0;98023:7;98046:6;98056:1;98046:11;98043:25;;-1:-1:-1;98067:1:0;;97966:301;-1:-1:-1;97966:301:0:o;98043:25::-;98079:17;98110:14;;98101:6;:23;;;;:::i;:::-;:30;;98127:4;98101:30;:::i;:::-;98079:53;-1:-1:-1;98167:12:0;98143:19;98211:21;98167:12;98079:53;98211:21;:::i;:::-;98191:41;97966:301;-1:-1:-1;;;;;97966:301:0:o;109448:2181::-;35217:21;:19;:21::i;:::-;109567:10:::1;109527:24;109554::::0;;;:12:::1;:24;::::0;;;;;;;;109527:51;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;109614:15:::1;::::0;109650:39;::::1;::::0;::::1;::::0;:102:::1;;;109736:15;;109712:9;:21;;;:39;;;;:::i;:::-;109693:14;:59;;109650:102;109642:151;;;;-1:-1:-1::0;;;109642:151:0::1;;;;;;;:::i;:::-;109831:1;109812:16;:20;109804:75;;;;-1:-1:-1::0;;;109804:75:0::1;;;;;;;:::i;:::-;109894:8;::::0;::::1;;:17;;:8;:17:::0;109890:388:::1;;109989:15;109965:9;:21;;;:39;109931:167;;;;-1:-1:-1::0;;;109931:167:0::1;;;;;;;:::i;:::-;110117:25;110145:35;110161:10;110172:1;110174:5:::0;110145:15:::1;:35::i;:::-;110117:63:::0;-1:-1:-1;110210:22:0;;110202:64:::1;;;;-1:-1:-1::0;;;110202:64:0::1;;;;;;;:::i;:::-;109912:366;109890:388;110297:18:::0;;110289:55:::1;;;::::0;-1:-1:-1;;;110289:55:0;;15904:2:1;110289:55:0::1;::::0;::::1;15886:21:1::0;15943:2;15923:18;;;15916:30;-1:-1:-1;;;15962:18:1;;;15955:51;16023:18;;110289:55:0::1;15702:345:1::0;110289:55:0::1;110363:18:::0;;:38;-1:-1:-1;110363:38:0::1;110355:70;;;::::0;-1:-1:-1;;;110355:70:0;;16254:2:1;110355:70:0::1;::::0;::::1;16236:21:1::0;16293:2;16273:18;;;16266:30;-1:-1:-1;;;16312:18:1;;;16305:50;16372:18;;110355:70:0::1;16052:344:1::0;110355:70:0::1;110458:18:::0;;:38;-1:-1:-1;110458:38:0::1;110436:119;;;::::0;-1:-1:-1;;;110436:119:0;;16603:2:1;110436:119:0::1;::::0;::::1;16585:21:1::0;16642:2;16622:18;;;16615:30;16681:32;16661:18;;;16654:60;16731:18;;110436:119:0::1;16401:354:1::0;110436:119:0::1;110588:30;::::0;-1:-1:-1;;;110588:30:0;;110607:10:::1;110588:30;::::0;::::1;359:51:1::0;110622:16:0;;110588:8:::1;-1:-1:-1::0;;;;;110588:18:0::1;::::0;::::1;::::0;332::1;;110588:30:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;110566:132;;;::::0;-1:-1:-1;;;110566:132:0;;16962:2:1;110566:132:0::1;::::0;::::1;16944:21:1::0;;;16981:18;;;16974:30;17040:34;17020:18;;;17013:62;17092:18;;110566:132:0::1;16760:356:1::0;110566:132:0::1;110731:32;::::0;-1:-1:-1;;;110731:32:0;;110757:4:::1;110731:32;::::0;::::1;359:51:1::0;110767:16:0;;110731:7:::1;-1:-1:-1::0;;;;;110731:17:0::1;::::0;::::1;::::0;332:18:1;;110731:32:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:52;;110709:132;;;::::0;-1:-1:-1;;;110709:132:0;;17323:2:1;110709:132:0::1;::::0;::::1;17305:21:1::0;17362:2;17342:18;;;17335:30;17401:32;17381:18;;;17374:60;17451:18;;110709:132:0::1;17121:354:1::0;110709:132:0::1;110854:46;::::0;-1:-1:-1;;;110854:46:0;;-1:-1:-1;;;;;110854:8:0::1;:17;::::0;::::1;::::0;:46:::1;::::0;110872:10:::1;::::0;110883:16;;110854:46:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;110913:17;110933:29;110945:16;110933:11;:29::i;:::-;110913:49;;110993:1;110981:9;:13;110973:60;;;;-1:-1:-1::0;;;110973:60:0::1;;;;;;;:::i;:::-;111073:18:::0;;111099:3:::1;::::0;111073:22:::1;::::0;111094:1:::1;111073:22;:::i;:::-;111072:30;;;;:::i;:::-;111052:16;:51;111044:93;;;::::0;-1:-1:-1;;;111044:93:0;;18085:2:1;111044:93:0::1;::::0;::::1;18067:21:1::0;18124:2;18104:18;;;18097:30;18163:32;18143:18;;;18136:60;18213:18;;111044:93:0::1;17883:354:1::0;111044:93:0::1;111148:20;111171:28;111190:9:::0;111171:16;:28:::1;:::i;:::-;111148:51:::0;-1:-1:-1;111220:46:0::1;-1:-1:-1::0;;;;;111220:7:0::1;:20;111241:10;111148:51:::0;111220:20:::1;:46::i;:::-;111298:20;::::0;111277:52:::1;::::0;-1:-1:-1;;;;;111277:7:0::1;:20:::0;::::1;::::0;111298::::1;::::0;::::1;;111319:9:::0;111277:20:::1;:52::i;:::-;111362:16;111340:9;:18;;:38;;;;;;;:::i;:::-;::::0;;-1:-1:-1;111389:13:0::1;:33:::0;;111406:16;;111389:13;::::1;::::0;:33:::1;::::0;111406:16;;111389:33:::1;:::i;:::-;;;;;;;;111451:16;111433:14;;:34;;;;;;;:::i;:::-;;;;;;;;111501:16;111478:9;:19;;:39;;;;;;;:::i;:::-;::::0;;-1:-1:-1;111541:10:0::1;111528:24;::::0;;;:12:::1;:24;::::0;;;;;;;;:36;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;111580:41;::::1;::::0;::::1;::::0;111604:16;160:25:1;;148:2;133:18;;14:177;86684:1376:0;35217:21;:19;:21::i;:::-;86764:8:::1;::::0;::::1;;:17;86756:47;;;;-1:-1:-1::0;;;86756:47:0::1;;;;;;;:::i;:::-;86835:1;86822:10;:14;86814:56;;;::::0;-1:-1:-1;;;86814:56:0;;12887:2:1;86814:56:0::1;::::0;::::1;12869:21:1::0;12926:2;12906:18;;;12899:30;12965:31;12945:18;;;12938:59;13014:18;;86814:56:0::1;12685:353:1::0;86814:56:0::1;86903:31;::::0;-1:-1:-1;;;86903:31:0;;86923:10:::1;86903:31;::::0;::::1;359:51:1::0;86938:10:0;;86903:9:::1;-1:-1:-1::0;;;;;86903:19:0::1;::::0;::::1;::::0;332:18:1;;86903:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;86881:113;;;::::0;-1:-1:-1;;;86881:113:0;;18444:2:1;86881:113:0::1;::::0;::::1;18426:21:1::0;18483:2;18463:18;;;18456:30;-1:-1:-1;;;18502:18:1;;;18495:48;18560:18;;86881:113:0::1;18242:342:1::0;86881:113:0::1;87042:10;87027:26;::::0;;;:14:::1;:26;::::0;;;;:37;:42;87005:119:::1;;;::::0;-1:-1:-1;;;87005:119:0;;18791:2:1;87005:119:0::1;::::0;::::1;18773:21:1::0;18830:2;18810:18;;;18803:30;18869:29;18849:18;;;18842:57;18916:18;;87005:119:0::1;18589:351:1::0;87005:119:0::1;87180:10;87136:26;87165::::0;;;:14:::1;:26;::::0;;;;;;;;87136:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;::::1;::::0;;;;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;;::::0;;;;;;87208:65:::1;::::0;:9:::1;-1:-1:-1::0;;;;;87208:26:0::1;::::0;87255:4:::1;87262:10:::0;87208:26:::1;:65::i;:::-;87284:22;87309:15;87284:40;;87357:10;87338:15;;:29;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;87378:33:0;;;87422:24:::1;::::0;::::1;:41:::0;;;87511:20:::1;::::0;87494:37:::1;::::0;87449:14;87494:37:::1;:::i;:::-;87474:17;::::0;::::1;:57:::0;87593:20:::1;::::0;87576:37:::1;::::0;:14;:37:::1;:::i;:::-;87552:21;::::0;::::1;:61:::0;87721:30:::1;::::0;::::1;:47:::0;;;87779:38:::1;::::0;-1:-1:-1;;;87779:38:0;;-1:-1:-1;;;;;87779:10:0::1;:15;::::0;::::1;::::0;:38:::1;::::0;87795:10:::1;::::0;87806;;87779:38:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;87850:10;87830:16;;:30;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;87891:14:0::1;::::0;:18:::1;::::0;87908:1:::1;87891:18;:::i;:::-;87871:17;::::0;::::1;:38:::0;87920:21:::1;::::0;::::1;:35:::0;;87945:10;;87920:21;:35:::1;::::0;87945:10;;87920:35:::1;:::i;:::-;::::0;;-1:-1:-1;87981:10:0::1;87966:26;::::0;;;:14:::1;:26;::::0;;;;;;;;:38;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;88020:32;::::1;::::0;::::1;::::0;88041:10;160:25:1;;148:2;133:18;;14:177;88020:32:0::1;;;;;;;;86745:1315;;35261:20:::0;34655:1;35781:22;;35598:213;88810:1357;35217:21;:19;:21::i;:::-;88886:8:::1;::::0;::::1;;:17;88878:47;;;;-1:-1:-1::0;;;88878:47:0::1;;;;;;;:::i;:::-;88955:1;88944:8;:12;88936:56;;;::::0;-1:-1:-1;;;88936:56:0;;19147:2:1;88936:56:0::1;::::0;::::1;19129:21:1::0;19186:2;19166:18;;;19159:30;19225:32;19205:18;;;19198:60;19275:18;;88936:56:0::1;18945:354:1::0;88936:56:0::1;89025:29;::::0;-1:-1:-1;;;89025:29:0;;89043:10:::1;89025:29;::::0;::::1;359:51:1::0;89058:8:0;;89025:7:::1;-1:-1:-1::0;;;;;89025:17:0::1;::::0;::::1;::::0;332:18:1;;89025:29:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;89003:109;;;::::0;-1:-1:-1;;;89003:109:0;;18444:2:1;89003:109:0::1;::::0;::::1;18426:21:1::0;18483:2;18463:18;;;18456:30;-1:-1:-1;;;18502:18:1;;;18495:48;18560:18;;89003:109:0::1;18242:342:1::0;89003:109:0::1;89158:10;89145:24;::::0;;;:12:::1;:24;::::0;;;;:33;:38;89123:111:::1;;;::::0;-1:-1:-1;;;89123:111:0;;19506:2:1;89123:111:0::1;::::0;::::1;19488:21:1::0;19545:2;19525:18;;;19518:30;19584:25;19564:18;;;19557:53;19627:18;;89123:111:0::1;19304:347:1::0;89123:111:0::1;89285:10;89245:24;89272::::0;;;:12:::1;:24;::::0;;;;;;;;89245:51;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;89307:60:::1;::::0;:7:::1;-1:-1:-1::0;;;;;89307:24:0::1;::::0;89351:4:::1;89358:8:::0;89307:24:::1;:60::i;:::-;89395:8;89378:13;;:25;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;89465:30:0;;89439:15:::1;::::0;89487:8;;89465:9;;:30:::1;::::0;89487:8;;89465:30:::1;:::i;:::-;::::0;;-1:-1:-1;89506:24:0::1;::::0;::::1;:41:::0;;;89595:20:::1;::::0;89578:37:::1;::::0;89533:14;89578:37:::1;:::i;:::-;89558:17;::::0;::::1;:57:::0;89667:20:::1;::::0;89650:37:::1;::::0;:14;:37:::1;:::i;:::-;89626:21;::::0;::::1;:61:::0;89795:30:::1;::::0;::::1;:47:::0;;;89853:34:::1;::::0;-1:-1:-1;;;89853:34:0;;-1:-1:-1;;;;;89853:8:0::1;:13;::::0;::::1;::::0;:34:::1;::::0;89867:10:::1;::::0;89878:8;;89853:34:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;89966:8;89948:14;;:26;;;;;;;:::i;:::-;;;;;;;;90008:8;89985:9;:19;;:31;;;;;;;:::i;:::-;::::0;;-1:-1:-1;90047:14:0::1;::::0;:18:::1;::::0;90064:1:::1;90047:18;:::i;:::-;90027:17;::::0;::::1;:38:::0;;;90090:10:::1;90077:24;::::0;;;:12:::1;:24;::::0;;;;;;;;:36;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;90129:29;160:25:1;;;90090:10:0;;90129:29:::1;::::0;133:18:1;90129:29:0::1;14:177:1::0;124940:592:0;125062:7;125084;125106;125128;125150;125206:14;;125194:8;:26;;125186:63;;;;-1:-1:-1;;;125186:63:0;;19858:2:1;125186:63:0;;;19840:21:1;19897:2;19877:18;;;19870:30;19936:26;19916:18;;;19909:54;19980:18;;125186:63:0;19656:348:1;125186:63:0;-1:-1:-1;;;125281:21:0;;;;-1:-1:-1;;125281:11:0;:21;;;;;:29;;125325:36;;;;125376:37;;;;125428:33;;;;125477:35;;;;;125281:29;;125325:36;;125376:37;;125428:33;;124940:592::o;106515:2074::-;35217:21;:19;:21::i;:::-;106640:10:::1;106596:26;106625::::0;;;:14:::1;:26;::::0;;;;;;;;106596:55;;::::1;::::0;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;::::1;::::0;;;;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;::::1;;::::0;;;;;;;106687:15:::1;::::0;106720:39;::::1;::::0;::::1;::::0;:102:::1;;;106806:15;;106782:9;:21;;;:39;;;;:::i;:::-;106763:14;:59;;106720:102;106712:151;;;;-1:-1:-1::0;;;106712:151:0::1;;;;;;;:::i;:::-;106901:1;106882:16;:20;106874:75;;;;-1:-1:-1::0;;;106874:75:0::1;;;;;;;:::i;:::-;106964:8;::::0;::::1;;:17;;:8;:17:::0;106960:387:::1;;107059:15;107035:9;:21;;;:39;107001:167;;;;-1:-1:-1::0;;;107001:167:0::1;;;;;;;:::i;:::-;107187:25;107215:34;107231:10;107242:1;107244:4;107215:15;:34::i;:::-;107187:62:::0;-1:-1:-1;107279:22:0;;107271:64:::1;;;;-1:-1:-1::0;;;107271:64:0::1;;;;;;;:::i;:::-;106982:365;106960:387;107366:20:::0;;107358:57:::1;;;::::0;-1:-1:-1;;;107358:57:0;;15904:2:1;107358:57:0::1;::::0;::::1;15886:21:1::0;15943:2;15923:18;;;15916:30;-1:-1:-1;;;15962:18:1;;;15955:51;16023:18;;107358:57:0::1;15702:345:1::0;107358:57:0::1;107448:20:::0;;:40;-1:-1:-1;107448:40:0::1;107426:112;;;::::0;-1:-1:-1;;;107426:112:0;;20211:2:1;107426:112:0::1;::::0;::::1;20193:21:1::0;20250:2;20230:18;;;20223:30;-1:-1:-1;;;20269:18:1;;;20262:52;20331:18;;107426:112:0::1;20009:346:1::0;107426:112:0::1;107571:34;::::0;-1:-1:-1;;;107571:34:0;;107599:4:::1;107571:34;::::0;::::1;359:51:1::0;107609:16:0;;107571:9:::1;-1:-1:-1::0;;;;;107571:19:0::1;::::0;::::1;::::0;332:18:1;;107571:34:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;107549:134;;;::::0;-1:-1:-1;;;107549:134:0;;16603:2:1;107549:134:0::1;::::0;::::1;16585:21:1::0;16642:2;16622:18;;;16615:30;16681:32;16661:18;;;16654:60;16731:18;;107549:134:0::1;16401:354:1::0;107549:134:0::1;107704:17;107724:29;107736:16;107724:11;:29::i;:::-;107704:49;;107784:1;107772:9;:13;107764:60;;;;-1:-1:-1::0;;;107764:60:0::1;;;;;;;:::i;:::-;107864:20:::0;;107892:3:::1;::::0;107864:24:::1;::::0;107887:1:::1;107864:24;:::i;:::-;107863:32;;;;:::i;:::-;107843:16;:53;107835:95;;;::::0;-1:-1:-1;;;107835:95:0;;18085:2:1;107835:95:0::1;::::0;::::1;18067:21:1::0;18124:2;18104:18;;;18097:30;18163:32;18143:18;;;18136:60;18213:18;;107835:95:0::1;17883:354:1::0;107835:95:0::1;107941:20;107964:28;107983:9:::0;107964:16;:28:::1;:::i;:::-;107941:51:::0;-1:-1:-1;108013:48:0::1;-1:-1:-1::0;;;;;108013:9:0::1;:22;108036:10;107941:51:::0;108013:22:::1;:48::i;:::-;108095:20;::::0;108072:54:::1;::::0;-1:-1:-1;;;;;108072:9:0::1;:22:::0;::::1;::::0;108095:20:::1;::::0;::::1;;108116:9:::0;108072:22:::1;:54::i;:::-;108204:49;::::0;-1:-1:-1;;;108204:49:0;;-1:-1:-1;;;;;108204:10:0::1;:19;::::0;::::1;::::0;:49:::1;::::0;108224:10:::1;::::0;108236:16;;108204:49:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;108292:16;108268:9;:20;;:40;;;;;;;:::i;:::-;::::0;;-1:-1:-1;108323:21:0::1;::::0;::::1;:41:::0;;108348:16;;108323:21;:41:::1;::::0;108348:16;;108323:41:::1;:::i;:::-;::::0;;-1:-1:-1;108379:16:0::1;:36:::0;;108399:16;;108379;::::1;::::0;:36:::1;::::0;108399:16;;108379:36:::1;:::i;:::-;;;;;;;;108449:16;108430:15;;:35;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;108495:10:0::1;108480:26;::::0;;;:14:::1;:26;::::0;;;;;;;;:38;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;108538:42;::::1;::::0;::::1;::::0;108563:16;160:25:1;;148:2;133:18;;14:177;50167:201:0;49154:13;:11;:13::i;:::-;-1:-1:-1;;;;;50256:22:0;::::1;50248:73;;;::::0;-1:-1:-1;;;50248:73:0;;20562:2:1;50248:73:0::1;::::0;::::1;20544:21:1::0;20601:2;20581:18;;;20574:30;20640:34;20620:18;;;20613:62;-1:-1:-1;;;20691:18:1;;;20684:36;20737:19;;50248:73:0::1;20360:402:1::0;50248:73:0::1;50332:28;50351:8;50332:18;:28::i;116026:165::-:0;49154:13;:11;:13::i;:::-;116100:20:::1;:37:::0;;;116148:18:::1;:35:::0;116026:165::o;121031:161::-;49154:13;:11;:13::i;:::-;121091:8:::1;::::0;::::1;;:17;121082:45;;;::::0;-1:-1:-1;;;121082:45:0;;20969:2:1;121082:45:0::1;::::0;::::1;20951:21:1::0;21008:2;20988:18;;;20981:30;-1:-1:-1;;;21027:18:1;;;21020:44;21081:18;;121082:45:0::1;20767:338:1::0;121082:45:0::1;121138:8;:15:::0;;-1:-1:-1;;121138:15:0::1;121149:4;121138:15;::::0;;121169::::1;::::0;::::1;::::0;121138:8:::1;::::0;121169:15:::1;121031:161::o:0;49433:132::-;49314:7;49341:6;-1:-1:-1;;;;;49341:6:0;36871:10;49497:23;49489:68;;;;-1:-1:-1;;;49489:68:0;;21312:2:1;49489:68:0;;;21294:21:1;;;21331:18;;;21324:30;21390:34;21370:18;;;21363:62;21442:18;;49489:68:0;21110:356:1;35297:293:0;34699:1;35431:7;;:19;35423:63;;;;-1:-1:-1;;;35423:63:0;;21673:2:1;35423:63:0;;;21655:21:1;21712:2;21692:18;;;21685:30;21751:33;21731:18;;;21724:61;21802:18;;35423:63:0;21471:355:1;35423:63:0;34699:1;35564:7;:18;35297:293::o;54796:162::-;54879:71;54899:5;54921;-1:-1:-1;;;;;54921:14:0;;54938:2;54942:5;54906:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54906:43:0;;;;;;;;;;;54879:19;:71::i;:::-;54796:162;;;:::o;55203:190::-;55331:53;;-1:-1:-1;;;;;22089:15:1;;;55331:53:0;;;22071:34:1;22141:15;;;22121:18;;;22114:43;22173:18;;;22166:34;;;55304:81:0;;55324:5;;55346:18;;;;;22006::1;;55331:53:0;21831:375:1;55304:81:0;55203:190;;;;:::o;115394:197::-;115470:13;;115456:11;;:27;;;;:::i;:::-;115441:12;:42;;;115524:15;115494:27;:45;115555:28;;160:25:1;;;115555:28:0;;148:2:1;133:18;115555:28:0;;;;;;;115394:197::o;50528:191::-;50602:16;50621:6;;-1:-1:-1;;;;;50638:17:0;;;-1:-1:-1;;;;;;50638:17:0;;;;;;50671:40;;50621:6;;;;;;;50671:40;;50602:16;50671:40;50591:128;50528:191;:::o;57607:638::-;58031:23;58057:33;-1:-1:-1;;;;;58057:27:0;;58085:4;58057:27;:33::i;:::-;58031:59;;58105:10;:17;58126:1;58105:22;;:57;;;;;58143:10;58132:30;;;;;;;;;;;;:::i;:::-;58131:31;58105:57;58101:137;;;58186:40;;-1:-1:-1;;;58186:40:0;;-1:-1:-1;;;;;377:32:1;;58186:40:0;;;359:51:1;332:18;;58186:40:0;196:220:1;25283:153:0;25358:12;25390:38;25412:6;25420:4;25426:1;25390:21;:38::i;:::-;25383:45;;25283:153;;;;;:::o;25771:398::-;25870:12;25923:5;25899:21;:29;25895:110;;;25952:41;;-1:-1:-1;;;25952:41:0;;25987:4;25952:41;;;359:51:1;332:18;;25952:41:0;196:220:1;25895:110:0;26016:12;26030:23;26057:6;-1:-1:-1;;;;;26057:11:0;26076:5;26083:4;26057:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26015:73;;;;26106:55;26133:6;26141:7;26150:10;26106:26;:55::i;:::-;26099:62;25771:398;-1:-1:-1;;;;;;25771:398:0:o;27247:597::-;27395:12;27425:7;27420:417;;27449:19;27457:10;27449:7;:19::i;:::-;27420:417;;;27677:17;;:22;:49;;;;-1:-1:-1;;;;;;27703:18:0;;;:23;27677:49;27673:121;;;27754:24;;-1:-1:-1;;;27754:24:0;;-1:-1:-1;;;;;377:32:1;;27754:24:0;;;359:51:1;332:18;;27754:24:0;196:220:1;27673:121:0;-1:-1:-1;27815:10:0;27808:17;;28397:528;28530:17;;:21;28526:392;;28762:10;28756:17;28819:15;28806:10;28802:2;28798:19;28791:44;28526:392;28889:17;;-1:-1:-1;;;28889:17:0;;;;;;;;;;;648:173:1;716:20;;-1:-1:-1;;;;;765:31:1;;755:42;;745:70;;811:1;808;801:12;826:186;885:6;938:2;926:9;917:7;913:23;909:32;906:52;;;954:1;951;944:12;906:52;977:29;996:9;977:29;:::i;1893:180::-;1952:6;2005:2;1993:9;1984:7;1980:23;1976:32;1973:52;;;2021:1;2018;2011:12;1973:52;-1:-1:-1;2044:23:1;;1893:180;-1:-1:-1;1893:180:1:o;2618:254::-;2686:6;2694;2747:2;2735:9;2726:7;2722:23;2718:32;2715:52;;;2763:1;2760;2753:12;2715:52;2786:29;2805:9;2786:29;:::i;:::-;2776:39;2862:2;2847:18;;;;2834:32;;-1:-1:-1;;;2618:254:1:o;3100:248::-;3168:6;3176;3229:2;3217:9;3208:7;3204:23;3200:32;3197:52;;;3245:1;3242;3235:12;3197:52;-1:-1:-1;;3268:23:1;;;3338:2;3323:18;;;3310:32;;-1:-1:-1;3100:248:1:o;4029:118::-;4115:5;4108:13;4101:21;4094:5;4091:32;4081:60;;4137:1;4134;4127:12;4152:241;4208:6;4261:2;4249:9;4240:7;4236:23;4232:32;4229:52;;;4277:1;4274;4267:12;4229:52;4316:9;4303:23;4335:28;4357:5;4335:28;:::i;4398:383::-;4472:6;4480;4488;4541:2;4529:9;4520:7;4516:23;4512:32;4509:52;;;4557:1;4554;4547:12;4509:52;4580:29;4599:9;4580:29;:::i;:::-;4570:39;;4656:2;4645:9;4641:18;4628:32;4618:42;;4710:2;4699:9;4695:18;4682:32;4723:28;4745:5;4723:28;:::i;:::-;4770:5;4760:15;;;4398:383;;;;;:::o;4786:309::-;4851:6;4859;4912:2;4900:9;4891:7;4887:23;4883:32;4880:52;;;4928:1;4925;4918:12;4880:52;4964:9;4951:23;4941:33;;5024:2;5013:9;5009:18;4996:32;5037:28;5059:5;5037:28;:::i;:::-;5084:5;5074:15;;;4786:309;;;;;:::o;5445:127::-;5506:10;5501:3;5497:20;5494:1;5487:31;5537:4;5534:1;5527:15;5561:4;5558:1;5551:15;5577:168;5650:9;;;5681;;5698:15;;;5692:22;;5678:37;5668:71;;5719:18;;:::i;5750:342::-;5952:2;5934:21;;;5991:2;5971:18;;;5964:30;-1:-1:-1;;;6025:2:1;6010:18;;6003:48;6083:2;6068:18;;5750:342::o;6097:406::-;6299:2;6281:21;;;6338:2;6318:18;;;6311:30;6377:34;6372:2;6357:18;;6350:62;-1:-1:-1;;;6443:2:1;6428:18;;6421:40;6493:3;6478:19;;6097:406::o;6854:125::-;6919:9;;;6940:10;;;6937:36;;;6953:18;;:::i;6984:128::-;7051:9;;;7072:11;;;7069:37;;;7086:18;;:::i;7117:217::-;7157:1;7183;7173:132;;7227:10;7222:3;7218:20;7215:1;7208:31;7262:4;7259:1;7252:15;7290:4;7287:1;7280:15;7173:132;-1:-1:-1;7319:9:1;;7117:217::o;7687:184::-;7757:6;7810:2;7798:9;7789:7;7785:23;7781:32;7778:52;;;7826:1;7823;7816:12;7778:52;-1:-1:-1;7849:16:1;;7687:184;-1:-1:-1;7687:184:1:o;7876:398::-;8078:2;8060:21;;;8117:2;8097:18;;;8090:30;8156:34;8151:2;8136:18;;8129:62;-1:-1:-1;;;8222:2:1;8207:18;;8200:32;8264:3;8249:19;;7876:398::o;8279:::-;8481:2;8463:21;;;8520:2;8500:18;;;8493:30;8559:34;8554:2;8539:18;;8532:62;-1:-1:-1;;;8625:2:1;8610:18;;8603:32;8667:3;8652:19;;8279:398::o;11905:135::-;11944:3;11965:17;;;11962:43;;11985:18;;:::i;:::-;-1:-1:-1;12032:1:1;12021:13;;11905:135::o;12045:274::-;-1:-1:-1;;;;;12237:32:1;;;;12219:51;;12301:2;12286:18;;12279:34;12207:2;12192:18;;12045:274::o;13390:354::-;13592:2;13574:21;;;13631:2;13611:18;;;13604:30;13670:32;13665:2;13650:18;;13643:60;13735:2;13720:18;;13390:354::o;14469:401::-;14671:2;14653:21;;;14710:2;14690:18;;;14683:30;14749:34;14744:2;14729:18;;14722:62;-1:-1:-1;;;14815:2:1;14800:18;;14793:35;14860:3;14845:19;;14469:401::o;14875:407::-;15077:2;15059:21;;;15116:2;15096:18;;;15089:30;15155:34;15150:2;15135:18;;15128:62;-1:-1:-1;;;15221:2:1;15206:18;;15199:41;15272:3;15257:19;;14875:407::o;15287:410::-;15489:2;15471:21;;;15528:2;15508:18;;;15501:30;15567:34;15562:2;15547:18;;15540:62;-1:-1:-1;;;15633:2:1;15618:18;;15611:44;15687:3;15672:19;;15287:410::o;17480:398::-;17682:2;17664:21;;;17721:2;17701:18;;;17694:30;17760:34;17755:2;17740:18;;17733:62;-1:-1:-1;;;17826:2:1;17811:18;;17804:32;17868:3;17853:19;;17480:398::o;22211:245::-;22278:6;22331:2;22319:9;22310:7;22306:23;22302:32;22299:52;;;22347:1;22344;22337:12;22299:52;22379:9;22373:16;22398:28;22420:5;22398:28;:::i;22461:412::-;22590:3;22628:6;22622:13;22653:1;22663:129;22677:6;22674:1;22671:13;22663:129;;;22775:4;22759:14;;;22755:25;;22749:32;22736:11;;;22729:53;22692:12;22663:129;;;-1:-1:-1;22847:1:1;22811:16;;22836:13;;;-1:-1:-1;22811:16:1;22461:412;-1:-1:-1;22461:412:1:o
Swarm Source
ipfs://b5238863d9c7280935da6daa40f884a82c3d1c9fa091414489cad77bcd9417f3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.001264 | 3,013,233.4362 | $3,808.46 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.