Source Code
Overview
GLMR Balance
GLMR Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 553 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer From | 4019160 | 924 days ago | IN | 0 GLMR | 0.0193593 | ||||
| Transfer From | 4019152 | 924 days ago | IN | 0 GLMR | 0.00594011 | ||||
| Transfer From | 3986301 | 928 days ago | IN | 0 GLMR | 0.01175526 | ||||
| Transfer From | 3986298 | 928 days ago | IN | 0 GLMR | 0.01213165 | ||||
| Transfer From | 3986279 | 928 days ago | IN | 0 GLMR | 0.01297613 | ||||
| Transfer From | 3986264 | 928 days ago | IN | 0 GLMR | 0.02047782 | ||||
| Set Favourite NF... | 3932300 | 936 days ago | IN | 0 GLMR | 0.00446333 | ||||
| Transfer From | 3732079 | 964 days ago | IN | 0 GLMR | 0.0065011 | ||||
| Transfer From | 3732071 | 964 days ago | IN | 0 GLMR | 0.01359242 | ||||
| Transfer From | 3732063 | 964 days ago | IN | 0 GLMR | 0.01449224 | ||||
| Transfer From | 3732047 | 964 days ago | IN | 0 GLMR | 0.01542002 | ||||
| Transfer From | 3732032 | 964 days ago | IN | 0 GLMR | 0.01626091 | ||||
| Transfer From | 3732017 | 964 days ago | IN | 0 GLMR | 0.01719292 | ||||
| Transfer From | 3732005 | 964 days ago | IN | 0 GLMR | 0.01753761 | ||||
| Transfer From | 3731996 | 964 days ago | IN | 0 GLMR | 0.0184362 | ||||
| Transfer From | 3731986 | 964 days ago | IN | 0 GLMR | 0.01940045 | ||||
| Transfer From | 3731977 | 964 days ago | IN | 0 GLMR | 0.02026642 | ||||
| Transfer From | 3731966 | 964 days ago | IN | 0 GLMR | 0.00648549 | ||||
| Transfer From | 3731958 | 964 days ago | IN | 0 GLMR | 0.00647922 | ||||
| Transfer From | 3731950 | 964 days ago | IN | 0 GLMR | 0.00649032 | ||||
| Transfer From | 3731937 | 964 days ago | IN | 0 GLMR | 0.0136084 | ||||
| Transfer From | 3731912 | 964 days ago | IN | 0 GLMR | 0.01440872 | ||||
| Transfer From | 3731905 | 964 days ago | IN | 0 GLMR | 0.01534226 | ||||
| Transfer From | 3731891 | 964 days ago | IN | 0 GLMR | 0.01636845 | ||||
| Transfer From | 3724988 | 965 days ago | IN | 0 GLMR | 0.01454821 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Sinergy
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity)
/**
*Submitted for verification at moonbeam.moonscan.io on 2023-04-16
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount);
(bool success, ) = recipient.call{value: amount}("");
require(success);
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
0,
"Address: low-level call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
"Address: low-level call with value failed"
);
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(
address(this).balance >= value,
"Address: insufficient balance for call"
);
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data
) internal view returns (bytes memory) {
return
functionStaticCall(
target,
data,
"Address: low-level static call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data
) internal returns (bytes memory) {
return
functionDelegateCall(
target,
data,
"Address: low-level delegate call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(
bytes memory returndata,
string memory errorMessage
) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
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 `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);
}
}
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0);
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
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) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(
uint256 a,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return
result +
(rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return
result +
(rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return
result +
(rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(
uint256 value,
Rounding rounding
) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return
result +
(rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
interface IERC721 is IERC165 {
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(
uint256 tokenId
) external view returns (address operator);
function isApprovedForAll(
address owner,
address operator
) external view returns (bool);
}
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
// Sinergy NFT
mapping(address => uint256[]) public get_my_nfts;
mapping(address => uint256) public favourite_nft;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function updateFromAble() public {}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(
address owner
) public view virtual override returns (uint256) {
require(owner != address(0));
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(
uint256 tokenId
) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0));
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(
uint256 tokenId
) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner);
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()));
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(
uint256 tokenId
) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(
address operator,
bool approved
) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(
address owner,
address operator
) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId));
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId));
_safeTransfer(from, to, tokenId, data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data));
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(
address spender,
uint256 tokenId
) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner ||
isApprovedForAll(owner, spender) ||
getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, data));
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0));
require(!_exists(tokenId));
_beforeTokenTransfer(address(0), to, tokenId);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId));
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function add_nft_before_transfer(uint256 tokenId, address wallet) private {
get_my_nfts[wallet].push(tokenId);
if (favourite_nft[wallet] == 0)
{
favourite_nft[wallet] = tokenId;
}
}
function delete_nft_before_transfer(
uint256 tokenId,
address wallet
) private {
uint256 i = 0;
while (get_my_nfts[wallet][i] != tokenId) i++;
for (i; i < (_balances[wallet] - 1); i++) {
get_my_nfts[wallet][i] = get_my_nfts[wallet][i + 1];
}
get_my_nfts[wallet].pop();
if (favourite_nft[wallet] == tokenId)
{
favourite_nft[wallet] = get_my_nfts[wallet][0];
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from);
require(to != address(0));
_beforeTokenTransfer(from, to, tokenId);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from);
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
delete_nft_before_transfer(tokenId, from);
_balances[from] -= 1;
add_nft_before_transfer(tokenId, to);
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator);
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId));
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try
IERC721Receiver(to).onERC721Received(
_msgSender(),
from,
tokenId,
data
)
returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert();
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any (single) token transfer. This includes minting and burning.
* See {_beforeConsecutiveTokenTransfer}.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` 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 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any (single) transfer of tokens. This includes minting and burning.
* See {_afterConsecutiveTokenTransfer}.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `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 tokenId
) internal virtual {}
/**
* @dev Hook that is called before consecutive token transfers.
* Calling conditions are similar to {_beforeTokenTransfer}.
*
* The default implementation include balances updates that extensions such as {ERC721Consecutive} cannot perform
* directly.
*/
function _beforeConsecutiveTokenTransfer(
address from,
address to,
uint256 /*first*/,
uint96 size
) internal virtual {
if (from != address(0)) {
_balances[from] -= size;
}
if (to != address(0)) {
_balances[to] += size;
}
}
/**
* @dev Hook that is called after consecutive token transfers.
* Calling conditions are similar to {_afterTokenTransfer}.
*/
function _afterConsecutiveTokenTransfer(
address /*from*/,
address /*to*/,
uint256 /*first*/,
uint96 /*size*/
) internal virtual {}
}
abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(
uint256 tokenId
) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(
uint256 tokenId,
string memory _tokenURI
) internal virtual {
require(_exists(tokenId));
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev See {ERC721-_burn}. This override additionally checks to see if a
* token-specific URI was set for the token, and if so, it deletes the token URI from
* the storage mapping.
*/
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
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());
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing 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));
_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);
}
}
contract SinergyMigration is ERC721, ERC721URIStorage, Ownable {
// Constants
uint256 public constant PRICE = 36 ether;
uint256 public constant REWARD = 3 ether;
uint256 public constant TO_DEVELOPMENT = 3 ether;
// NFT GENESIS
string constant NFT_GENESIS_NAME = "GENESIS";
string constant NFT_GENESIS_INSCRIPTION = "GENESIS INSCRIPTION";
string constant NFT_GENESIS_VALUE_PROPOSAL = "GENESIS VALUE PROPOSAL";
string constant NFT_GENESIS_IMAGE_URL =
"https://res.cloudinary.com/saver-community/image/upload/v1666380501/jvjbls4lg5mtxsxhlhnf.png";
// Migration
Sinergy ContractMigration =
Sinergy(0xEa063b5A744616a161272a013a626A1cBD80Ee1B);
// ERC20's
ERC20 CDA = ERC20(0x8e3153a724aF487Fd11fB4C4cDA508984dEDf3c4);
ERC20 ABLE = ERC20(0xd9B9c7A1B42f1ad78D9C3Dd5C7F0381277ddc9Bb);
ERC20 BUSD = ERC20(0xB856De7DAFf71A0d7eAFD4CC22A7db6F762179de);
// Able Sale
SinergySale public ABLE_SALE =
SinergySale(0xD8c101aA6b225135b437E3B87988457B23Adb2f0);
SinergySale public TRIPLE_SALE =
SinergySale(0xD8c101aA6b225135b437E3B87988457B23Adb2f0);
// Address
address public communityWallet = 0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
address public constant developmentWallet =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
uint256 public oneDay = 12 minutes;
uint256 public timeToNextReward;
// Counters
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
// Migration
mapping(address => bool) public isRecover;
mapping(uint256 => bool) public nftRecover;
mapping(uint256 => bool) public first_level_references_recover;
mapping(uint256 => bool) public second_level_references_recover;
mapping(uint256 => bool) public third_level_references_recover;
mapping(uint256 => bool) public four_level_references_recover;
mapping(uint256 => bool) public five_level_references_recover;
mapping(uint256 => bool) public six_level_references_recover;
mapping(uint256 => bool) public seven_level_references_recover;
mapping(uint256 => bool) public eight_level_references_recover;
mapping(uint256 => bool) public nine_level_references_recover;
uint256 public starting_nft_id;
uint256[] public recovered_nfts;
uint256 public recovered_nfts_amount;
// Constructor
constructor(uint256 initial_tokenID) ERC721("Saver Sinergy", "Sinergy") {
while (_tokenIds.current() < initial_tokenID) {
_tokenIds.increment();
}
timeToNextReward = block.timestamp + oneDay;
starting_nft_id = initial_tokenID;
}
// NFT's
uint256 public nfts_qualified;
mapping(address => bool) public is_qualified;
// mapping(address => uint256) public favourite_nft;
// mapping(address => uint256[]) public get_my_nfts;
mapping(uint256 => string) public get_nft_name;
mapping(uint256 => string) public get_nft_inscription;
mapping(uint256 => string) public get_nft_value_proposal;
mapping(uint256 => uint256) public get_nft_timestamp_created;
mapping(uint256 => string) public get_nft_image_url;
// mapping(string => uint256[]) public get_nfts_by_keyword; // me queda implementarlo en el crear nft
// References
// Esto sabemos que va (Cantidad de NFTs que estan conectados conmigo en el NIVEL x)
mapping(uint256 => uint256) public get_first_level_amount_reference;
mapping(uint256 => uint256) public get_second_level_amount_reference;
mapping(uint256 => uint256) public get_third_level_amount_reference;
mapping(uint256 => uint256) public get_four_level_amount_reference;
mapping(uint256 => uint256) public get_five_level_amount_reference;
mapping(uint256 => uint256) public get_six_level_amount_reference;
mapping(uint256 => uint256) public get_seven_level_amount_reference;
mapping(uint256 => uint256) public get_eight_level_amount_reference;
mapping(uint256 => uint256) public get_nine_level_amount_reference;
mapping(uint256 => uint256) public get_total_amount_references; // Cantidad de NFTs que estan conectados conmigo en total.
// Esto puede fallar (NFT ID de cada uno que esta conectado con nosotros en el NIVEL x)
mapping(uint256 => uint256[]) public get_first_level_references;
mapping(uint256 => uint256[]) public get_second_level_references;
mapping(uint256 => uint256[]) public get_third_level_references;
mapping(uint256 => uint256[]) public get_four_level_references;
mapping(uint256 => uint256[]) public get_five_level_references;
mapping(uint256 => uint256[]) public get_six_level_references;
mapping(uint256 => uint256[]) public get_seven_level_references;
mapping(uint256 => uint256[]) public get_eight_level_references;
mapping(uint256 => uint256[]) public get_nine_level_references;
// NFT al que me conecte
mapping(uint256 => uint256) public get_nft_reference;
// Rewards
mapping(uint256 => uint256) public get_nft_balance_to_claim;
mapping(uint256 => uint256) public get_nft_rewards_claimed;
// Passive Rewards
uint256 public passiveRewardID;
mapping(uint256 => uint256) public passiveReward;
mapping(uint256 => uint256) public passiveRewardClaimed;
mapping(address => uint256) public timestampToClaimPassiveReward;
// Constancy Rewards (usa el ID de las pasivas)
mapping(uint256 => uint256) public constancyReward;
mapping(uint256 => uint256) public constancyRewardClaimed;
mapping(address => uint256) public timestampToClaimConstancyReward;
// Resources
uint256 public resourcesAmount;
// Stadistics
mapping(address => uint256) public total_stablecoin_earned;
mapping(address => uint256) public total_lost_income;
mapping(address => uint256) public actual_lost_income;
// Auxs
mapping(address => uint256) public amount_nfts_considered;
// Public Functions
// Migration
function migrate() public {
require(!isRecover[msg.sender]);
if (msg.sender == communityWallet) {
create_genesis_nfts();
isRecover[communityWallet] = true;
return;
}
uint256 amountNFTs = ContractMigration.balanceOf(msg.sender);
uint256[] storage nfts = get_my_nfts[msg.sender];
uint256[] storage new_nfts_recovered = recovered_nfts;
uint256 nftID;
for (uint256 i = 0; i < amountNFTs; i++) {
nftID = ContractMigration.get_my_nfts(msg.sender, i);
nfts.push(nftID);
new_nfts_recovered.push(nftID);
recovered_nfts_amount++;
recoverNFT(nftID);
_safeMint(msg.sender, nftID);
}
favourite_nft[msg.sender] = ContractMigration.favourite_nft(msg.sender);
get_my_nfts[msg.sender] = nfts;
recovered_nfts = new_nfts_recovered;
isRecover[msg.sender] = true;
}
function recoverNFT(uint256 nftID) private {
// NFT Basic Info
get_nft_name[nftID] = ContractMigration.get_nft_name(nftID);
get_nft_inscription[nftID] = ContractMigration.get_nft_inscription(
nftID
);
get_nft_value_proposal[nftID] = ContractMigration
.get_nft_value_proposal(nftID);
get_nft_timestamp_created[nftID] = ContractMigration
.get_nft_timestamp_created(nftID);
get_nft_image_url[nftID] = ContractMigration.get_nft_image_url(nftID);
get_nft_reference[nftID] = ContractMigration.get_nft_reference(nftID);
// References
get_first_level_amount_reference[nftID] = ContractMigration
.get_first_level_amount_reference(nftID);
get_second_level_amount_reference[nftID] = ContractMigration
.get_second_level_amount_reference(nftID);
get_third_level_amount_reference[nftID] = ContractMigration
.get_third_level_amount_reference(nftID);
get_four_level_amount_reference[nftID] = ContractMigration
.get_four_level_amount_reference(nftID);
get_five_level_amount_reference[nftID] = ContractMigration
.get_five_level_amount_reference(nftID);
get_six_level_amount_reference[nftID] = ContractMigration
.get_six_level_amount_reference(nftID);
get_seven_level_amount_reference[nftID] = ContractMigration
.get_seven_level_amount_reference(nftID);
get_eight_level_amount_reference[nftID] = ContractMigration
.get_eight_level_amount_reference(nftID);
get_nine_level_amount_reference[nftID] = ContractMigration
.get_nine_level_amount_reference(nftID);
get_total_amount_references[nftID] = ContractMigration
.get_total_amount_references(nftID);
nftRecover[nftID] = true;
}
function recoverFirstLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!first_level_references_recover[nftID]
);
uint256[] storage nfts = get_first_level_references[nftID];
// uint256 amount = ContractMigration.get_first_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_first_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_first_level_references(nftID, i));
}
get_first_level_references[nftID] = nfts;
first_level_references_recover[nftID] = true;
}
function recoverSecondLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!second_level_references_recover[nftID]
);
uint256[] storage nfts = get_second_level_references[nftID];
// uint256 amount = ContractMigration.get_second_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_second_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_second_level_references(nftID, i));
}
get_second_level_references[nftID] = nfts;
second_level_references_recover[nftID] = true;
}
function recoverThirdLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!third_level_references_recover[nftID]
);
uint256[] storage nfts = get_third_level_references[nftID];
// uint256 amount = ContractMigration.get_third_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_third_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_third_level_references(nftID, i));
}
get_third_level_references[nftID] = nfts;
third_level_references_recover[nftID] = true;
}
function recoverFourLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!four_level_references_recover[nftID]
);
uint256[] storage nfts = get_four_level_references[nftID];
// uint256 amount = ContractMigration.get_four_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_four_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_four_level_references(nftID, i));
}
get_four_level_references[nftID] = nfts;
four_level_references_recover[nftID] = true;
}
function recoverFiveLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!five_level_references_recover[nftID]
);
uint256[] storage nfts = get_five_level_references[nftID];
// uint256 amount = ContractMigration.get_five_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_five_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_five_level_references(nftID, i));
}
get_five_level_references[nftID] = nfts;
five_level_references_recover[nftID] = true;
}
function recoverSixLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) && !six_level_references_recover[nftID]
);
uint256[] storage nfts = get_six_level_references[nftID];
// uint256 amount = ContractMigration.get_six_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_six_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_six_level_references(nftID, i));
}
get_six_level_references[nftID] = nfts;
six_level_references_recover[nftID] = true;
}
function recoverSevenLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!seven_level_references_recover[nftID]
);
uint256[] storage nfts = get_seven_level_references[nftID];
// uint256 amount = ContractMigration.get_seven_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_seven_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_seven_level_references(nftID, i));
}
get_seven_level_references[nftID] = nfts;
seven_level_references_recover[nftID] = true;
}
function recoverEightLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!eight_level_references_recover[nftID]
);
uint256[] storage nfts = get_eight_level_references[nftID];
// uint256 amount = ContractMigration.get_eight_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_eight_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_eight_level_references(nftID, i));
}
get_eight_level_references[nftID] = nfts;
eight_level_references_recover[nftID] = true;
}
function recoverNineLevelReferences(uint256 nftID) public {
require(
msg.sender == ownerOf(nftID) &&
!nine_level_references_recover[nftID]
);
uint256[] storage nfts = get_nine_level_references[nftID];
// uint256 amount = ContractMigration.get_nine_level_amount_reference(nftID);
for (
uint256 i = 0;
i < ContractMigration.get_nine_level_amount_reference(nftID);
i++
) {
nfts.push(ContractMigration.get_nine_level_references(nftID, i));
}
get_nine_level_references[nftID] = nfts;
nine_level_references_recover[nftID] = true;
}
// NFT
function createNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
string memory _uri,
string memory _imageURL,
uint256 _ref,
uint256 _timestamp
) public {
// Get Reference
uint256 _reference = favourite_nft[ABLE.lastDonationFrom()];
if (_ref != 0) {
_reference = _ref;
}
if (_reference == 0) {
_reference = 8;
}
require(_reference < _tokenIds.current());
BUSD.transferFrom(msg.sender, address(this), PRICE);
update_qualified_nfts(msg.sender);
ABLE_SALE.try_to_swap(favourite_nft[msg.sender]);
// Mint NFT
uint256 tokenID = _tokenIds.current();
_tokenIds.increment();
_safeMint(msg.sender, tokenID);
// Set URI
_setTokenURI(tokenID, _uri);
// Add information to the NFT
get_nft_name[tokenID] = _name;
get_nft_inscription[tokenID] = _inscription;
get_nft_value_proposal[tokenID] = _valueProposal;
get_nft_reference[tokenID] = _reference;
get_nft_image_url[tokenID] = _imageURL;
get_nft_timestamp_created[tokenID] = _timestamp;
if (favourite_nft[msg.sender] == 0) {
favourite_nft[msg.sender] = tokenID;
}
uint256[] storage myNFTS = get_my_nfts[msg.sender];
myNFTS.push(tokenID);
get_my_nfts[msg.sender] = myNFTS;
// Increase the resources amount
resourcesAmount += TO_DEVELOPMENT;
// Increase Passive Rewards
passiveReward[passiveRewardID] += 6 ether;
// Distribute BUSD's in 9 generations
distribute(tokenID, _reference, true);
update(msg.sender);
// Emit event
// emit Mint(tokenID, block.timestamp, _name, _valueProposal, msg.sender);
}
function modifyNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
uint256 _tokenID
) public {
require(msg.sender == ownerOf(_tokenID));
BUSD.transferFrom(msg.sender, address(this), PRICE);
// Modify the NFT
get_nft_name[_tokenID] = _name;
get_nft_inscription[_tokenID] = _inscription;
get_nft_value_proposal[_tokenID] = _valueProposal;
// Increase the resources amount
resourcesAmount += TO_DEVELOPMENT;
// Increase Passive Rewards
passiveReward[passiveRewardID] += 6 ether;
// Distribute BUSD in 9 generations
distribute(_tokenID, get_nft_reference[_tokenID], false);
update(msg.sender);
}
// Rewards
function claimReward(uint256 _tokenID) public {
require(
msg.sender == ownerOf(_tokenID) &&
get_nft_balance_to_claim[_tokenID] > 0
);
BUSD.transfer(msg.sender, get_nft_balance_to_claim[_tokenID]);
// // Emit events
// emit Reward(
// _tokenID,
// get_nft_balance_to_claim[_tokenID],
// msg.sender,
// block.timestamp
// );
get_nft_rewards_claimed[_tokenID] += get_nft_balance_to_claim[_tokenID];
get_nft_balance_to_claim[_tokenID] = 0;
update(msg.sender);
}
function viewAmountToClaimPassiveReward(
address wallet
) public view returns (uint256) {
if (passiveRewardID == 0 || nfts_qualified == 0) return 0;
if (nfts_qualified < balanceOf(wallet)) return 0;
uint256 amount_raised = passiveReward[passiveRewardID - 1];
uint256 amount_claimed = passiveRewardClaimed[passiveRewardID - 1];
uint256 amount_to_claim = ((balanceOf(wallet) * amount_raised) /
nfts_qualified);
if (amount_to_claim > (amount_raised - amount_claimed)) {
return (amount_raised - amount_claimed);
}
return amount_to_claim;
}
function viewAmountToClaimConstancyReward(
address wallet
) public view returns (uint256) {
// Formula:
// Veces que gane el Premio Able * Cantidad recaudada / Veces que ganaron el Premio Able
uint256 totalWinsSaverReward = ABLE.totalWinsSaverReward();
uint256 winsSaverRewardOf = ABLE.winsSaverRewardOf(wallet);
if (passiveRewardID == 0 || totalWinsSaverReward == 0) return 0;
if (totalWinsSaverReward < winsSaverRewardOf) return 0;
uint256 amount_raised = constancyReward[passiveRewardID - 1];
uint256 amount_claimed = constancyRewardClaimed[passiveRewardID - 1];
uint256 amount_to_claim = ((winsSaverRewardOf * amount_raised) /
totalWinsSaverReward);
if (amount_to_claim > (amount_raised - amount_claimed)) {
return (amount_raised - amount_claimed);
}
return amount_to_claim;
}
function claimPassiveReward() public {
require(
passiveRewardID > 0 &&
block.timestamp > timestampToClaimPassiveReward[msg.sender] &&
ABLE.canReclaim(msg.sender)
);
uint256 amount = viewAmountToClaimPassiveReward(msg.sender);
BUSD.transfer(msg.sender, amount);
passiveRewardClaimed[passiveRewardID - 1] += amount;
timestampToClaimPassiveReward[msg.sender] = block.timestamp + oneDay;
update(msg.sender);
// Emit events
// emit PassiveReward(amount, msg.sender, block.timestamp);
}
function claimConstancyReward() public {
require(
passiveRewardID > 0 &&
block.timestamp > timestampToClaimConstancyReward[msg.sender] &&
ABLE.canReclaim(msg.sender) &&
ABLE.winSaverReward(msg.sender) &&
ABLE.totalWinsSaverReward() >= 2
);
uint256 amount = viewAmountToClaimConstancyReward(msg.sender);
BUSD.transfer(msg.sender, amount);
constancyRewardClaimed[passiveRewardID - 1] += amount;
timestampToClaimConstancyReward[msg.sender] = block.timestamp + oneDay;
update(msg.sender);
// Emit Event
}
function claimResources() public {
require(msg.sender == developmentWallet);
BUSD.transfer(msg.sender, resourcesAmount);
// Emit events
// emit Resources(block.timestamp, resourcesAmount);
resourcesAmount = 0;
update(msg.sender);
}
// Read functions
function getAmountOfNftMinted() public view returns (uint256) {
return _tokenIds.current();
}
// Set Functions
function setAbleAddress(address _ableAddress) public {
require(msg.sender == developmentWallet);
ABLE = ERC20(_ableAddress);
}
function setFavouriteNFT(uint256 id) public {
require(_tokenIds.current() > id);
favourite_nft[msg.sender] = id;
update(msg.sender);
}
function changeCommunityWallet(address newAddress) public {
require(msg.sender == communityWallet);
communityWallet = newAddress;
}
// Booleans
function nft_was_qualified(uint256 tokenID) public view returns (bool) {
return
ABLE.canReclaim(ownerOf(tokenID)) ||
ABLE.qualifiedHistory(ownerOf(tokenID), ABLE.cycle() - 1);
}
// Update Functions
function update_qualified_nfts(address wallet) private {
if (is_qualified[wallet]) {
nfts_qualified -= amount_nfts_considered[wallet];
amount_nfts_considered[wallet] = 0;
is_qualified[wallet] = false;
}
if (ABLE.canReclaim(wallet)) {
nfts_qualified += balanceOf(wallet);
amount_nfts_considered[wallet] = balanceOf(wallet);
is_qualified[wallet] = true;
}
}
function update_timestamp() private {
if (block.timestamp > timeToNextReward) {
if (
passiveRewardID > 0 &&
passiveReward[passiveRewardID - 1] >
passiveRewardClaimed[passiveRewardID - 1]
) {
passiveReward[passiveRewardID] += (passiveReward[
passiveRewardID - 1
] - passiveRewardClaimed[passiveRewardID - 1]);
}
if (
passiveRewardID > 0 &&
constancyReward[passiveRewardID - 1] >
constancyRewardClaimed[passiveRewardID - 1]
) {
constancyReward[passiveRewardID] += (constancyReward[
passiveRewardID - 1
] - constancyRewardClaimed[passiveRewardID - 1]);
}
passiveRewardID++;
timeToNextReward = block.timestamp + oneDay;
}
}
function update(address wallet) public {
ABLE.updateFromSinergy(wallet);
update_timestamp();
update_qualified_nfts(wallet);
}
function updateFromAble(address wallet) public {
update_timestamp();
update_qualified_nfts(wallet);
}
function getAbleBalance(address wallet) public view returns (uint256) {
return ABLE.balanceOf(wallet);
}
// SaleToken Public Functions
function set_able_sale(SinergySale ableSale) public {
require(msg.sender == developmentWallet);
ABLE_SALE = ableSale;
}
function set_triple_sale(SinergySale tripleSale) public {
require(msg.sender == developmentWallet);
TRIPLE_SALE = tripleSale;
}
function set_passive_rewards(uint256 amount) public {
require(
msg.sender == address(ABLE_SALE) ||
msg.sender == address(TRIPLE_SALE)
);
passiveReward[passiveRewardID] += amount;
}
function set_active_rewards(uint256 tokenID, uint256 amount) public {
require(
msg.sender == address(ABLE_SALE) ||
msg.sender == address(TRIPLE_SALE)
);
get_nft_balance_to_claim[tokenID] += amount;
}
function set_constancy_reward(uint256 amount) public {
require(
msg.sender == address(ABLE_SALE) ||
msg.sender == address(TRIPLE_SALE)
);
constancyReward[passiveRewardID] += amount;
}
// Private Functions
// Distribute 9 generations
function distribute(
uint256 tokenID,
uint256 _reference,
bool created
) private {
address owner;
uint256 i = 0;
while (i < 9) {
if (created) setReferences(i, tokenID, _reference);
owner = ownerOf(_reference);
if (ABLE.canReclaim(owner)) {
get_nft_balance_to_claim[_reference] += REWARD;
total_stablecoin_earned[owner] += REWARD;
} else {
passiveReward[passiveRewardID] += REWARD;
total_lost_income[owner] += REWARD;
actual_lost_income[owner] = REWARD;
}
_reference = get_nft_reference[_reference];
i++;
}
}
function create_genesis_nfts() private {
// Crear 8 NFTs para la billetera destinada a Desarrollo y Mantenimiento
// Estos NFTs deben estar vinculados entre si
uint256[] storage myNFTS = get_my_nfts[communityWallet];
uint256[] storage new_nfts_recovered = recovered_nfts;
for (uint256 i = 0; i < 9; i++) {
_safeMint(communityWallet, i);
recoverNFT(i);
myNFTS.push(i);
new_nfts_recovered.push(i);
recovered_nfts_amount++;
_setTokenURI(
i,
"ipfs://QmRi1DvgDu6zAJwpbURGNBBQTM82ZCNZAyTkEArbKZKm1U/0.json"
);
}
get_my_nfts[communityWallet] = myNFTS;
recovered_nfts = new_nfts_recovered;
}
function setReferences(uint256 i, uint256 tokenID, uint256 ref) private {
if (i == 0) {
get_first_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_first_level_references[ref];
nftIDs.push(tokenID);
get_first_level_references[ref] = nftIDs;
return;
}
if (i == 1) {
get_second_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_second_level_references[ref];
nftIDs.push(tokenID);
get_second_level_references[ref] = nftIDs;
return;
}
if (i == 2) {
get_third_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_third_level_references[ref];
nftIDs.push(tokenID);
get_third_level_references[ref] = nftIDs;
return;
}
if (i == 3) {
get_four_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_four_level_references[ref];
nftIDs.push(tokenID);
get_four_level_references[ref] = nftIDs;
return;
}
if (i == 4) {
get_five_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_five_level_references[ref];
nftIDs.push(tokenID);
get_five_level_references[ref] = nftIDs;
return;
}
if (i == 5) {
get_six_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_six_level_references[ref];
nftIDs.push(tokenID);
get_six_level_references[ref] = nftIDs;
return;
}
if (i == 6) {
get_seven_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_seven_level_references[ref];
nftIDs.push(tokenID);
get_seven_level_references[ref] = nftIDs;
return;
}
if (i == 7) {
get_eight_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_eight_level_references[ref];
nftIDs.push(tokenID);
get_eight_level_references[ref] = nftIDs;
return;
}
if (i == 8) {
get_nine_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
uint256[] storage nftIDs = get_nine_level_references[ref];
nftIDs.push(tokenID);
get_nine_level_references[ref] = nftIDs;
return;
}
}
// The following functions are overrides required by Solidity.
function _burn(
uint256 tokenId
) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(
uint256 tokenId
) public view override(ERC721, ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
contract ERC20 is Context, IERC20, IERC20Metadata {
// Migration Saver
uint256 timestampToCloseMigration;
mapping(address => bool) public isRecover;
// ERC20 Standard
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint256 public POTENCIAL = 9;
uint256 public timeStableCoinReward = 6 minutes;
// Saver
uint256 public maxSupply = 369000000000 * 10 ** 18;
uint256 public initialSupply = 369000000 * 10 ** 18;
uint256 public devSupply = 1845000 * 10 ** 18;
// Addresses
address payable public communityWallet =
payable(0xc8895f6f85D870589C42fd6d531c855bddD27B0f);
address public managementWallet =
0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
address public managementWallet2 =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
address public devWallet = 0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
// Saver Reward
mapping(address => bool) public isListedToClaimSaver;
mapping(address => uint256) public cyclesOf;
// ERC20's
// Stable Coin
ERC20 public USDC = ERC20(0x4E8F5dC8c0f21992116Aac2458b0Bded98E11F13); // USDC (6 decimals)
uint256 public USDC_DECIMALS = 6;
ERC20 public USDT = ERC20(0x17c3358F9Aa2D85E49d502EFBc27c9289ef913aA); // USDT (6 decimals)
uint256 public USDT_DECIMALS = 6;
ERC20 public BUSD = ERC20(0xB856De7DAFf71A0d7eAFD4CC22A7db6F762179de); // BUSD (18 decimals)
uint256 public BUSD_DECIMALS = 18;
// Contract Migration
ERC20 public AbleMigration =
ERC20(0xB13D289830F6512dFf4C6ce97f121F29bD400E39);
ERC20 public TripleMigration =
ERC20(0x38e43FCEEE68373e08a30714123010b8d841364d);
SinergyMigration ContractMigration =
SinergyMigration(0xEa063b5A744616a161272a013a626A1cBD80Ee1B);
// ERC721
ERC721 public SinergyBronze;
ERC721 public SinergySilver;
ERC721 public SinergyGold;
// Sell List
SinergySale public ABLE_SALE;
// Cycles
uint256 public cycle = 1;
mapping(address => uint256) public cycleToCheck;
mapping(address => uint256) public cycleToSaverReward;
uint256 public CYCLES_FOR_SAVER_REWARD = 3;
// Saver Reward
mapping(address => uint256) public balanceOfWins_SaverReward;
mapping(address => bool) public winSaverReward;
mapping(address => uint256) public winsSaverRewardOf;
mapping(address => uint256) public total_saver_earned_of;
uint256 public totalWinsSaverReward;
uint256 public total_saver_distributed;
address[] public wallet_winners;
// Stable Coin Reward
uint256 public minAmountToQualify = 3 * 10 ** 18;
uint256 public rewardID = 1;
uint256 public rewardIDonClaim;
uint256 public totalStableCoinDistribute;
mapping(uint256 => uint256) public rewardAmount; // rewardAmount[rewardID] => Amount Raised
mapping(uint256 => uint256) public rewardAmountClaimed; // rewardAmount[rewardID] => Amount Claimed
mapping(uint256 => uint256) public timeOpenClaimReward; // timeOpenClaimReward[rewardID] => timestamp
mapping(address => mapping(uint256 => bool)) public holderClaimed; // holderClaimed[wallet][rewardID] => bool
mapping(address => uint256) public stableCoinEarned;
mapping(address => uint256) public stableCoinEarnedByAbleReward;
mapping(address => bool) public isQualified; // isQualified[wallet] => bool
mapping(address => uint256) public claimFrom;
// Donations
uint256 public totalDonationBalance;
uint256 public qualifiedDonationBalance;
uint256 public totalDonations;
uint256 public wallets_with_donation_balance;
uint256 public total_qualified_wallets;
mapping(address => uint256) public donationBalance;
mapping(address => uint256) public allDonatesOf;
uint256 public lastDonationTimestamp;
address public lastDonationFrom;
// Donations per day
mapping(address => mapping(uint256 => uint256)) public donatedByDayOf; // donatedByDayOf[wallet][cycle] => amount donated
mapping(address => mapping(uint256 => uint256))
public donationBalancePerCycle;
// Savings
mapping(address => mapping(uint256 => uint256)) public usdcRecord;
mapping(address => uint256) public lastAmountUSDC;
mapping(address => mapping(uint256 => uint256)) public usdtRecord;
mapping(address => uint256) public lastAmountUSDT;
// Holders
uint256 public totalHolders;
uint256 public qualifiedHolders;
mapping(address => bool) public isHolder;
mapping(address => string) public personalPurpose;
mapping(address => string) public communityPurpose;
// Resources for Admin
uint256 public total_raised_for_admin; // Total amount raised for admin
// Videos
bool public sort; // true => sorted | false => not sorted
uint256 public videoID;
mapping(uint256 => string) public youtubeID;
mapping(uint256 => string) public firstQuestion;
mapping(uint256 => string) public secondQuestion;
mapping(uint256 => string) public thirdQuestion;
mapping(uint256 => string) public firstRealAnswer;
mapping(uint256 => string) public secondRealAnswer;
mapping(uint256 => string) public thirdRealAnswer;
mapping(uint256 => string) public firstFakeAnswer1;
mapping(uint256 => string) public secondFakeAnswer1;
mapping(uint256 => string) public thirdFakeAnswer1;
mapping(uint256 => string) public firstFakeAnswer2;
mapping(uint256 => string) public secondFakeAnswer2;
mapping(uint256 => string) public thirdFakeAnswer2;
mapping(address => mapping(uint256 => bool)) public videoAnswerOf; // answerOf[wallet][cycle] => true
// Qualified
// qualified[wallet][cycle] => bool
mapping(address => mapping(uint256 => bool)) public qualifiedSinergy;
mapping(address => mapping(uint256 => bool)) public qualifiedSaver;
mapping(address => mapping(uint256 => bool)) public qualifiedUSDC;
mapping(address => mapping(uint256 => bool)) public qualifiedUSDT;
mapping(address => mapping(uint256 => bool)) public qualifiedBDD;
mapping(address => mapping(uint256 => bool)) public qualifiedDonatedPerDay;
mapping(address => mapping(uint256 => bool)) public qualifiedVideo;
mapping(address => mapping(uint256 => bool)) public qualifiedHistory;
// Informacion
string public managementInfo;
// Events
event ClaimBUSD(
uint256 indexed date,
uint256 amount,
address indexed wallet
);
event ClaimAble(
uint256 indexed date,
uint256 amount,
address indexed wallet
);
event AnswerVideo(uint256 indexed date, bool res, address indexed wallet);
event Update(uint256 indexed date, address indexed wallet);
// Nuevos eventos
event AbleRewardQualification(
uint256 indexed date,
address indexed wallet,
bool status
); // true => te has enlistado para el premio able || false => te has descalificado del premio able
event UserQualification(
uint256 indexed date,
address indexed wallet,
bool status
);
event CycleChange(uint256 indexed date, uint256 indexed cycle);
event CloseCycle(
address indexed wallet,
uint256 cycle,
bool qualifiedSinergy,
bool qualifiedUSDT,
bool qualifiedUSDC,
bool qualifiedSaver,
bool qualifiedBDD,
bool qualifiedDonatedPerDay,
bool qualifiedVideo
);
event Points(
address indexed wallet,
uint256 cycle,
uint256 amount,
bool increase
);
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
timeOpenClaimReward[rewardID] = block.timestamp + timeStableCoinReward;
timestampToCloseMigration = block.timestamp + 30 days;
// Se mintea el 0.1% del totalSupply (369.000.000 ABLE)
_mint(communityWallet, initialSupply - devSupply);
_mint(devWallet, devSupply);
isHolder[communityWallet] = true;
isHolder[devWallet] = true;
totalHolders = 2;
qualifiedHolders = 2;
total_qualified_wallets = 2;
}
// Recover Saver
function get_able_to_recover(address wallet) public view returns (uint256) {
bool was_active = AbleMigration.canReclaim(wallet);
uint256 _cycle = AbleMigration.cycle();
uint256 i;
uint256 default_amount = AbleMigration.balanceOf(wallet) +
TripleMigration.balanceOf(wallet);
while (!was_active && i < 69) {
was_active = AbleMigration.qualifiedHistory(wallet, _cycle - i);
i++;
}
if (was_active) {
return (default_amount + AbleMigration.donationBalance(wallet));
}
return default_amount;
}
function migrate() public {
require(block.timestamp < timestampToCloseMigration);
require(!isRecover[msg.sender]);
// Recover Donation Balance
donationBalance[msg.sender] += AbleMigration.donationBalance(
msg.sender
);
totalDonationBalance += donationBalance[msg.sender];
allDonatesOf[msg.sender] += AbleMigration.allDonatesOf(msg.sender);
// Recover Purposes
personalPurpose[msg.sender] = AbleMigration.personalPurpose(msg.sender);
communityPurpose[msg.sender] = AbleMigration.communityPurpose(
msg.sender
);
// Recover SAVF (Last Saver Fast)
_mint(msg.sender, get_able_to_recover(msg.sender));
if (AbleMigration.balanceOf(msg.sender) > 0 && !isHolder[msg.sender]) {
totalHolders++;
isHolder[msg.sender] = true;
}
// Recover Qualified Donation Balance
if (canReclaim(msg.sender) && !isQualified[msg.sender]) {
qualifiedDonationBalance += donationBalance[msg.sender];
isQualified[msg.sender] = true;
qualifiedHolders++;
emit UserQualification(block.timestamp, msg.sender, true);
}
isRecover[msg.sender] = true;
}
function burn_bdd(uint256 amount) public {
require(donationBalance[msg.sender] >= amount);
reduceDonationBalance(msg.sender, amount);
}
function claim() public {
uint256 amountRaised = rewardAmount[rewardIDonClaim];
uint256 amountClaimed = rewardAmountClaimed[rewardIDonClaim];
require(!holderClaimed[msg.sender][rewardIDonClaim]);
require(rewardIDonClaim >= claimFrom[msg.sender]);
require(canReclaim(msg.sender));
uint256 stableCoinToClaim = viewClaimStableCoin(msg.sender);
require(stableCoinToClaim > 0);
require(amountRaised >= (amountClaimed + stableCoinToClaim));
require(donationBalance[msg.sender] >= (stableCoinToClaim / POTENCIAL));
require(BUSD.transfer(msg.sender, stableCoinToClaim));
reduceDonationBalance(msg.sender, stableCoinToClaim / POTENCIAL);
rewardAmountClaimed[rewardIDonClaim] += stableCoinToClaim;
holderClaimed[msg.sender][rewardIDonClaim] = true;
totalStableCoinDistribute += stableCoinToClaim;
stableCoinEarned[msg.sender] += stableCoinToClaim;
stableCoinEarnedByAbleReward[msg.sender] += stableCoinToClaim;
_updateALL(msg.sender);
// Emit events
emit ClaimBUSD(block.timestamp, stableCoinToClaim, msg.sender);
}
function claimSaver() public {
_updateALL(msg.sender);
require((_totalSupply + donationBalance[msg.sender]) < maxSupply);
require(
canReclaimSaver(msg.sender),
"You are not qualified to claim SAVER."
);
// Nueva version
require(
cycleToSaverReward[msg.sender] < cycle,
"You have to wait 30 days to claim your SAVER."
);
// Emit events
emit ClaimAble(
block.timestamp,
donationBalance[msg.sender],
msg.sender
);
_mint(msg.sender, donationBalance[msg.sender]);
isListedToClaimSaver[msg.sender] = false;
if (!winSaverReward[msg.sender]) {
address[] storage winners = wallet_winners;
winners.push(msg.sender);
wallet_winners = winners;
}
winSaverReward[msg.sender] = true;
winsSaverRewardOf[msg.sender]++;
totalWinsSaverReward++;
balanceOfWins_SaverReward[msg.sender]++;
total_saver_distributed += donationBalance[msg.sender];
total_saver_earned_of[msg.sender] += donationBalance[msg.sender];
stableCoinEarnedByAbleReward[msg.sender] = 0;
updateTimestampRewards();
}
// Video
function uploadVideoAndFirstQuestion(
string memory _youtubeID,
string memory _firstQuestion,
string memory _firstRealAnswer,
string memory _firstFakeAnswer1,
string memory _firstFakeAnswer2
) public {
require(
msg.sender == managementWallet ||
msg.sender == managementWallet2 ||
msg.sender == communityWallet,
"You are not qualified to call this function"
);
youtubeID[videoID] = _youtubeID;
firstQuestion[videoID] = _firstQuestion;
firstRealAnswer[videoID] = _firstRealAnswer;
firstFakeAnswer1[videoID] = _firstFakeAnswer1;
firstFakeAnswer2[videoID] = _firstFakeAnswer2;
videoID++;
}
function uploadSecondQuestion(
string memory _secondQuestion,
string memory _secondRealAnswer,
string memory _secondFakeAnswer1,
string memory _secondFakeAnswer2
) public {
require(
msg.sender == managementWallet ||
msg.sender == managementWallet2 ||
msg.sender == communityWallet,
"You are not qualified to call this function"
);
secondQuestion[videoID - 1] = _secondQuestion;
secondRealAnswer[videoID - 1] = _secondRealAnswer;
secondFakeAnswer1[videoID - 1] = _secondFakeAnswer1;
secondFakeAnswer2[videoID - 1] = _secondFakeAnswer2;
}
function uploadThirdQuestion(
string memory _thirdQuestion,
string memory _thirdRealAnswer,
string memory _thirdFakeAnswer1,
string memory _thirdFakeAnswer2
) public {
require(
msg.sender == managementWallet ||
msg.sender == managementWallet2 ||
msg.sender == communityWallet,
"You are not qualified to call this function"
);
thirdQuestion[videoID - 1] = _thirdQuestion;
thirdRealAnswer[videoID - 1] = _thirdRealAnswer;
thirdFakeAnswer1[videoID - 1] = _thirdFakeAnswer1;
thirdFakeAnswer2[videoID - 1] = _thirdFakeAnswer2;
}
function answerVideo(
string memory answer1,
string memory answer2,
string memory answer3,
uint256 _videoID
) public {
bool first = (keccak256(abi.encodePacked((answer1))) ==
keccak256(abi.encodePacked((firstRealAnswer[_videoID]))));
bool second = (keccak256(abi.encodePacked((answer2))) ==
keccak256(abi.encodePacked((secondRealAnswer[_videoID]))));
bool third = (keccak256(abi.encodePacked((answer3))) ==
keccak256(abi.encodePacked((thirdRealAnswer[_videoID]))));
videoAnswerOf[msg.sender][cycle] = first && second && third;
emit AnswerVideo(block.timestamp, first && second && third, msg.sender);
_updateALL(msg.sender);
}
function changeSorted() public {
require(
msg.sender == communityWallet ||
msg.sender == managementWallet ||
msg.sender == managementWallet2,
"You are not qualified to call this function"
);
sort = !sort;
}
function changeUSDC(address _newCoin, uint256 _decimals) public {
require(
msg.sender == communityWallet || msg.sender == devWallet,
"You are not able to call this function"
);
USDC = ERC20(_newCoin);
USDC_DECIMALS = _decimals;
}
function changeUSDT(address _newCoin, uint256 _decimals) public {
require(
msg.sender == communityWallet || msg.sender == devWallet,
"You are not able to call this function"
);
USDT = ERC20(_newCoin);
USDT_DECIMALS = _decimals;
}
function changeBUSD(address _newCoin, uint256 _decimals) public {
require(
msg.sender == communityWallet || msg.sender == devWallet,
"You are not able to call this function"
);
BUSD = ERC20(_newCoin);
BUSD_DECIMALS = _decimals;
}
function changeCommunityWallet(address newAddress) public {
require(
msg.sender == communityWallet,
"You are not qualified to call this function."
);
communityWallet = payable(newAddress);
}
function viewClaimStableCoin(address wallet) public view returns (uint256) {
if (qualifiedDonationBalance == 0 || !canReclaim(wallet)) return 0;
uint256 amount = ((rewardAmount[rewardIDonClaim] *
donationBalance[wallet]) / qualifiedDonationBalance);
uint256 amountClaimed = rewardAmountClaimed[rewardIDonClaim];
uint256 amountRaised = rewardAmount[rewardIDonClaim];
if (amountRaised < (amountClaimed + amount)) {
amount = (amountRaised - amountClaimed);
}
if (amount > (donationBalance[wallet] * POTENCIAL))
return donationBalance[wallet] * POTENCIAL;
return amount;
}
function qualifiedForBDD(address wallet) public view returns (bool) {
return (donationBalance[wallet] >= minAmountToQualify);
}
function qualifiedForSAVER(address wallet) public view returns (bool) {
return (_balances[wallet] > donationBalance[wallet]);
}
function qualifiedForUSDT(address wallet) public view returns (bool) {
return (getBalanceOfUSDT(wallet) > donationBalance[wallet]);
}
function qualifiedForUSDC(address wallet) public view returns (bool) {
return (getBalanceOfUSDC(wallet) > donationBalance[wallet]);
}
function qualifiedForDonatePerDay(
address wallet
) public view returns (bool) {
if (donationBalance[wallet] == 0) return false;
if (cycle > 1) {
return (donationBalancePerCycle[wallet][cycle - 1] >=
getZeroPointNinePercent(
donationBalancePerCycle[wallet][cycle - 2]
));
}
return true;
}
function getSavingsLimit(address wallet) public view returns (uint256) {
return ((usdcRecord[wallet][cycle - 1] * 100369) / 100000);
}
function getZeroPointNinePercent(
uint256 amount
) public pure returns (uint256) {
return (amount * 1009) / 1000;
}
function qualifiedForVideo(address wallet) public view returns (bool) {
return videoAnswerOf[wallet][cycle - 1];
}
function getMinAmountToDonate(
address wallet
) public view returns (uint256) {
if (
getZeroPointNinePercent(
donationBalancePerCycle[wallet][cycle - 1]
) > donationBalance[wallet]
) {
return
getZeroPointNinePercent(
donationBalancePerCycle[wallet][cycle - 1]
) - donationBalance[wallet];
}
return 0;
}
function qualifiedForSinergy(address wallet) public view returns (bool) {
bool bronze = false;
bool silver = false;
bool gold = false;
if (SinergyBronze != ERC721(address(0))) {
bronze = SinergyBronze.balanceOf(wallet) > 0;
}
if (SinergySilver != ERC721(address(0))) {
silver = SinergySilver.balanceOf(wallet) > 0;
}
if (SinergyGold != ERC721(address(0))) {
gold = SinergyGold.balanceOf(wallet) > 0;
}
return (bronze || silver || gold);
}
function canReclaim(address wallet) public view returns (bool) {
if (wallet == communityWallet || wallet == devWallet) return true;
return (qualifiedSinergy[wallet][cycle - 1] &&
qualifiedUSDT[wallet][cycle - 1] &&
qualifiedUSDC[wallet][cycle - 1] &&
qualifiedSaver[wallet][cycle - 1] &&
qualifiedBDD[wallet][cycle - 1] &&
qualifiedDonatedPerDay[wallet][cycle - 1] &&
qualifiedVideo[wallet][cycle - 1]);
}
function canReclaimSaver(address wallet) public view returns (bool) {
return (canReclaim(wallet) && isListedToClaimSaver[wallet]);
}
// Esta funcion la agregamos porque fallaba el premio able (28-10-2022)
// Pero luego nos dimos cuenta que estaba bien
function canReclaimAble(address wallet) public view returns (bool) {
bool res = true;
if (cycle < CYCLES_FOR_SAVER_REWARD) return false;
for (uint256 i = cycle - CYCLES_FOR_SAVER_REWARD; i < cycle; i++) {
res = res && qualifiedHistory[wallet][i];
}
return res;
}
/*
Si los decimales son distintos a 18, entonces para tratar a todos los tokens con 18 decimales retornamos
el balance que dice el contrato del token multiplicado por 10 elevado a la diferencia de 18 y los decimales
de ese token.
Por ejemplo: USDC (6 Decimales)
Como sus decimales son distintos a 18, hara lo siguiente. El balance que retorne el contrato de USDC en
6 decimales le agregara 12 decimales mas. (18 - DECIMALS).
Para asi finalmente tratarlo como un token de 18 decimales.
*/
function getBalanceOfUSDC(address wallet) public view returns (uint256) {
if (USDC_DECIMALS == 18) {
return USDC.balanceOf(wallet);
}
return USDC.balanceOf(wallet) * 10 ** (18 - USDC_DECIMALS);
}
function getBalanceOfUSDT(address wallet) public view returns (uint256) {
if (USDT_DECIMALS == 18) {
return USDT.balanceOf(wallet);
}
return USDT.balanceOf(wallet) * 10 ** (18 - USDT_DECIMALS);
}
function getBalanceOfBUSD(address wallet) public view returns (uint256) {
if (BUSD_DECIMALS == 18) {
return BUSD.balanceOf(wallet);
}
return BUSD.balanceOf(wallet) * 10 ** (18 - BUSD_DECIMALS);
}
function updateTimestampRewards() public {
if (block.timestamp > timeOpenClaimReward[rewardID]) {
// If someone forgot to claim, this reward will appear on the next reward
rewardAmount[rewardID] += (rewardAmount[rewardIDonClaim] -
rewardAmountClaimed[rewardIDonClaim]);
cycle++;
emit CycleChange(block.timestamp, cycle);
rewardIDonClaim = rewardID;
rewardID++;
// Update times to claim
timeOpenClaimReward[rewardID] =
block.timestamp +
timeStableCoinReward;
}
}
function updateALL(address wallet) public {
updateTimestampRewards();
updateSavings(wallet);
updateQualifiedDonationBalance(wallet);
checkDay(wallet);
checkSaverReward(wallet);
if (SinergyBronze != ERC721(address(0))) {
SinergyBronze.updateFromAble();
}
if (SinergySilver != ERC721(address(0))) {
SinergySilver.updateFromAble();
}
if (SinergyGold != ERC721(address(0))) {
SinergyGold.updateFromAble();
}
emit Update(block.timestamp, wallet);
}
function _updateALL(address wallet) private {
updateTimestampRewards();
updateSavings(wallet);
updateQualifiedDonationBalance(wallet);
checkDay(wallet);
checkSaverReward(wallet);
if (SinergyBronze != ERC721(address(0))) {
SinergyBronze.updateFromAble();
}
if (SinergySilver != ERC721(address(0))) {
SinergySilver.updateFromAble();
}
if (SinergyGold != ERC721(address(0))) {
SinergyGold.updateFromAble();
}
}
function updateFromSinergy(address wallet) public {
updateTimestampRewards();
updateSavings(wallet);
updateQualifiedDonationBalance(wallet);
checkDay(wallet);
checkSaverReward(wallet);
}
function setPersonalPurpose(string memory _str) public {
personalPurpose[msg.sender] = _str;
}
function setCommunityPurpose(string memory _str) public {
communityPurpose[msg.sender] = _str;
}
function withdrawAllFunds() public {
require(
(block.timestamp - lastDonationTimestamp) > 1 days,
"The contract is still working"
);
require(
msg.sender == communityWallet,
"You are not qualified to call to this function"
);
require(
BUSD.transfer(msg.sender, address(this).balance),
"Cannot pay StableCoin"
);
}
function setManagementInfo(string memory info) public {
require(
msg.sender == managementWallet || msg.sender == communityWallet,
"You are not qualified to call this function"
);
managementInfo = info;
}
function changeManagementWallet(address _managementWallet) public {
require(
msg.sender == communityWallet,
"You are not qualified to call this function"
);
managementWallet = _managementWallet;
}
function changeManagementWallet2(address _managementWallet) public {
require(
msg.sender == communityWallet,
"You are not qualified to call this function"
);
managementWallet2 = _managementWallet;
}
function set_potencial(uint256 _potencial) public {
require(
msg.sender == communityWallet || msg.sender == devWallet,
"You are not qualified to call this function."
);
POTENCIAL = _potencial;
}
function setSinergyBronze(address _sinergyBronze) public {
require(
msg.sender == devWallet,
"You are not qualified to call this function"
);
SinergyBronze = ERC721(_sinergyBronze);
}
function setSinergySilver(address _sinergySilver) public {
require(
msg.sender == devWallet,
"You are not qualified to call this function"
);
SinergySilver = ERC721(_sinergySilver);
}
function setSinergyGold(address _sinergyGold) public {
require(
msg.sender == devWallet,
"You are not qualified to call this function"
);
SinergyGold = ERC721(_sinergyGold);
}
function setSinergySell(SinergySale _ableSale) public {
require(msg.sender == devWallet);
ABLE_SALE = _ableSale;
}
// Private funcs
function updateQualifiedDonationBalanceAfterDonate(
address wallet,
uint256 amount
) private {
bool previousStatus = isQualified[wallet];
if (isQualified[wallet]) {
qualifiedDonationBalance -= donationBalance[wallet];
isQualified[wallet] = false;
total_qualified_wallets--;
qualifiedHolders--;
}
if (donationBalance[wallet] == 0) {
wallets_with_donation_balance++;
}
donationBalance[wallet] += amount;
totalDonationBalance += amount;
if (canReclaim(wallet)) {
qualifiedDonationBalance += donationBalance[wallet];
isQualified[wallet] = true;
total_qualified_wallets++;
qualifiedHolders++;
}
if (previousStatus != isQualified[wallet]) {
emit UserQualification(block.timestamp, wallet, !previousStatus);
}
}
function updateQualifiedDonationBalance(address wallet) private {
bool previousStatus = isQualified[wallet];
if (isQualified[wallet]) {
qualifiedDonationBalance -= donationBalance[wallet];
isQualified[wallet] = false;
total_qualified_wallets--;
qualifiedHolders--;
}
if (canReclaim(wallet)) {
qualifiedDonationBalance += donationBalance[wallet];
isQualified[wallet] = true;
total_qualified_wallets++;
qualifiedHolders++;
}
if (previousStatus != isQualified[wallet]) {
emit UserQualification(block.timestamp, wallet, !previousStatus);
}
}
function updateSavings(address wallet) private {
uint256 last_saving_amount = lastAmountUSDC[wallet] +
lastAmountUSDT[wallet];
uint256 actual_saving_amount = getBalanceOfUSDC(wallet) +
getBalanceOfUSDT(wallet);
if (actual_saving_amount < last_saving_amount) {
uint256 dif = last_saving_amount - actual_saving_amount;
if (dif > donationBalance[wallet]) {
reduceDonationBalance(wallet, donationBalance[wallet]);
} else {
reduceDonationBalance(wallet, dif);
}
}
}
function checkSaverReward(address wallet) private {
if (!canReclaim(wallet) && isListedToClaimSaver[wallet]) {
isListedToClaimSaver[wallet] = false;
emit AbleRewardQualification(block.timestamp, wallet, false);
return;
}
if (canReclaim(wallet) && !isListedToClaimSaver[wallet]) {
isListedToClaimSaver[wallet] = true;
cycleToSaverReward[wallet] = cycle + CYCLES_FOR_SAVER_REWARD;
emit AbleRewardQualification(block.timestamp, wallet, true);
return;
}
}
// antes llamada checkDonatedByDay
function checkDay(address wallet) private {
if (cycle >= cycleToCheck[wallet]) {
cycleToCheck[wallet] = cycle + 1;
lastAmountUSDC[wallet] = getBalanceOfUSDC(wallet);
lastAmountUSDT[wallet] = getBalanceOfUSDT(wallet);
usdcRecord[wallet][cycle] = lastAmountUSDC[wallet];
usdtRecord[wallet][cycle] = lastAmountUSDT[wallet];
donationBalancePerCycle[wallet][cycle - 1] = donationBalance[
msg.sender
];
qualifiedSinergy[wallet][cycle - 1] = qualifiedForSinergy(wallet);
qualifiedSaver[wallet][cycle - 1] = qualifiedForSAVER(wallet);
qualifiedUSDT[wallet][cycle - 1] = qualifiedForUSDT(wallet);
qualifiedUSDC[wallet][cycle - 1] = qualifiedForUSDC(wallet);
qualifiedBDD[wallet][cycle - 1] = qualifiedForBDD(wallet);
qualifiedDonatedPerDay[wallet][
cycle - 1
] = qualifiedForDonatePerDay(wallet);
qualifiedVideo[wallet][cycle - 1] = qualifiedForVideo(wallet);
qualifiedHistory[wallet][cycle - 1] = canReclaim(wallet);
emit CloseCycle(
wallet,
cycle - 1,
qualifiedSinergy[wallet][cycle - 1],
qualifiedUSDT[wallet][cycle - 1],
qualifiedUSDC[wallet][cycle - 1],
qualifiedSaver[wallet][cycle - 1],
qualifiedBDD[wallet][cycle - 1],
qualifiedDonatedPerDay[wallet][cycle - 1],
qualifiedVideo[wallet][cycle - 1]
);
}
}
// Esta nueva funcion la tiene que llamar SinergySale cada vez que alguien compra ABLE
function incrementDonationBalance(
uint256 amount_spended,
address wallet
) public {
require(msg.sender == address(ABLE_SALE));
updateQualifiedDonationBalanceAfterDonate(wallet, amount_spended);
_updateALL(wallet);
if (canReclaim(wallet)) {
lastDonationFrom = msg.sender;
}
rewardAmount[rewardID] += (amount_spended / 3);
allDonatesOf[wallet] += amount_spended;
donatedByDayOf[wallet][cycle] += amount_spended;
claimFrom[wallet] = rewardID;
totalDonations++;
total_raised_for_admin += (amount_spended / 3);
lastDonationTimestamp = block.timestamp;
// Emit Event
emit Points(wallet, cycle, amount_spended, true);
}
function reduceDonationBalance(address wallet, uint256 amount) private {
bool previousStatus = isQualified[wallet];
if (isQualified[wallet]) {
qualifiedDonationBalance -= donationBalance[wallet];
isQualified[wallet] = false;
total_qualified_wallets--;
qualifiedHolders--;
}
donationBalance[wallet] -= amount;
totalDonationBalance -= amount;
if (donationBalance[wallet] == 0) {
wallets_with_donation_balance--;
}
if (canReclaim(wallet)) {
qualifiedDonationBalance += donationBalance[wallet];
isQualified[wallet] = true;
total_qualified_wallets++;
qualifiedHolders++;
}
if (previousStatus != isQualified[wallet]) {
emit UserQualification(block.timestamp, wallet, !previousStatus);
}
// Emit Event
emit Points(wallet, cycle, amount, false);
}
// Funcs Private view
// Funcs IERC20
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(
address account
) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(
address to,
uint256 amount
) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(
address owner,
address spender
) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(
address spender,
uint256 amount
) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
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;
}
function increaseAllowance(
address spender,
uint256 addedValue
) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(
address spender,
uint256 subtractedValue
) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(
currentAllowance >= subtractedValue,
"ERC20: decreased allowance below zero"
);
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
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);
if (!isHolder[to]) {
totalHolders++;
isHolder[to] = true;
}
uint256 fromBalance = _balances[from];
require(
fromBalance >= amount,
"ERC20: transfer amount exceeds balance"
);
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
if (_balances[from] == 0) {
totalHolders--;
isHolder[from] = false;
}
_updateALL(from);
_updateALL(to);
updateQualifiedDonationBalance(from);
updateQualifiedDonationBalance(to);
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
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;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
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;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
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);
}
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);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
contract SinergySale {
// Constants
uint256 public constant TIME_OF_CYCLE = 6 minutes;
uint256 public MAX_AMOUNT_SELL_TOKEN = 90 ether;
uint256 public MIN_AMOUNT_SELL_TOKEN = 9 ether;
uint256 public TOKEN_PRICE = 3;
uint256 public LIMIT_POST_BY_CYCLE = 1;
// Global Variables
uint256 public TOTAL_TOKENS_SOLD;
mapping(uint256 => uint256) public tokens_sold_by_cycle;
// ERC20 Contracts
ERC20 public ABLE;
ERC20 public TOKEN;
ERC20 public BUSD;
// ERC721 Contract
Sinergy public SinergyContract =
Sinergy(0x508c132EE7cBb4A666E661634F85B59158eaDB4B);
// Wallets
address payable public communityWallet =
payable(0xc8895f6f85D870589C42fd6d531c855bddD27B0f);
address public dev_wallet = 0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
// Sell List
uint256[] public sell_list;
mapping(uint256 => bool) public is_in_sell_list;
mapping(address => uint256) public timestamp_last_post_sell;
mapping(address => uint256) public amount_of_post_of;
// Driven List
uint256[] public driven_list;
mapping(uint256 => bool) public is_in_driven_list;
mapping(address => uint256) public turns_in_driven_list_of;
// Turn of pick
uint256 public turn; // 0 y 1 => Driven List ||| 2 => Sell List
// Amount on Sell
uint256 public total_selling_amount;
mapping(uint256 => uint256) public selling_amount_of;
mapping(address => uint256) public post_count_of;
// User Data
mapping(address => uint256) public amount_sold_of;
// Events
event SellList(uint256 indexed nft_id, bool comeIn, bool driven);
event SellToken(
uint256 indexed nft_id,
address indexed buyer,
address indexed seller,
uint256 amount
);
event SwapList(uint256 indexed nft_id);
event BackToQueue(uint256 indexed nft_id, uint256 posAnt, uint256 posAct);
// Constructor
constructor(ERC20 _able, ERC20 _busd, ERC20 _token) {
ABLE = _able;
TOKEN = _token;
BUSD = _busd;
}
// Public Methods
function sell(uint256 _amount, uint256 _tokenID) public {
require(
_amount >= MIN_AMOUNT_SELL_TOKEN,
"The amount to sell have to be more or equal than 9 and less or equal than 90."
);
require(
(selling_amount_of[_tokenID] + _amount) <= MAX_AMOUNT_SELL_TOKEN,
"The amount to sell have to be more or equal than 9 and less or equal than 90."
);
require(
SinergyContract.ownerOf(_tokenID) == msg.sender,
"You are not the owner of this NFT."
);
require(
!is_selling(_tokenID),
"You are already selling tokens on SinergySell"
);
require(
TOKEN.transferFrom(msg.sender, address(this), _amount),
"Transfer fails."
);
require(
block.timestamp > timestamp_last_post_sell[msg.sender],
"You have to wait to post another sell."
);
selling_amount_of[_tokenID] += _amount;
total_selling_amount += _amount;
timestamp_last_post_sell[msg.sender] = block.timestamp + TIME_OF_CYCLE;
if (can_be_in_driven_list(msg.sender)) {
set_nft_to_driven_list(_tokenID);
turns_in_driven_list_of[msg.sender]++;
} else {
set_nft_to_sell_list(_tokenID);
}
}
function buy(uint256 _amount, bool incrementBDD) public {
require(_amount <= total_selling_amount);
// Transferimos los BUSD a este contrato
BUSD.transferFrom(msg.sender, address(this), _amount * TOKEN_PRICE);
// El 33% que va para el vendedor de los tokens, se envian directamente a la billetera del vendedor.
// Esto se hace en la funcion sell_able_from_list
// Transferimos 33% para el Admin
BUSD.transfer(communityWallet, ((_amount * TOKEN_PRICE) / 3));
// Transferimos 33% para Able, para que lo otorgue en el regalo diario de Able.
BUSD.transfer(address(ABLE), ((_amount * TOKEN_PRICE) / 3));
// Transferimos los TOKEN al usuario
TOKEN.transfer(msg.sender, _amount);
// Buscamos los vendedores
uint256 nfts_to_remove_sell;
uint256 nfts_to_remove_driven;
(nfts_to_remove_sell, nfts_to_remove_driven) = find_sellers(
_amount,
msg.sender
);
// Eliminamos de la lista, los vendedores que vendieron el total de su capital.
for (uint256 i = 0; i < nfts_to_remove_sell; i++) {
remove_first_nft_from_sell_list();
}
for (uint256 i = 0; i < nfts_to_remove_driven; i++) {
remove_first_nft_from_driven_list();
}
// Aumentamos el BDD de esta billetera en ABLE
if (incrementBDD)
ABLE.incrementDonationBalance(_amount * TOKEN_PRICE, msg.sender);
// Aumentamos la cantidad de tokens vendidos.
TOTAL_TOKENS_SOLD += _amount;
tokens_sold_by_cycle[ABLE.cycle()] += _amount;
}
function quit_sell(uint256 tokenID) public {
require(is_selling(tokenID));
require(SinergyContract.ownerOf(tokenID) == msg.sender);
require(selling_amount_of[tokenID] > 0);
require(total_selling_amount >= selling_amount_of[tokenID]);
require(TOKEN.transfer(msg.sender, selling_amount_of[tokenID]));
// Descontamos el monto que se saca de la venta
total_selling_amount -= selling_amount_of[tokenID];
selling_amount_of[tokenID] = 0;
// Sacamos al NFT de la Lista de Venta TOKEN
if (is_in_sell_list[tokenID]) {
remove_nft_from_sell_list(get_index_of_nft_from_sell_list(tokenID));
} else {
remove_nft_from_driven_list(
get_index_of_nft_from_driven_list(tokenID)
);
}
}
// Check Methods
function check_sell_list() public {
// Chequeamos si algun NFT de la Lista de Venta de Able esta descalificado.
for (uint256 i = 0; i < sell_list.length; i++) {
uint256 nft_id = sell_list[i];
if (!SinergyContract.nft_was_qualified(nft_id)) {
// Traemos todos los NFTs que habia detras una posicion mas adelante
for (uint256 j = i; j < sell_list.length - 1; j++) {
sell_list[j] = sell_list[j + 1];
}
// Posicionamos al NFT sancionado en el ultimo lugar de la cola
sell_list[sell_list.length - 1] = nft_id;
emit BackToQueue(nft_id, i, sell_list.length - 1);
}
}
}
function check_driven_list() public {
// Chequeamos si algun NFT de la Lista de Venta de Able esta descalificado.
for (uint256 i = 0; i < driven_list.length; i++) {
uint256 nft_id = driven_list[i];
if (!SinergyContract.nft_was_qualified(nft_id)) {
// Traemos todos los NFTs que habia detras una posicion mas adelante
for (uint256 j = i; j < driven_list.length - 1; j++) {
driven_list[j] = sell_list[j + 1];
}
// Posicionamos al NFT sancionado en el ultimo lugar de la cola
driven_list[driven_list.length - 1] = nft_id;
emit BackToQueue(nft_id, i, driven_list.length - 1);
}
}
}
// Get Methods
function get_sell_list_length() public view returns (uint256) {
return sell_list.length;
}
function get_driven_list_length() public view returns (uint256) {
return driven_list.length;
}
// Communication
function try_to_swap(uint256 _tokenID) public {
require(
msg.sender == address(SinergyContract),
"Only SinergyContract can call to this function."
);
if (
is_selling(_tokenID) &&
is_in_sell_list[_tokenID] &&
(get_index_of_nft_from_sell_list(_tokenID) > driven_list.length)
) {
remove_nft_from_sell_list(
get_index_of_nft_from_sell_list(_tokenID)
);
set_nft_to_driven_list(_tokenID);
emit SwapList(_tokenID);
}
}
function set_sinergy(address _sinergyContract) public {
require(
msg.sender == dev_wallet,
"You are not qualified to call this function."
);
SinergyContract = Sinergy(_sinergyContract);
}
function set_limit_post_by_cycle(uint256 new_limit) public {
require(
msg.sender == communityWallet || msg.sender == dev_wallet,
"You are not qualified to call this function."
);
LIMIT_POST_BY_CYCLE = new_limit;
}
function set_values_of_sale(
uint256 max_amount,
uint256 min_amount,
uint256 price
) public {
/*
Ninguno de los parametros tienen que estar en WEI.
Tienen que estar directamente en Ether.
*/
require(
msg.sender == dev_wallet || msg.sender == communityWallet,
"You are not qualified to call this function"
);
MAX_AMOUNT_SELL_TOKEN = max_amount * 1 ether;
MIN_AMOUNT_SELL_TOKEN = min_amount * 1 ether;
TOKEN_PRICE = price;
}
// Helpers
function is_selling(uint256 _tokenID) public view returns (bool) {
return is_in_sell_list[_tokenID] || is_in_driven_list[_tokenID];
}
// Sell Helpers
function is_sell_turn() public view returns (bool) {
return (turn == 2);
}
function sell_list_is_empty() public view returns (bool) {
return sell_list.length == 0;
}
function can_use_sell() public view returns (bool) {
return (!sell_list_is_empty() &&
(is_sell_turn() || driven_list_is_empty()));
}
// Driven Helpers
function can_be_in_driven_list(address wallet) public view returns (bool) {
return
ABLE.winSaverReward(wallet) &&
ABLE.winsSaverRewardOf(wallet) > turns_in_driven_list_of[wallet];
}
function is_driven_turn() public view returns (bool) {
return turn == 0 || turn == 1;
}
function driven_list_is_empty() public view returns (bool) {
return driven_list.length == 0;
}
function can_use_driven() public view returns (bool) {
return (!driven_list_is_empty() &&
(is_driven_turn() || sell_list_is_empty()));
}
// Private Methods
function set_nft_to_sell_list(uint256 _tokenID) private {
sell_list.push(_tokenID);
is_in_sell_list[_tokenID] = true;
emit SellList(_tokenID, true, false);
}
function set_nft_to_driven_list(uint256 _tokenID) private {
driven_list.push(_tokenID);
is_in_driven_list[_tokenID] = true;
emit SellList(_tokenID, true, true);
}
function remove_first_nft_from_sell_list() private {
require(sell_list.length > 0);
uint256 nft_id = sell_list[0];
for (uint256 i = 0; i < sell_list.length - 1; i++) {
sell_list[i] = sell_list[i + 1];
}
sell_list.pop();
is_in_sell_list[nft_id] = false;
emit SellList(nft_id, false, false);
}
function remove_first_nft_from_driven_list() private {
require(driven_list.length > 0);
uint256 nft_id = driven_list[0];
for (uint256 i = 0; i < driven_list.length - 1; i++) {
driven_list[i] = driven_list[i + 1];
}
driven_list.pop();
is_in_driven_list[nft_id] = false;
emit SellList(nft_id, false, true);
}
function remove_nft_from_sell_list(uint256 idx) private {
require(sell_list.length > idx);
uint256 nft_id = sell_list[idx];
for (uint256 i = idx; i < sell_list.length - 1; i++) {
sell_list[i] = sell_list[i + 1];
}
sell_list.pop();
is_in_sell_list[nft_id] = false;
emit SellList(nft_id, false, false);
}
function remove_nft_from_driven_list(uint256 idx) private {
require(driven_list.length > idx);
uint256 nft_id = driven_list[idx];
for (uint256 i = idx; i < driven_list.length - 1; i++) {
driven_list[i] = driven_list[i + 1];
}
driven_list.pop();
is_in_driven_list[nft_id] = false;
emit SellList(nft_id, false, true);
}
function can_sell(address wallet) private returns (bool) {
if (block.timestamp > timestamp_last_post_sell[wallet]) {
post_count_of[wallet] = 0;
return true;
}
if (post_count_of[wallet] < LIMIT_POST_BY_CYCLE) {
post_count_of[wallet]++;
return true;
}
return false;
}
function get_index_of_nft_from_sell_list(
uint256 tokenID
) private view returns (uint256) {
for (uint256 i = 0; i < sell_list.length; i++) {
if (sell_list[i] == tokenID) {
return i;
}
}
return sell_list.length + 1;
}
function get_index_of_nft_from_driven_list(
uint256 tokenID
) private view returns (uint256) {
for (uint256 i = 0; i < driven_list.length; i++) {
if (driven_list[i] == tokenID) {
return i;
}
}
return driven_list.length + 1;
}
function sell_able_from_list(
uint256 _amount,
uint256 _tokenID,
address buyer
) private {
address owner = SinergyContract.ownerOf(_tokenID);
selling_amount_of[_tokenID] -= _amount;
total_selling_amount -= _amount;
// 33% van directo al usuario
BUSD.transfer(owner, ((_amount * TOKEN_PRICE) / 3));
amount_sold_of[owner] += ((_amount * TOKEN_PRICE) / 3);
emit SellToken(_tokenID, buyer, owner, _amount);
}
// Turn Helper
function increment_turn() private {
if (turn == 2) {
turn = 0;
} else {
turn++;
}
}
function find_sellers(
uint256 _amount,
address buyer
) private returns (uint256, uint256) {
bool sell_all = false;
uint256 nft_id;
uint256 idx_sell = 0;
uint256 nfts_to_remove_sell;
uint256 idx_driven = 0;
uint256 nfts_to_remove_driven;
while (!sell_all) {
// Driven List
while (
can_use_driven() && idx_driven < driven_list.length && !sell_all
) {
nft_id = driven_list[idx_driven];
if (_amount <= selling_amount_of[nft_id]) {
// Este NFT me da lo que necesito.
if (_amount == selling_amount_of[nft_id]) {
nfts_to_remove_driven++;
}
sell_able_from_list(_amount, nft_id, buyer);
sell_all = true;
} else {
// Este NFT me ayuda a alcanzar lo que necesito. No me es suficiente lo que me da.
_amount -= selling_amount_of[nft_id];
sell_able_from_list(
selling_amount_of[nft_id],
nft_id,
buyer
);
nfts_to_remove_driven++;
}
idx_driven++;
increment_turn();
}
// Sell List
while (can_use_sell() && idx_sell < sell_list.length && !sell_all) {
nft_id = sell_list[idx_sell];
if (_amount <= selling_amount_of[nft_id]) {
// Este NFT me da lo que necesito.
if (_amount == selling_amount_of[nft_id]) {
nfts_to_remove_sell++;
}
sell_able_from_list(_amount, nft_id, buyer);
sell_all = true;
} else {
// Este NFT me ayuda a alcanzar lo que necesito. No me es suficiente lo que me da.
_amount -= selling_amount_of[nft_id];
sell_able_from_list(
selling_amount_of[nft_id],
nft_id,
buyer
);
nfts_to_remove_sell++;
}
idx_sell++;
increment_turn();
}
}
return (nfts_to_remove_sell, nfts_to_remove_driven);
}
}
contract Reward {
// Contracts
ERC20 public ABLE = ERC20(0x68627b19b01C497749328e160e17a168D7719956);
ERC20 public TOKEN = ERC20(0x68627b19b01C497749328e160e17a168D7719956);
SinergySale public ABLE_SALE =
SinergySale(0xD42058180A985DEe1b52aEAEa5573D069D87Dc94);
Sinergy public SinergyContract =
Sinergy(0x508c132EE7cBb4A666E661634F85B59158eaDB4B);
// Wallets
address public developmentWallet =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
// Attributes
uint256 public TIME = 6 minutes;
uint256 public reward_id;
uint256 public AMOUNT_USERS_NEED_TO_CLAIM = 3;
mapping(uint256 => uint256) public reward;
mapping(uint256 => uint256) public reward_claimed;
mapping(address => uint256) public timestamp_to_claim_reward;
event RewardClaimed(uint256 amount, address indexed wallet);
function set_reward(uint256 amount) public {
require(can_call(msg.sender));
reward[reward_id] += amount;
}
function claim_reward(bool passive) public {
require(
can_claim(msg.sender, passive),
"You are not qualified to claim this reward."
);
uint256 amount = view_amount_to_claim(msg.sender, passive);
// Transferimos los tokens correspondientes
TOKEN.transfer(msg.sender, amount);
set_reward_claimed(msg.sender, amount);
emit RewardClaimed(amount, msg.sender);
}
function set_reward_claimed(address wallet, uint256 amount) private {
reward_claimed[reward_id - 1] += amount;
timestamp_to_claim_reward[wallet] = block.timestamp + TIME;
}
function view_amount_to_claim(
address wallet,
bool passive
) public view returns (uint256) {
if (reward_id == 0) return 0;
if (block.timestamp <= timestamp_to_claim_reward[wallet]) return 0;
uint256 user_amount = get_user_amount(wallet, passive);
uint256 total_amount = get_total_amount(passive);
if (user_amount == 0) return 0;
if (total_amount < user_amount) return 0;
if (user_amount > 9) user_amount = 9;
uint256 amount_to_claim = (user_amount * reward[reward_id - 1]) /
total_amount;
if (
amount_to_claim >
(reward[reward_id - 1] - reward_claimed[reward_id - 1])
) {
return (reward[reward_id - 1] - reward_claimed[reward_id - 1]);
}
return amount_to_claim;
}
function update() public {
require(can_call(msg.sender));
reward_id++;
if (reward[reward_id - 1] > reward_claimed[reward_id - 1]) {
reward[reward_id] += (reward[reward_id - 1] -
reward_claimed[reward_id - 1]);
}
}
function can_claim(
address wallet,
bool passive
) public view returns (bool) {
if (passive) {
return (reward_id > 0 &&
block.timestamp > timestamp_to_claim_reward[wallet] &&
ABLE.canReclaim(wallet));
}
return (reward_id > 0 &&
block.timestamp > timestamp_to_claim_reward[wallet] &&
ABLE.canReclaim(wallet) &&
ABLE.totalWinsSaverReward() >= AMOUNT_USERS_NEED_TO_CLAIM &&
ABLE.winsSaverRewardOf(wallet) > 0);
}
function set_contracts(
ERC20 _able,
ERC20 _token,
SinergySale _sinergySale,
Sinergy _sinergyContract
) public {
require(
msg.sender == developmentWallet,
"You are not qualified to call this function"
);
ABLE = _able;
TOKEN = _token;
ABLE_SALE = _sinergySale;
SinergyContract = _sinergyContract;
}
// Getters
function get_amount_raised() public view returns (uint256) {
if (reward_id == 0) return 0;
return reward[reward_id - 1];
}
function get_amount_claimed() public view returns (uint256) {
if (reward_id == 0) return 0;
return reward_claimed[reward_id - 1];
}
function can_call(address wallet) private view returns (bool) {
return
wallet == address(ABLE) ||
wallet == address(ABLE_SALE) ||
wallet == address(SinergyContract) ||
wallet == developmentWallet;
}
function get_user_amount(
address wallet,
bool passive
) private view returns (uint256) {
if (passive) {
return SinergyContract.balanceOf(wallet);
}
return ABLE.winsSaverRewardOf(wallet);
}
function get_total_amount(bool passive) private view returns (uint256) {
if (passive) {
return SinergyContract.nfts_qualified();
}
return ABLE.totalWinsSaverReward();
}
}
contract Migration {
// Constants
uint256 public constant AMOUNT_LIMIT_TO_MIGRATE = 21;
// Contracts
SinergyMigration ContractMigration =
SinergyMigration(0xEa063b5A744616a161272a013a626A1cBD80Ee1B);
Sinergy Contract = Sinergy(0x508c132EE7cBb4A666E661634F85B59158eaDB4B);
// ERC20
ERC20 public ABLE = ERC20(0x68627b19b01C497749328e160e17a168D7719956);
// Addresses
address public communityWallet = 0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
address public constant developmentWallet =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
// Migration
mapping(address => bool) public isRecover;
mapping(uint256 => bool) public nftRecover;
mapping(uint256 => bool) public first_level_references_recover;
mapping(uint256 => uint256) public first_level_references_recover_amount;
mapping(uint256 => bool) public second_level_references_recover;
mapping(uint256 => uint256) public second_level_references_recover_amount;
mapping(uint256 => bool) public third_level_references_recover;
mapping(uint256 => uint256) public third_level_references_recover_amount;
mapping(uint256 => bool) public four_level_references_recover;
mapping(uint256 => uint256) public four_level_references_recover_amount;
mapping(uint256 => bool) public five_level_references_recover;
mapping(uint256 => uint256) public five_level_references_recover_amount;
mapping(uint256 => bool) public six_level_references_recover;
mapping(uint256 => uint256) public six_level_references_recover_amount;
mapping(uint256 => bool) public seven_level_references_recover;
mapping(uint256 => uint256) public seven_level_references_recover_amount;
mapping(uint256 => bool) public eight_level_references_recover;
mapping(uint256 => uint256) public eight_level_references_recover_amount;
mapping(uint256 => bool) public nine_level_references_recover;
mapping(uint256 => uint256) public nine_level_references_recover_amount;
mapping(address => uint256) public nfts_migrated;
uint256 public starting_nft_id;
uint256[] public recovered_nfts;
uint256 public recovered_nfts_amount;
constructor() {
isRecover[developmentWallet] = true;
}
// Main recover
function migrate() public {
if (msg.sender == communityWallet && !isRecover[communityWallet]) {
Contract.create_genesis_nfts();
isRecover[communityWallet] = true;
handle_recover_nfts_amount_for_admin();
return;
}
if (!isRecover[msg.sender]) {
uint256 affiliate_rewards;
uint256 amount = ContractMigration.balanceOf(msg.sender);
uint256 migrated;
uint256 nftID;
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
nfts_migrated[msg.sender] < amount
) {
nftID = ContractMigration.get_my_nfts(
msg.sender,
nfts_migrated[msg.sender]
);
recovered_nfts.push(nftID);
Contract.handleRecover(msg.sender, nftID);
nftRecover[nftID] = true;
recovered_nfts_amount++;
affiliate_rewards += ContractMigration.get_nft_balance_to_claim(
nftID
);
nfts_migrated[msg.sender]++;
migrated++;
}
if (nfts_migrated[msg.sender] == amount) {
ABLE.transfer(msg.sender, affiliate_rewards);
isRecover[msg.sender] = true;
}
}
}
// Recover by level
function recoverFirstLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!first_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_first_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
first_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverFirstLevel(
nftID,
first_level_references_recover_amount[nftID]
);
migrated++;
first_level_references_recover_amount[nftID]++;
}
if (first_level_references_recover_amount[nftID] == amount) {
first_level_references_recover[nftID] = true;
}
}
function recoverSecondLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!second_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_second_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
second_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverSecondLevel(
nftID,
second_level_references_recover_amount[nftID]
);
migrated++;
second_level_references_recover_amount[nftID]++;
}
if (second_level_references_recover_amount[nftID] == amount) {
second_level_references_recover[nftID] = true;
}
}
function recoverThirdLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!third_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_third_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
third_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverThirdLevel(
nftID,
third_level_references_recover_amount[nftID]
);
migrated++;
third_level_references_recover_amount[nftID]++;
}
if (third_level_references_recover_amount[nftID] == amount) {
third_level_references_recover[nftID] = true;
}
}
function recoverFourLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!four_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_four_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
four_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverFourLevel(
nftID,
four_level_references_recover_amount[nftID]
);
migrated++;
four_level_references_recover_amount[nftID]++;
}
if (four_level_references_recover_amount[nftID] == amount) {
four_level_references_recover[nftID] = true;
}
}
function recoverFiveLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!five_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_five_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
five_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverFiveLevel(
nftID,
five_level_references_recover_amount[nftID]
);
migrated++;
five_level_references_recover_amount[nftID]++;
}
if (five_level_references_recover_amount[nftID] == amount) {
five_level_references_recover[nftID] = true;
}
}
function recoverSixLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!six_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_six_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
six_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverSixLevel(
nftID,
six_level_references_recover_amount[nftID]
);
migrated++;
six_level_references_recover_amount[nftID]++;
}
if (six_level_references_recover_amount[nftID] == amount) {
six_level_references_recover[nftID] = true;
}
}
function recoverSevenLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!seven_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_seven_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
seven_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverSevenLevel(
nftID,
seven_level_references_recover_amount[nftID]
);
migrated++;
seven_level_references_recover_amount[nftID]++;
}
if (seven_level_references_recover_amount[nftID] == amount) {
seven_level_references_recover[nftID] = true;
}
}
function recoverEightLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!eight_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_eight_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
eight_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverEightLevel(
nftID,
eight_level_references_recover_amount[nftID]
);
migrated++;
eight_level_references_recover_amount[nftID]++;
}
if (eight_level_references_recover_amount[nftID] == amount) {
eight_level_references_recover[nftID] = true;
}
}
function recoverNineLevelReferences(uint256 nftID) public {
require(
msg.sender == Contract.ownerOf(nftID) &&
!nine_level_references_recover[nftID]
);
uint256 migrated;
uint256 amount = ContractMigration.get_nine_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
nine_level_references_recover_amount[nftID] < amount
) {
Contract.handlerRecoverNineLevel(
nftID,
nine_level_references_recover_amount[nftID]
);
migrated++;
nine_level_references_recover_amount[nftID]++;
}
if (nine_level_references_recover_amount[nftID] == amount) {
nine_level_references_recover[nftID] = true;
}
}
// Helpers
function handle_recover_nfts_amount_for_admin() private {
for (uint8 i = 0; i < 9; i++) {
recovered_nfts.push(i);
recovered_nfts_amount++;
}
}
// Set Contracts
function set_sinergy(Sinergy _sinergyAddress) public {
if (msg.sender != developmentWallet) return;
Contract = Sinergy(_sinergyAddress);
}
function set_able(ERC20 _able) public {
if (msg.sender != developmentWallet) return;
ABLE = ERC20(_able);
}
}
// This is the main contract here!
contract Sinergy is ERC721, ERC721URIStorage, Ownable {
// Constants
uint256 public constant PRICE = 36 ether;
uint256 public constant ABLE_PRICE = 12 ether;
uint256 public constant REWARD = 3 ether;
uint256 public constant TO_DEVELOPMENT = 3 ether;
// NFT GENESIS
string constant NFT_GENESIS_NAME = "GENESIS";
string constant NFT_GENESIS_INSCRIPTION = "GENESIS INSCRIPTION";
string constant NFT_GENESIS_VALUE_PROPOSAL = "GENESIS VALUE PROPOSAL";
string constant NFT_GENESIS_IMAGE_URL =
"https://res.cloudinary.com/saver-community/image/upload/v1666380501/jvjbls4lg5mtxsxhlhnf.png";
// Migration
SinergyMigration ContractMigration =
SinergyMigration(0xEa063b5A744616a161272a013a626A1cBD80Ee1B);
Migration public MigrationContract =
Migration(0xfd26B8BE868C0E16A5a54E8D586B0C6D7d6892fA);
// ERC20's
ERC20 public ABLE = ERC20(0x0b85cCA1814eE40C6E83E3591F3819eC7e87d0A5);
ERC20 public BUSD = ERC20(0x765277EebeCA2e31912C9946eAe1021199B39C61);
// Able Sale
SinergySale public ABLE_SALE =
SinergySale(0x7fa46675165F0d0Ab1A3bd3FD96AA3eD59167B52);
// Passive Rewards
Reward public BUSD_PassiveReward =
Reward(0x4F19668690b3501fa2404039436d4f1C14079dB8);
Reward public ABLE_PassiveReward =
Reward(0x72e29bC0cF7E6f2A3FC99890069E857b736F6dE9);
// Constancy Rewards (usa el ID de las pasivas)
Reward public BUSD_ConstancyReward =
Reward(0x2B06dD06Cf7cdAB0f8cC39a6F79FD88b20cb2C5D);
Reward public ABLE_ConstancyReward =
Reward(0xc32AfBC61e4A2Be096cBe27Fa1072EA7f25Aa79d);
// Address
address public communityWallet = 0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
address public constant developmentWallet =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
uint256 public oneDay = 1 days;
uint256 public timeToNextReward;
// Counters
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 public starting_nft_id;
uint256 initial_tokenID = 1159;
// Constructor
constructor() ERC721("Offer Sinergy", "Sinergy") {
while (_tokenIds.current() < initial_tokenID) {
_tokenIds.increment();
}
// Mint NFT
uint256 tokenID = _tokenIds.current();
_tokenIds.increment();
_safeMint(developmentWallet, tokenID);
get_nft_name[tokenID] = NFT_GENESIS_NAME;
get_nft_inscription[tokenID] = NFT_GENESIS_INSCRIPTION;
get_nft_value_proposal[tokenID] = NFT_GENESIS_VALUE_PROPOSAL;
get_nft_image_url[tokenID] = NFT_GENESIS_IMAGE_URL;
get_nft_timestamp_created[tokenID] = block.timestamp;
favourite_nft[developmentWallet] = tokenID;
_setTokenURI(
tokenID,
"ipfs://QmRi1DvgDu6zAJwpbURGNBBQTM82ZCNZAyTkEArbKZKm1U/273.json"
);
get_my_nfts[developmentWallet].push(tokenID);
timeToNextReward = block.timestamp + oneDay;
starting_nft_id = initial_tokenID;
total_holders++;
is_holder[developmentWallet] = true;
}
// NFT's
uint256 public nfts_qualified;
mapping(address => bool) public is_qualified;
mapping(uint256 => string) public get_nft_name;
mapping(uint256 => string) public get_nft_inscription;
mapping(uint256 => string) public get_nft_value_proposal;
mapping(uint256 => uint256) public get_nft_timestamp_created;
mapping(uint256 => string) public get_nft_image_url;
// References
// Esto sabemos que va (Cantidad de NFTs que estan conectados conmigo en el NIVEL x)
mapping(uint256 => uint256) public get_first_level_amount_reference;
mapping(uint256 => uint256) public get_second_level_amount_reference;
mapping(uint256 => uint256) public get_third_level_amount_reference;
mapping(uint256 => uint256) public get_four_level_amount_reference;
mapping(uint256 => uint256) public get_five_level_amount_reference;
mapping(uint256 => uint256) public get_six_level_amount_reference;
mapping(uint256 => uint256) public get_seven_level_amount_reference;
mapping(uint256 => uint256) public get_eight_level_amount_reference;
mapping(uint256 => uint256) public get_nine_level_amount_reference;
mapping(uint256 => uint256) public get_total_amount_references; // Cantidad de NFTs que estan conectados conmigo en total.
// Esto puede fallar (NFT ID de cada uno que esta conectado con nosotros en el NIVEL x)
mapping(uint256 => uint256[]) public get_first_level_references;
mapping(uint256 => uint256[]) public get_second_level_references;
mapping(uint256 => uint256[]) public get_third_level_references;
mapping(uint256 => uint256[]) public get_four_level_references;
mapping(uint256 => uint256[]) public get_five_level_references;
mapping(uint256 => uint256[]) public get_six_level_references;
mapping(uint256 => uint256[]) public get_seven_level_references;
mapping(uint256 => uint256[]) public get_eight_level_references;
mapping(uint256 => uint256[]) public get_nine_level_references;
// NFT al que me conecte
mapping(uint256 => uint256) public get_nft_reference;
// Rewards
mapping(uint256 => uint256) public nft_affiliate_rewards_earned;
// Resources
uint256 public total_raided_for_admin;
// Stadistics
uint256 public total_stablecoin_distributed;
mapping(address => uint256) public total_stablecoin_earned;
mapping(address => uint256) public total_lost_income;
mapping(address => uint256) public actual_lost_income;
mapping(uint256 => uint256) public nfts_created_by_cycle;
// Holders
mapping(address => bool) public is_holder;
uint256 public total_holders;
// Auxs
mapping(address => uint256) public amount_nfts_considered;
// Events
event Mint(
uint256 id,
uint256 date,
string indexed name,
string indexed valueProposal,
address indexed wallet
);
event AffiliateRewardEvent(
uint256 tokenID,
uint256 amount,
address indexed wallet,
uint256 indexed date
);
event ChangeFavourite(
address indexed wallet,
uint256 previousFavourite,
uint256 actualFavourite
);
// Public Functions
// Migration
function set_migration_contract(Migration _migrationContract) public {
if (msg.sender != developmentWallet) return;
MigrationContract = _migrationContract;
}
function handleRecover(address wallet, uint256 tokenId) public {
if (msg.sender != address(MigrationContract)) return;
recoverNFT(tokenId);
get_my_nfts[wallet].push(tokenId);
_safeMint(wallet, tokenId);
if (favourite_nft[wallet] == 0) {
favourite_nft[wallet] = tokenId;
}
}
function recoverNFT(uint256 nftID) private {
// NFT Basic Info
get_nft_name[nftID] = ContractMigration.get_nft_name(nftID);
get_nft_inscription[nftID] = ContractMigration.get_nft_inscription(
nftID
);
get_nft_value_proposal[nftID] = ContractMigration
.get_nft_value_proposal(nftID);
get_nft_timestamp_created[nftID] = ContractMigration
.get_nft_timestamp_created(nftID);
get_nft_image_url[nftID] = ContractMigration.get_nft_image_url(nftID);
get_nft_reference[nftID] = ContractMigration.get_nft_reference(nftID);
// References
get_first_level_amount_reference[nftID] = ContractMigration
.get_first_level_amount_reference(nftID);
get_second_level_amount_reference[nftID] = ContractMigration
.get_second_level_amount_reference(nftID);
get_third_level_amount_reference[nftID] = ContractMigration
.get_third_level_amount_reference(nftID);
get_four_level_amount_reference[nftID] = ContractMigration
.get_four_level_amount_reference(nftID);
get_five_level_amount_reference[nftID] = ContractMigration
.get_five_level_amount_reference(nftID);
get_six_level_amount_reference[nftID] = ContractMigration
.get_six_level_amount_reference(nftID);
get_seven_level_amount_reference[nftID] = ContractMigration
.get_seven_level_amount_reference(nftID);
get_eight_level_amount_reference[nftID] = ContractMigration
.get_eight_level_amount_reference(nftID);
get_nine_level_amount_reference[nftID] = ContractMigration
.get_nine_level_amount_reference(nftID);
get_total_amount_references[nftID] = ContractMigration
.get_total_amount_references(nftID);
}
function handlerRecoverFirstLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_first_level_references[tokenId].push(
ContractMigration.get_first_level_references(tokenId, index)
);
}
function handlerRecoverSecondLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_second_level_references[tokenId].push(
ContractMigration.get_second_level_references(tokenId, index)
);
}
function handlerRecoverThirdLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_third_level_references[tokenId].push(
ContractMigration.get_third_level_references(tokenId, index)
);
}
function handlerRecoverFourLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_four_level_references[tokenId].push(
ContractMigration.get_four_level_references(tokenId, index)
);
}
function handlerRecoverFiveLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_five_level_references[tokenId].push(
ContractMigration.get_five_level_references(tokenId, index)
);
}
function handlerRecoverSixLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_six_level_references[tokenId].push(
ContractMigration.get_six_level_references(tokenId, index)
);
}
function handlerRecoverSevenLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_seven_level_references[tokenId].push(
ContractMigration.get_seven_level_references(tokenId, index)
);
}
function handlerRecoverEightLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_eight_level_references[tokenId].push(
ContractMigration.get_eight_level_references(tokenId, index)
);
}
function handlerRecoverNineLevel(uint256 tokenId, uint256 index) public {
if (msg.sender != address(MigrationContract)) return;
get_nine_level_references[tokenId].push(
ContractMigration.get_nine_level_references(tokenId, index)
);
}
// NFT
function createNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
string memory _uri,
string memory _imageURL,
uint256 _ref,
uint256 _timestamp
) public {
// Get Reference
uint256 _reference = favourite_nft[ABLE.lastDonationFrom()];
if (_ref != 0) {
_reference = _ref;
}
if (_reference == 0) {
_reference = 8;
}
require(_reference < _tokenIds.current());
BUSD.transferFrom(msg.sender, address(this), PRICE);
ABLE.transferFrom(msg.sender, address(this), ABLE_PRICE);
// Transferimos 3 BUSD para el admin
BUSD.transfer(communityWallet, TO_DEVELOPMENT);
update_qualified_nfts(msg.sender);
ABLE_SALE.try_to_swap(favourite_nft[msg.sender]);
// Mint NFT
uint256 tokenID = _tokenIds.current();
_tokenIds.increment();
_safeMint(msg.sender, tokenID);
// Set URI
_setTokenURI(tokenID, _uri);
// Add information to the NFT
get_nft_name[tokenID] = _name;
get_nft_inscription[tokenID] = _inscription;
get_nft_value_proposal[tokenID] = _valueProposal;
get_nft_reference[tokenID] = _reference;
get_nft_image_url[tokenID] = _imageURL;
get_nft_timestamp_created[tokenID] = _timestamp;
if (favourite_nft[msg.sender] == 0) {
favourite_nft[msg.sender] = tokenID;
}
// uint256[] storage myNFTS = get_my_nfts[msg.sender];
get_my_nfts[msg.sender].push(tokenID);
// get_my_nfts[msg.sender] = myNFTS;
// Increase the resources amount
total_raided_for_admin += TO_DEVELOPMENT;
// Increase Rewards
ABLE_PassiveReward.set_reward(6 ether);
ABLE.transfer(address(ABLE_PassiveReward), 6 ether);
BUSD_PassiveReward.set_reward(3 ether);
BUSD.transfer(address(BUSD_PassiveReward), 3 ether);
ABLE_ConstancyReward.set_reward(6 ether);
ABLE.transfer(address(ABLE_ConstancyReward), 6 ether);
BUSD_ConstancyReward.set_reward(3 ether);
BUSD.transfer(address(BUSD_ConstancyReward), 3 ether);
// Distribute BUSD's in 9 generations
distribute(tokenID, _reference, true);
update(msg.sender);
// Aumentamos la cantidad de NFTs creados en este ciclo
nfts_created_by_cycle[ABLE.cycle()]++;
// Holders
if (!is_holder[msg.sender]) {
is_holder[msg.sender] = true;
total_holders++;
}
// Emit event
emit Mint(tokenID, block.timestamp, _name, _valueProposal, msg.sender);
}
function modifyNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
uint256 _tokenID
) public {
require(msg.sender == ownerOf(_tokenID));
BUSD.transferFrom(msg.sender, address(this), PRICE);
ABLE.transferFrom(msg.sender, address(this), ABLE_PRICE);
// Transferimos 3 BUSD para el admin
BUSD.transfer(communityWallet, TO_DEVELOPMENT);
// Modify the NFT
get_nft_name[_tokenID] = _name;
get_nft_inscription[_tokenID] = _inscription;
get_nft_value_proposal[_tokenID] = _valueProposal;
// Increase the resources amount
total_raided_for_admin += TO_DEVELOPMENT;
// Increase Rewards
BUSD_PassiveReward.set_reward(3 ether);
BUSD.transfer(address(BUSD_PassiveReward), 3 ether);
ABLE_PassiveReward.set_reward(6 ether);
ABLE.transfer(address(ABLE_PassiveReward), 6 ether);
ABLE_ConstancyReward.set_reward(6 ether);
ABLE.transfer(address(ABLE_ConstancyReward), 6 ether);
BUSD_ConstancyReward.set_reward(3 ether);
BUSD.transfer(address(ABLE_ConstancyReward), 3 ether);
// Distribute BUSD in 9 generations
distribute(_tokenID, get_nft_reference[_tokenID], false);
update(msg.sender);
}
// Read functions
function getAmountOfNftMinted() public view returns (uint256) {
return _tokenIds.current();
}
// Set Functions
function setAbleAddress(address _ableAddress) public {
require(msg.sender == developmentWallet);
ABLE = ERC20(_ableAddress);
}
function setRewards(
Reward busd_passive,
Reward busd_constancy,
Reward able_passive,
Reward able_constancy
) public {
require(msg.sender == developmentWallet);
BUSD_PassiveReward = busd_passive;
BUSD_ConstancyReward = busd_constancy;
ABLE_PassiveReward = able_passive;
ABLE_ConstancyReward = able_constancy;
}
function setFavouriteNFT(address wallet, uint256 id) public {
require(id <= _tokenIds.current());
require(msg.sender == ownerOf(id) || msg.sender == address(MigrationContract), "Wallet not qualified to setFavouriteNFT");
uint256 previousFavourite = favourite_nft[wallet];
favourite_nft[wallet] = id;
emit ChangeFavourite(msg.sender, previousFavourite, id);
}
function changeCommunityWallet(address newAddress) public {
require(msg.sender == communityWallet);
communityWallet = newAddress;
}
// Booleans
function nft_was_qualified(uint256 tokenID) public view returns (bool) {
return
ABLE.canReclaim(ownerOf(tokenID)) ||
ABLE.qualifiedHistory(ownerOf(tokenID), ABLE.cycle() - 1);
}
// Update Functions
function update_qualified_nfts(address wallet) private {
if (is_qualified[wallet]) {
nfts_qualified -= amount_nfts_considered[wallet];
amount_nfts_considered[wallet] = 0;
is_qualified[wallet] = false;
}
if (ABLE.canReclaim(wallet)) {
nfts_qualified += balanceOf(wallet);
amount_nfts_considered[wallet] = balanceOf(wallet);
is_qualified[wallet] = true;
}
}
function update_timestamp() private {
if (block.timestamp > timeToNextReward) {
BUSD_PassiveReward.update();
ABLE_PassiveReward.update();
BUSD_ConstancyReward.update();
ABLE_ConstancyReward.update();
timeToNextReward = block.timestamp + oneDay;
}
}
function update(address wallet) public {
ABLE.updateFromSinergy(wallet);
update_timestamp();
update_qualified_nfts(wallet);
}
function updateFromAble(address wallet) public {
update_timestamp();
update_qualified_nfts(wallet);
}
function getAbleBalance(address wallet) public view returns (uint256) {
return ABLE.balanceOf(wallet);
}
// SaleToken Public Functions
function set_able_sale(SinergySale ableSale) public {
require(msg.sender == developmentWallet);
ABLE_SALE = ableSale;
}
// Private Functions
// Distribute 9 generations
function distribute(
uint256 tokenID,
uint256 _reference,
bool created
) private {
address owner;
uint256 i = 0;
while (i < 9) {
if (created) setReferences(i, tokenID, _reference);
owner = ownerOf(_reference);
total_stablecoin_earned[owner] += REWARD;
nft_affiliate_rewards_earned[_reference] += REWARD;
total_stablecoin_distributed += REWARD;
BUSD.transfer(owner, REWARD);
// Emit events
emit AffiliateRewardEvent(
_reference,
REWARD,
owner,
block.timestamp
);
_reference = get_nft_reference[_reference];
i++;
}
}
function create_genesis_nfts() public {
if (msg.sender != address(MigrationContract)) return;
// Crear 8 NFTs para la billetera destinada a Desarrollo y Mantenimiento
// Estos NFTs deben estar vinculados entre si
uint256 affiliate_rewards;
for (uint256 i = 0; i < 9; i++) {
_safeMint(communityWallet, i);
recoverNFT(i);
affiliate_rewards += ContractMigration.get_nft_balance_to_claim(i);
get_my_nfts[communityWallet].push(i);
_setTokenURI(
i,
"ipfs://QmRi1DvgDu6zAJwpbURGNBBQTM82ZCNZAyTkEArbKZKm1U/0.json"
);
}
}
function setReferences(uint256 i, uint256 tokenID, uint256 ref) private {
if (i == 0) {
get_first_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_first_level_references[ref];
get_first_level_references[ref].push(tokenID);
// get_first_level_references[ref] = nftIDs;
return;
}
if (i == 1) {
get_second_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_second_level_references[ref];
get_second_level_references[ref].push(tokenID);
// get_second_level_references[ref] = nftIDs;
return;
}
if (i == 2) {
get_third_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_third_level_references[ref];
get_third_level_references[ref].push(tokenID);
// get_third_level_references[ref] = nftIDs;
return;
}
if (i == 3) {
get_four_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_four_level_references[ref];
get_four_level_references[ref].push(tokenID);
// get_four_level_references[ref] = nftIDs;
return;
}
if (i == 4) {
get_five_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_five_level_references[ref];
get_five_level_references[ref].push(tokenID);
// get_five_level_references[ref] = nftIDs;
return;
}
if (i == 5) {
get_six_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_six_level_references[ref];
get_six_level_references[ref].push(tokenID);
// get_six_level_references[ref] = nftIDs;
return;
}
if (i == 6) {
get_seven_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_seven_level_references[ref];
get_seven_level_references[ref].push(tokenID);
// get_seven_level_references[ref] = nftIDs;
return;
}
if (i == 7) {
get_eight_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_eight_level_references[ref];
get_eight_level_references[ref].push(tokenID);
// get_eight_level_references[ref] = nftIDs;
return;
}
if (i == 8) {
get_nine_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
// uint256[] storage nftIDs = get_nine_level_references[ref];
get_nine_level_references[ref].push(tokenID);
// get_nine_level_references[ref] = nftIDs;
return;
}
}
// The following functions are overrides required by Solidity.
function _burn(
uint256 tokenId
) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(
uint256 tokenId
) public view override(ERC721, ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"uint256","name":"date","type":"uint256"}],"name":"AffiliateRewardEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousFavourite","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualFavourite","type":"uint256"}],"name":"ChangeFavourite","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"date","type":"uint256"},{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"string","name":"valueProposal","type":"string"},{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ABLE","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ABLE_ConstancyReward","outputs":[{"internalType":"contract Reward","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ABLE_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ABLE_PassiveReward","outputs":[{"internalType":"contract Reward","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ABLE_SALE","outputs":[{"internalType":"contract SinergySale","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUSD","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUSD_ConstancyReward","outputs":[{"internalType":"contract Reward","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUSD_PassiveReward","outputs":[{"internalType":"contract Reward","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MigrationContract","outputs":[{"internalType":"contract Migration","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TO_DEVELOPMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"actual_lost_income","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amount_nfts_considered","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"changeCommunityWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"communityWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_inscription","type":"string"},{"internalType":"string","name":"_valueProposal","type":"string"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"string","name":"_imageURL","type":"string"},{"internalType":"uint256","name":"_ref","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"createNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"create_genesis_nfts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"developmentWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"favourite_nft","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getAbleBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAmountOfNftMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_eight_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_eight_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_first_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_first_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_five_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_five_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_four_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_four_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_my_nfts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_image_url","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_inscription","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_timestamp_created","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nft_value_proposal","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nine_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_nine_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_second_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_second_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_seven_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_seven_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_six_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_six_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_third_level_amount_reference","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_third_level_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"get_total_amount_references","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"handleRecover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverEightLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverFirstLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverFiveLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverFourLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverNineLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverSecondLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverSevenLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverSixLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"handlerRecoverThirdLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"is_holder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"is_qualified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_inscription","type":"string"},{"internalType":"string","name":"_valueProposal","type":"string"},{"internalType":"uint256","name":"_tokenID","type":"uint256"}],"name":"modifyNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nft_affiliate_rewards_earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"nft_was_qualified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nfts_created_by_cycle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nfts_qualified","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oneDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ableAddress","type":"address"}],"name":"setAbleAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"setFavouriteNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Reward","name":"busd_passive","type":"address"},{"internalType":"contract Reward","name":"busd_constancy","type":"address"},{"internalType":"contract Reward","name":"able_passive","type":"address"},{"internalType":"contract Reward","name":"able_constancy","type":"address"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract SinergySale","name":"ableSale","type":"address"}],"name":"set_able_sale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Migration","name":"_migrationContract","type":"address"}],"name":"set_migration_contract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"starting_nft_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeToNextReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_holders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"total_lost_income","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_raided_for_admin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_stablecoin_distributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"total_stablecoin_earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"updateFromAble","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateFromAble","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052600a80546001600160a01b031990811673ea063b5a744616a161272a013a626a1cbd80ee1b17909155600b8054821673fd26b8be868c0e16a5a54e8d586b0c6d7d6892fa179055600c80548216730b85cca1814ee40c6e83e3591f3819ec7e87d0a5179055600d8054821673765277eebeca2e31912c9946eae1021199b39c61179055600e80548216737fa46675165f0d0ab1a3bd3fd96aa3ed59167b52179055600f80548216734f19668690b3501fa2404039436d4f1c14079db81790556010805482167372e29bc0cf7e6f2a3fc99890069e857b736f6de9179055601180548216732b06dd06cf7cdab0f8cc39a6f79fd88b20cb2c5d17905560128054821673c32afbc61e4a2be096cbe27fa1072ea7f25aa79d1790556013805490911673c8895f6f85d870589c42fd6d531c855bddd27b0f179055620151806014556104876018553480156200015657600080fd5b50604080518082018252600d81526c4f666665722053696e6572677960981b60208083019182528351808501909452600784526653696e6572677960c81b908401528151919291620001ab91600091620007bd565b508051620001c1906001906020840190620007bd565b505050620001de620001d8620004e260201b60201c565b620004e6565b601854620001f860166200053860201b62002b121760201c565b10156200021c576200021660166200053c60201b62002b161760201c565b620001de565b60006200023560166200053860201b62002b121760201c565b90506200024e60166200053c60201b62002b161760201c565b6200026e739060723c22de586c2fa5efa07a7743f6f4a935f58262000545565b604080518082018252600781526647454e4553495360c81b60208083019182526000858152601b909152929092209051620002aa9290620007bd565b50604080518082018252601381527f47454e4553495320494e534352495054494f4e0000000000000000000000000060208083019182526000858152601c909152929092209051620002fd9290620007bd565b50604080518082018252601681527f47454e455349532056414c55452050524f504f53414c0000000000000000000060208083019182526000858152601d909152929092209051620003509290620007bd565b506040518060800160405280605c815260200162005997605c91396000828152601f602090815260409091208251620003909391929190910190620007bd565b506000818152601e60209081526040808320429055739060723c22de586c2fa5efa07a7743f6f4a935f5909252600781527ff0f65e204a552941be11f09a7255d57c9fb6370598c96860a72420b18c78f78b839055815160608101909252603e8083526200040b928492909190620059f3908301396200056b565b60066020527ea535364af8b72a27ad8fea04427a99c3496881b6eeecf55e51e8e1d0096a9380546001810182556000919091527f4ea4f0f529ea4326092b46e5231da2b02a7ce14afeead36ac08f50bb9aa671c10181905560145462000472904262000911565b601555601854601755603c80549060006200048d8362000969565b9091555050739060723c22de586c2fa5efa07a7743f6f4a935f560005250603b6020527fa68fd757b359b471585cc9d12d08d13ee4410790d3ea103994bd4a20c8cd506a805460ff191660011790556200099d565b3390565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b80546001019055565b62000567828260405180602001604052806000815250620005a660201b60201c565b5050565b6200057682620005cb565b6200058057600080fd5b60008281526008602090815260409091208251620005a192840190620007bd565b505050565b620005b28383620005e8565b620005c1600084848462000693565b620005a157600080fd5b6000908152600260205260409020546001600160a01b0316151590565b6001600160a01b038216620005fc57600080fd5b6200060781620005cb565b156200061257600080fd5b6200061d81620005cb565b156200062857600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000620006b4846001600160a01b0316620007ae60201b62002b1f1760201c565b15620007a257604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290620006ee90339089908890889060040162000896565b602060405180830381600087803b1580156200070957600080fd5b505af19250505080156200073c575060408051601f3d908101601f19168201909252620007399181019062000863565b60015b62000787573d8080156200076d576040519150601f19603f3d011682016040523d82523d6000602084013e62000772565b606091505b5080516200077f57600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050620007a6565b5060015b949350505050565b6001600160a01b03163b151590565b828054620007cb906200092c565b90600052602060002090601f016020900481019282620007ef57600085556200083a565b82601f106200080a57805160ff19168380011785556200083a565b828001600101855582156200083a579182015b828111156200083a5782518255916020019190600101906200081d565b50620008489291506200084c565b5090565b5b808211156200084857600081556001016200084d565b6000602082840312156200087657600080fd5b81516001600160e01b0319811681146200088f57600080fd5b9392505050565b600060018060a01b038087168352602081871681850152856040850152608060608501528451915081608085015260005b82811015620008e55785810182015185820160a001528101620008c7565b82811115620008f857600060a084870101525b5050601f01601f19169190910160a00195945050505050565b6000821982111562000927576200092762000987565b500190565b600181811c908216806200094157607f821691505b602082108114156200096357634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141562000980576200098062000987565b5060010190565b634e487b7160e01b600052601160045260246000fd5b614fea80620009ad6000396000f3fe608060405234801561001057600080fd5b506004361061044b5760003560e01c806301ffc9a71461045057806306fdde0314610478578063081812fc1461048d57806308a1f67f146104ad578063095ea7b3146104ce5780630dfc4ef9146104e3578063172a327e146104ec5780631c1b8772146104f55780631dbe17e51461050857806323b872dd1461051b578063297e07621461052e5780632ae6ddc3146105415780632e915ad814610554578063328b18a5146105675780633c1bd083146105705780633eab2b481461058357806342842e0e14610596578063443c0aa4146105a957806346bce096146105c9578063484f4ea9146105e957806349d4d80c146105fc5780634b2dfa7b1461060f5780634bd9351b1461062257806353294b701461062b5780635616f3251461064b578063570be5a11461066b5780636136c1561461067e57806361e1fa751461069e578063634ddfd8146106b15780636352211e146106c4578063671d2a76146106d757806367d13e99146106e05780636841b0a9146106f35780636b7979e8146107135780636ef3a27a1461071b578063706e2dfd1461072e57806370a082311461074e57806370c7038314610761578063715018a614610774578063724039f11461077c578063782300d51461078f5780637c209fc6146107b25780637e65c6f6146107c5578063813e551c146107d857806381c9db77146107f857806382210e5f1461081857806382d706ad1461082b57806384370b7a1461083e57806385c2214e14610847578063895694bf1461085a5780638d5791dc1461086d5780638d859f3e1461088d5780638da5cb5b1461089d57806390a97cb2146108a55780639106e0be146108b857806391dbff7a146108d857806394a05be7146108eb57806395d89b41146108fe5780639694dee514610906578063998ed59614610919578063a1df30731461092c578063a22cb4651461093f578063a621283114610952578063a653bfdc14610965578063aec2054b14610985578063b27d1b7e14610994578063b88d4fde146109a7578063bb53ac39146109ba578063bd8cd14e146109cd578063c04a5414146109ed578063c4a1eefc14610a08578063c757483914610a17578063c7a0e1dc14610a2a578063c87b56dd14610a4d578063c8aaf64b146104e1578063cab34c0814610985578063cafb7bec14610a60578063cb9f22c614610a73578063d3be604514610a93578063d6003e4e14610aa6578063d8f8924514610ac6578063da74d74214610ad9578063da7e928514610aec578063dad964f414610aff578063de66b4c414610b1e578063de88a3ba14610b31578063deaec42c14610b44578063e1aaa2fa14610b57578063e1cdc6f714610b6a578063e681204114610b8a578063e985e9c514610baa578063eb20feab14610bbd578063ec3bc7b114610bd0578063ecd8966414610be3578063f26716c514610c03578063f2fde38b14610c0b578063f3e3f99414610c1e575b600080fd5b61046361045e3660046149c6565b610c27565b60405190151581526020015b60405180910390f35b610480610c79565b60405161046f9190614d9e565b6104a061049b366004614c45565b610d0b565b60405161046f9190614d10565b6104c06104bb366004614c77565b610d32565b60405190815260200161046f565b6104e16104dc36600461497d565b610d63565b005b6104c0603c5481565b6104c060365481565b6104e161050336600461481c565b610dc3565b600f546104a0906001600160a01b031681565b6104e161052936600461488f565b610e39565b6104c061053c366004614c77565b610e57565b6104e161054f366004614c77565b610e73565b6104e161056236600461481c565b610f34565b6104c060175481565b61048061057e366004614c45565b610f74565b6104c0610591366004614c77565b61100e565b6104e16105a436600461488f565b61102a565b6104c06105b7366004614c45565b60236020526000908152604090205481565b6104c06105d7366004614c45565b60226020526000908152604090205481565b600d546104a0906001600160a01b031681565b6104e161060a366004614c77565b611045565b6104e161061d36600461481c565b61109c565b6104c060145481565b6104c0610639366004614c45565b60286020526000908152604090205481565b6104c0610659366004614c45565b60246020526000908152604090205481565b6104e1610679366004614a00565b6110a4565b6104c061068c36600461481c565b60386020526000908152604090205481565b6104e16106ac366004614bb6565b611114565b6104c06106bf366004614c77565b61176f565b6104a06106d2366004614c45565b61178b565b6104c060155481565b6104e16106ee366004614ad2565b6117ac565b6104c0610701366004614c45565b603a6020526000908152604090205481565b6104c0612129565b6104e161072936600461481c565b612139565b6104c061073c366004614c45565b60256020526000908152604090205481565b6104c061075c36600461481c565b61217b565b6104c061076f366004614c77565b6121ac565b6104e16121c8565b6104e161078a366004614c77565b6121dc565b61046361079d36600461481c565b603b6020526000908152604090205460ff1681565b6104e16107c0366004614c77565b612233565b6104e16107d3366004614c77565b61228a565b6104c06107e636600461481c565b60396020526000908152604090205481565b6104c0610806366004614c45565b60266020526000908152604090205481565b6104c061082636600461497d565b6122e1565b610480610839366004614c45565b6122fd565b6104c060195481565b6104e1610855366004614c77565b612316565b6104c0610868366004614c77565b61236d565b6104c061087b366004614c45565b60336020526000908152604090205481565b6104c06801f399b1438a10000081565b6104a0612389565b600c546104a0906001600160a01b031681565b6104c06108c6366004614c45565b60216020526000908152604090205481565b6104c06108e6366004614c77565b612398565b6104e16108f936600461497d565b6123b4565b610480612445565b600e546104a0906001600160a01b031681565b6104e161092736600461497d565b612454565b6104e161093a36600461481c565b612555565b6104e161094d36600461494f565b61258e565b6104e1610960366004614c77565b612599565b6104c0610973366004614c45565b601e6020526000908152604090205481565b6104c06729a2241af62c000081565b6012546104a0906001600160a01b031681565b6104e16109b53660046148d0565b6125f0565b6010546104a0906001600160a01b031681565b6104c06109db36600461481c565b60076020526000908152604090205481565b6104a0739060723c22de586c2fa5efa07a7743f6f4a935f581565b6104c067a688906bd8b0000081565b6013546104a0906001600160a01b031681565b610463610a3836600461481c565b601a6020526000908152604090205460ff1681565b610480610a5b366004614c45565b61260f565b6104c0610a6e366004614c77565b61261a565b6104c0610a81366004614c45565b60296020526000908152604090205481565b6104e1610aa1366004614c77565b612636565b6104c0610ab436600461481c565b603d6020526000908152604090205481565b6104c0610ad436600461481c565b61268d565b610480610ae7366004614c45565b61270e565b610463610afa366004614c45565b612727565b6104c0610b0d366004614c45565b602080526000908152604090205481565b6104e1610b2c366004614c77565b6128c4565b6011546104a0906001600160a01b031681565b600b546104a0906001600160a01b031681565b610480610b65366004614c45565b61291b565b6104c0610b78366004614c45565b60276020526000908152604090205481565b6104c0610b9836600461481c565b60376020526000908152604090205481565b610463610bb8366004614856565b612934565b6104c0610bcb366004614c77565b612962565b6104e1610bde36600461481c565b61297e565b6104c0610bf1366004614c45565b60346020526000908152604090205481565b6104e16129c0565b6104e1610c1936600461481c565b612aee565b6104c060355481565b60006001600160e01b031982166380ac58cd60e01b1480610c5857506001600160e01b03198216635b5e139f60e01b145b80610c7357506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060008054610c8890614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb490614e71565b8015610d015780601f10610cd657610100808354040283529160200191610d01565b820191906000526020600020905b815481529060010190602001808311610ce457829003601f168201915b5050505050905090565b6000610d1682612b2e565b506000908152600460205260409020546001600160a01b031690565b602f6020528160005260406000208181548110610d4e57600080fd5b90600052602060002001600091509150505481565b6000610d6e8261178b565b9050806001600160a01b0316836001600160a01b03161415610d8f57600080fd5b336001600160a01b0382161480610dab5750610dab8133612934565b610db457600080fd5b610dbe8383612b40565b505050565b600c546040516337f9ed1360e01b81526001600160a01b03909116906337f9ed1390610df3908490600401614d10565b600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50505050610e2d612bae565b610e3681612d6b565b50565b610e433382612ecb565b610e4c57600080fd5b610dbe838383612f2a565b602c6020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b03163314610e89575050565b60008281526030602052604090819020600a5491516332bedefb60e21b815290916001600160a01b03169063cafb7bec90610eca9086908690600401614db1565b60206040518083038186803b158015610ee257600080fd5b505afa158015610ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190614c5e565b815460018101835560009283526020909220909101555050565b33739060723c22de586c2fa5efa07a7743f6f4a935f514610f525750565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b601f6020526000908152604090208054610f8d90614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054610fb990614e71565b80156110065780601f10610fdb57610100808354040283529160200191611006565b820191906000526020600020905b815481529060010190602001808311610fe957829003601f168201915b505050505081565b602a6020528160005260406000208181548110610d4e57600080fd5b610dbe838383604051806020016040528060008152506125f0565b600b546001600160a01b0316331461105b575050565b6000828152602b602052604090819020600a5491516348edffbd60e11b815290916001600160a01b0316906391dbff7a90610eca9086908690600401614db1565b610e2d612bae565b33739060723c22de586c2fa5efa07a7743f6f4a935f5146110c457600080fd5b600f80546001600160a01b039586166001600160a01b0319918216179091556011805494861694821694909417909355601080549285169284169290921790915560128054919093169116179055565b61111d8161178b565b6001600160a01b0316336001600160a01b03161461113a57600080fd5b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd9061117790339030906801f399b1438a10000090600401614d24565b602060405180830381600087803b15801561119157600080fd5b505af11580156111a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c991906149a9565b50600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611206903390309067a688906bd8b0000090600401614d24565b602060405180830381600087803b15801561122057600080fd5b505af1158015611234573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125891906149a9565b50600d5460135460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92611297929116906729a2241af62c000090600401614d85565b602060405180830381600087803b1580156112b157600080fd5b505af11580156112c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e991906149a9565b506000818152601b60209081526040909120855161130992870190614725565b506000818152601c60209081526040909120845161132992860190614725565b506000818152601d60209081526040909120835161134992850190614725565b506729a2241af62c0000603560008282546113649190614e16565b9091555050600f546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156113b657600080fd5b505af11580156113ca573d6000803e3d6000fd5b5050600d54600f5460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb935061140d92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561142757600080fd5b505af115801561143b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145f91906149a9565b506010546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156114ad57600080fd5b505af11580156114c1573d6000803e3d6000fd5b5050600c5460105460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb935061150492909116906753444835ec58000090600401614d85565b602060405180830381600087803b15801561151e57600080fd5b505af1158015611532573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155691906149a9565b506012546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156115a457600080fd5b505af11580156115b8573d6000803e3d6000fd5b5050600c5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb93506115fb92909116906753444835ec58000090600401614d85565b602060405180830381600087803b15801561161557600080fd5b505af1158015611629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164d91906149a9565b506011546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b15801561169b57600080fd5b505af11580156116af573d6000803e3d6000fd5b5050600d5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb93506116f292909116906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561170c57600080fd5b505af1158015611720573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174491906149a9565b5060008181526033602052604081205461176091839190613033565b61176933610dc3565b50505050565b60316020528160005260406000208181548110610d4e57600080fd5b600080611797836131e3565b90506001600160a01b038116610c7357600080fd5b600060076000600c60009054906101000a90046001600160a01b03166001600160a01b031663b1ea10336040518163ffffffff1660e01b815260040160206040518083038186803b15801561180057600080fd5b505afa158015611814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118389190614839565b6001600160a01b031681526020810191909152604001600020549050821561185d5750815b80611866575060085b601654811061187457600080fd5b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906118b190339030906801f399b1438a10000090600401614d24565b602060405180830381600087803b1580156118cb57600080fd5b505af11580156118df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190391906149a9565b50600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611940903390309067a688906bd8b0000090600401614d24565b602060405180830381600087803b15801561195a57600080fd5b505af115801561196e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199291906149a9565b50600d5460135460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb926119d1929116906729a2241af62c000090600401614d85565b602060405180830381600087803b1580156119eb57600080fd5b505af11580156119ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2391906149a9565b50611a2d33612d6b565b600e543360009081526007602052604090819020549051633d9fa62360e01b81526001600160a01b0390921691633d9fa62391611a709160040190815260200190565b600060405180830381600087803b158015611a8a57600080fd5b505af1158015611a9e573d6000803e3d6000fd5b505050506000611aad60165490565b9050611abd601680546001019055565b611ac733826131fe565b611ad18187613218565b6000818152601b602090815260409091208a51611af0928c0190614725565b506000818152601c602090815260409091208951611b10928b0190614725565b506000818152601d602090815260409091208851611b30928a0190614725565b506000818152603360209081526040808320859055601f82529091208651611b5a92880190614725565b506000818152601e602090815260408083208690553383526007909152902054611b91573360009081526007602052604090208190555b3360009081526006602090815260408220805460018101825590835290822001829055603580546729a2241af62c00009290611bce908490614e16565b90915550506010546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611c2057600080fd5b505af1158015611c34573d6000803e3d6000fd5b5050600c5460105460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611c7792909116906753444835ec58000090600401614d85565b602060405180830381600087803b158015611c9157600080fd5b505af1158015611ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc991906149a9565b50600f546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611d1757600080fd5b505af1158015611d2b573d6000803e3d6000fd5b5050600d54600f5460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611d6e92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b158015611d8857600080fd5b505af1158015611d9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc091906149a9565b506012546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611e0e57600080fd5b505af1158015611e22573d6000803e3d6000fd5b5050600c5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611e6592909116906753444835ec58000090600401614d85565b602060405180830381600087803b158015611e7f57600080fd5b505af1158015611e93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb791906149a9565b506011546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611f0557600080fd5b505af1158015611f19573d6000803e3d6000fd5b5050600d5460115460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611f5c92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b158015611f7657600080fd5b505af1158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae91906149a9565b50611fbb81836001613033565b611fc433610dc3565b603a6000600c60009054906101000a90046001600160a01b03166001600160a01b0316636190c9d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561201657600080fd5b505afa15801561202a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204e9190614c5e565b8152602001908152602001600020600081548092919061206d90614eac565b9091555050336000908152603b602052604090205460ff166120b757336000908152603b60205260408120805460ff19166001179055603c8054916120b183614eac565b91905055505b60405133906120c7908990614cc5565b60405180910390208a6040516120dd9190614cc5565b60405180910390207f348a2af61c3e551d263eaa8735e61cbaaa4dbbcde2de30c684dd75431e5088d78442604051612116929190614db1565b60405180910390a4505050505050505050565b600061213460165490565b905090565b33739060723c22de586c2fa5efa07a7743f6f4a935f51461215957600080fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b03821661219057600080fd5b506001600160a01b031660009081526003602052604090205490565b602e6020528160005260406000208181548110610d4e57600080fd5b6121d0613249565b6121da6000613265565b565b600b546001600160a01b031633146121f2575050565b6000828152602e602052604090819020600a5491516370c7038360e01b815290916001600160a01b0316906370c7038390610eca9086908690600401614db1565b600b546001600160a01b03163314612249575050565b6000828152602d602052604090819020600a54915163895694bf60e01b815290916001600160a01b03169063895694bf90610eca9086908690600401614db1565b600b546001600160a01b031633146122a0575050565b60008281526032602052604090819020600a54915163eb20feab60e01b815290916001600160a01b03169063eb20feab90610eca9086908690600401614db1565b60066020528160005260406000208181548110610d4e57600080fd5b601d6020526000908152604090208054610f8d90614e71565b600b546001600160a01b0316331461232c575050565b6000828152602a602052604090819020600a5491516307d5656960e31b815290916001600160a01b031690633eab2b4890610eca9086908690600401614db1565b602d6020528160005260406000208181548110610d4e57600080fd5b6009546001600160a01b031690565b602b6020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b031633146123ca575050565b6123d3816132b7565b6001600160a01b03821660009081526006602090815260408220805460018101825590835291200181905561240882826131fe565b6001600160a01b038216600090815260076020526040902054612441576001600160a01b03821660009081526007602052604090208190555b5050565b606060018054610c8890614e71565b60165481111561246357600080fd5b61246c8161178b565b6001600160a01b0316336001600160a01b031614806124955750600b546001600160a01b031633145b6124f55760405162461bcd60e51b815260206004820152602760248201527f57616c6c6574206e6f74207175616c696669656420746f207365744661766f756044820152661c9a5d1953919560ca1b606482015260840160405180910390fd5b6001600160a01b03821660009081526007602052604090819020805490839055905133907ff1920cbfe18dff4155b1e46e979d6d82313c39f04760c14fbb8f37a21b36e912906125489084908690614db1565b60405180910390a2505050565b6013546001600160a01b0316331461256c57600080fd5b601380546001600160a01b0319166001600160a01b0392909216919091179055565b612441338383613bf9565b600b546001600160a01b031633146125af575050565b6000828152602f602052604090819020600a5491516308a1f67f60e01b815290916001600160a01b0316906308a1f67f90610eca9086908690600401614db1565b6125fa3383612ecb565b61260357600080fd5b61176984848484613c85565b6060610c7382613ca5565b60306020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b0316331461264c575050565b60008281526031602052604090819020600a549151630c69bbfb60e31b815290916001600160a01b03169063634ddfd890610eca9086908690600401614db1565b600c546040516370a0823160e01b81526000916001600160a01b0316906370a08231906126be908590600401614d10565b60206040518083038186803b1580156126d657600080fd5b505afa1580156126ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c739190614c5e565b601b6020526000908152604090208054610f8d90614e71565b600c546000906001600160a01b0316637ba14d8c6127448461178b565b6040518263ffffffff1660e01b81526004016127609190614d10565b60206040518083038186803b15801561277857600080fd5b505afa15801561278c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b091906149a9565b80610c735750600c546001600160a01b0316636252b6fd6127d08461178b565b600c5460408051636190c9d560e01b815290516001926001600160a01b031691636190c9d5916004808301926020929190829003018186803b15801561281557600080fd5b505afa158015612829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284d9190614c5e565b6128579190614e2e565b6040518363ffffffff1660e01b8152600401612874929190614d85565b60206040518083038186803b15801561288c57600080fd5b505afa1580156128a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7391906149a9565b600b546001600160a01b031633146128da575050565b6000828152602c602052604090819020600a5491516314bf03b160e11b815290916001600160a01b03169063297e076290610eca9086908690600401614db1565b601c6020526000908152604090208054610f8d90614e71565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60326020528160005260406000208181548110610d4e57600080fd5b33739060723c22de586c2fa5efa07a7743f6f4a935f51461299e57600080fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b031633146129d457565b6000805b6009811015612441576013546129f7906001600160a01b0316826131fe565b612a00816132b7565b600a5460405163d940848960e01b8152600481018390526001600160a01b039091169063d94084899060240160206040518083038186803b158015612a4457600080fd5b505afa158015612a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7c9190614c5e565b612a869083614e16565b6013546001600160a01b03166000908152600660209081526040808320805460018101825590845292829020909201849055815160608101909252603c808352929450612adc92849291614f5990830139613218565b80612ae681614eac565b9150506129d8565b612af6613249565b6001600160a01b038116612b0957600080fd5b610e3681613265565b5490565b80546001019055565b6001600160a01b03163b151590565b612b3781613dae565b610e3657600080fd5b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612b758261178b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6015544211156121da57600f60009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c0857600080fd5b505af1158015612c1c573d6000803e3d6000fd5b50505050601060009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c7057600080fd5b505af1158015612c84573d6000803e3d6000fd5b50505050601160009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612cd857600080fd5b505af1158015612cec573d6000803e3d6000fd5b50505050601260009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612d4057600080fd5b505af1158015612d54573d6000803e3d6000fd5b5050505060145442612d669190614e16565b601555565b6001600160a01b0381166000908152601a602052604090205460ff1615612deb576001600160a01b0381166000908152603d60205260408120546019805491929091612db8908490614e2e565b90915550506001600160a01b0381166000908152603d60209081526040808320839055601a9091529020805460ff191690555b600c54604051631ee8536360e21b81526001600160a01b0390911690637ba14d8c90612e1b908490600401614d10565b60206040518083038186803b158015612e3357600080fd5b505afa158015612e47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6b91906149a9565b15610e3657612e798161217b565b60196000828254612e8a9190614e16565b90915550612e9990508161217b565b6001600160a01b0382166000908152603d6020908152604080832093909355601a905220805460ff1916600117905550565b600080612ed78361178b565b9050806001600160a01b0316846001600160a01b03161480612efe5750612efe8185612934565b80612f225750836001600160a01b0316612f1784610d0b565b6001600160a01b0316145b949350505050565b826001600160a01b0316612f3d8261178b565b6001600160a01b031614612f5057600080fd5b6001600160a01b038216612f6357600080fd5b826001600160a01b0316612f768261178b565b6001600160a01b031614612f8957600080fd5b600081815260046020526040902080546001600160a01b0319169055612faf8184613dcb565b6001600160a01b03831660009081526003602052604090208054600019019055612fd98183613f8c565b6001600160a01b03808316600081815260036020908152604080832080546001019055858352600290915280822080546001600160a01b03191684179055518493871691600080516020614f9583398151915291a4505050565b6000805b60098110156131dc57821561305157613051818686613fe0565b61305a8461178b565b6001600160a01b038116600090815260376020526040812080549294506729a2241af62c00009290919061308f908490614e16565b9091555050600084815260346020526040812080546729a2241af62c000092906130ba908490614e16565b925050819055506729a2241af62c0000603660008282546130db9190614e16565b9091555050600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061311a9085906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561313457600080fd5b505af1158015613148573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316c91906149a9565b5042826001600160a01b03167fa421b4aced6f4fcb40d755e461bb29417a90636ae4f2769ff2cb29db7eab7994866729a2241af62c00006040516131b1929190614db1565b60405180910390a36000938452603360205260409093205492806131d481614eac565b915050613037565b5050505050565b6000908152600260205260409020546001600160a01b031690565b61244182826040518060200160405280600081525061438c565b61322182613dae565b61322a57600080fd5b60008281526008602090815260409091208251610dbe92840190614725565b33613252612389565b6001600160a01b0316146121da57600080fd5b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600a54604051636d3a6ba160e11b8152600481018390526001600160a01b039091169063da74d7429060240160006040518083038186803b1580156132fb57600080fd5b505afa15801561330f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133379190810190614a5c565b6000828152601b60209081526040909120825161335a9391929190910190614725565b50600a546040516370d5517d60e11b8152600481018390526001600160a01b039091169063e1aaa2fa9060240160006040518083038186803b15801561339f57600080fd5b505afa1580156133b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133db9190810190614a5c565b6000828152601c6020908152604090912082516133fe9391929190910190614725565b50600a546040516382d706ad60e01b8152600481018390526001600160a01b03909116906382d706ad9060240160006040518083038186803b15801561344357600080fd5b505afa158015613457573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261347f9190810190614a5c565b6000828152601d6020908152604090912082516134a29391929190910190614725565b50600a54604051632994eff760e21b8152600481018390526001600160a01b039091169063a653bfdc9060240160206040518083038186803b1580156134e757600080fd5b505afa1580156134fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351f9190614c5e565b6000828152601e60205260409081902091909155600a549051633c1bd08360e01b8152600481018390526001600160a01b0390911690633c1bd0839060240160006040518083038186803b15801561357657600080fd5b505afa15801561358a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135b29190810190614a5c565b6000828152601f6020908152604090912082516135d59391929190910190614725565b50600a54604051632355e47760e21b8152600481018390526001600160a01b0390911690638d5791dc9060240160206040518083038186803b15801561361a57600080fd5b505afa15801561362e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136529190614c5e565b6000828152603360205260409081902091909155600a5490516336b6593d60e21b8152600481018390526001600160a01b039091169063dad964f49060240160206040518083038186803b1580156136a957600080fd5b505afa1580156136bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e19190614c5e565b60008281526020805260409081902091909155600a549051634883705f60e11b8152600481018390526001600160a01b0390911690639106e0be9060240160206040518083038186803b15801561373757600080fd5b505afa15801561374b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376f9190614c5e565b6000828152602160205260409081902091909155600a54905163235e704b60e11b8152600481018390526001600160a01b03909116906346bce0969060240160206040518083038186803b1580156137c657600080fd5b505afa1580156137da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fe9190614c5e565b6000828152602260205260409081902091909155600a54905163110f02a960e21b8152600481018390526001600160a01b039091169063443c0aa49060240160206040518083038186803b15801561385557600080fd5b505afa158015613869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388d9190614c5e565b6000828152602360205260409081902091909155600a549051635616f32560e01b8152600481018390526001600160a01b0390911690635616f3259060240160206040518083038186803b1580156138e457600080fd5b505afa1580156138f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391c9190614c5e565b60008281526024602081905260409182902092909255600a54905163706e2dfd60e01b8152600481018490526001600160a01b039091169163706e2dfd910160206040518083038186803b15801561397357600080fd5b505afa158015613987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ab9190614c5e565b6000828152602560205260409081902091909155600a5490516381c9db7760e01b8152600481018390526001600160a01b03909116906381c9db779060240160206040518083038186803b158015613a0257600080fd5b505afa158015613a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a3a9190614c5e565b6000828152602660205260409081902091909155600a54905163e1cdc6f760e01b8152600481018390526001600160a01b039091169063e1cdc6f79060240160206040518083038186803b158015613a9157600080fd5b505afa158015613aa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac99190614c5e565b6000828152602760205260409081902091909155600a54905163053294b760e41b8152600481018390526001600160a01b03909116906353294b709060240160206040518083038186803b158015613b2057600080fd5b505afa158015613b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b589190614c5e565b6000828152602860205260409081902091909155600a5490516365cf916360e11b8152600481018390526001600160a01b039091169063cb9f22c69060240160206040518083038186803b158015613baf57600080fd5b505afa158015613bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613be79190614c5e565b60009182526029602052604090912055565b816001600160a01b0316836001600160a01b03161415613c1857600080fd5b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613c90848484612f2a565b613c9c848484846143ac565b61176957600080fd5b6060613cb082612b2e565b60008281526008602052604081208054613cc990614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054613cf590614e71565b8015613d425780601f10613d1757610100808354040283529160200191613d42565b820191906000526020600020905b815481529060010190602001808311613d2557829003601f168201915b505050505090506000613d6060408051602081019091526000815290565b9050805160001415613d73575092915050565b815115613da5578082604051602001613d8d929190614ce1565b60405160208183030381529060405292505050919050565b612f22846144ad565b600080613dba836131e3565b6001600160a01b0316141592915050565b60005b6001600160a01b0382166000908152600660205260409020805484919083908110613dfb57613dfb614ef3565b906000526020600020015414613e1d5780613e1581614eac565b915050613dce565b6001600160a01b038216600090815260036020526040902054613e4290600190614e2e565b811015613edb576001600160a01b0382166000908152600660205260409020613e6c826001614e16565b81548110613e7c57613e7c614ef3565b906000526020600020015460066000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110613ebd57613ebd614ef3565b60009182526020909120015580613ed381614eac565b915050613e1d565b6001600160a01b0382166000908152600660205260409020805480613f0257613f02614edd565b6000828152602080822083016000199081018390559092019092556001600160a01b0384168252600790526040902054831415610dbe576001600160a01b03821660009081526006602052604081208054909190613f6257613f62614ef3565b60009182526020808320909101546001600160a01b03851683526007909152604090912055505050565b6001600160a01b0381166000818152600660209081526040808320805460018101825590845282842001869055928252600790522054612441576001600160a01b0316600090815260076020526040902055565b826140445760008181526020805260408120805491613ffe83614eac565b9091555050600081815260296020526040812080549161401d83614eac565b90915550506000908152602a60209081526040822080546001810182559083529120015550565b82600114156140ad57600081815260216020526040812080549161406783614eac565b9091555050600081815260296020526040812080549161408683614eac565b90915550506000908152602b60209081526040822080546001810182559083529120015550565b82600214156141165760008181526022602052604081208054916140d083614eac565b909155505060008181526029602052604081208054916140ef83614eac565b90915550506000908152602c60209081526040822080546001810182559083529120015550565b826003141561417f57600081815260236020526040812080549161413983614eac565b9091555050600081815260296020526040812080549161415883614eac565b90915550506000908152602d60209081526040822080546001810182559083529120015550565b82600414156141e85760008181526024602052604081208054916141a283614eac565b909155505060008181526029602052604081208054916141c183614eac565b90915550506000908152602e60209081526040822080546001810182559083529120015550565b826005141561425157600081815260256020526040812080549161420b83614eac565b9091555050600081815260296020526040812080549161422a83614eac565b90915550506000908152602f60209081526040822080546001810182559083529120015550565b82600614156142ba57600081815260266020526040812080549161427483614eac565b9091555050600081815260296020526040812080549161429383614eac565b90915550506000908152603060209081526040822080546001810182559083529120015550565b82600714156143235760008181526027602052604081208054916142dd83614eac565b909155505060008181526029602052604081208054916142fc83614eac565b90915550506000908152603160209081526040822080546001810182559083529120015550565b8260081415610dbe57600081815260286020526040812080549161434683614eac565b9091555050600081815260296020526040812080549161436583614eac565b90915550506000908152603260209081526040822080546001810182559083529120015550565b6143968383614521565b6143a360008484846143ac565b610dbe57600080fd5b60006143c0846001600160a01b0316612b1f565b156144a257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906143f7903390899088908890600401614d48565b602060405180830381600087803b15801561441157600080fd5b505af1925050508015614441575060408051601f3d908101601f1916820190925261443e918101906149e3565b60015b614488573d80801561446f576040519150601f19603f3d011682016040523d82523d6000602084013e614474565b606091505b50805161448057600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612f22565b506001949350505050565b60606144b882612b2e565b60006144cf60408051602081019091526000815290565b905060008151116144ef576040518060200160405280600081525061451a565b806144f9846145b3565b60405160200161450a929190614ce1565b6040516020818303038152906040525b9392505050565b6001600160a01b03821661453457600080fd5b61453d81613dae565b1561454757600080fd5b61455081613dae565b1561455a57600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020614f95833981519152908290a45050565b606060006145c08361464f565b60010190506000816001600160401b038111156145df576145df614f09565b6040519080825280601f01601f191660200182016040528015614609576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461464257614647565b614613565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061468e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106146b8576904ee2d6d415b85acef8160201b830492506020015b662386f26fc1000083106146d657662386f26fc10000830492506010015b6305f5e10083106146ee576305f5e100830492506008015b612710831061470257612710830492506004015b60648310614714576064830492506002015b600a8310610c735760010192915050565b82805461473190614e71565b90600052602060002090601f0160209004810192826147535760008555614799565b82601f1061476c57805160ff1916838001178555614799565b82800160010185558215614799579182015b8281111561479957825182559160200191906001019061477e565b506147a59291506147a9565b5090565b5b808211156147a557600081556001016147aa565b60006147d16147cc84614def565b614dbf565b90508281528383830111156147e557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261480d57600080fd5b61451a838335602085016147be565b60006020828403121561482e57600080fd5b813561451a81614f1f565b60006020828403121561484b57600080fd5b815161451a81614f1f565b6000806040838503121561486957600080fd5b823561487481614f1f565b9150602083013561488481614f1f565b809150509250929050565b6000806000606084860312156148a457600080fd5b83356148af81614f1f565b925060208401356148bf81614f1f565b929592945050506040919091013590565b600080600080608085870312156148e657600080fd5b84356148f181614f1f565b9350602085013561490181614f1f565b92506040850135915060608501356001600160401b0381111561492357600080fd5b8501601f8101871361493457600080fd5b614943878235602084016147be565b91505092959194509250565b6000806040838503121561496257600080fd5b823561496d81614f1f565b9150602083013561488481614f34565b6000806040838503121561499057600080fd5b823561499b81614f1f565b946020939093013593505050565b6000602082840312156149bb57600080fd5b815161451a81614f34565b6000602082840312156149d857600080fd5b813561451a81614f42565b6000602082840312156149f557600080fd5b815161451a81614f42565b60008060008060808587031215614a1657600080fd5b8435614a2181614f1f565b93506020850135614a3181614f1f565b92506040850135614a4181614f1f565b91506060850135614a5181614f1f565b939692955090935050565b600060208284031215614a6e57600080fd5b81516001600160401b03811115614a8457600080fd5b8201601f81018413614a9557600080fd5b8051614aa36147cc82614def565b818152856020838501011115614ab857600080fd5b614ac9826020830160208601614e45565b95945050505050565b600080600080600080600060e0888a031215614aed57600080fd5b87356001600160401b0380821115614b0457600080fd5b614b108b838c016147fc565b985060208a0135915080821115614b2657600080fd5b614b328b838c016147fc565b975060408a0135915080821115614b4857600080fd5b614b548b838c016147fc565b965060608a0135915080821115614b6a57600080fd5b614b768b838c016147fc565b955060808a0135915080821115614b8c57600080fd5b50614b998a828b016147fc565b93505060a0880135915060c0880135905092959891949750929550565b60008060008060808587031215614bcc57600080fd5b84356001600160401b0380821115614be357600080fd5b614bef888389016147fc565b95506020870135915080821115614c0557600080fd5b614c11888389016147fc565b94506040870135915080821115614c2757600080fd5b50614c34878288016147fc565b949793965093946060013593505050565b600060208284031215614c5757600080fd5b5035919050565b600060208284031215614c7057600080fd5b5051919050565b60008060408385031215614c8a57600080fd5b50508035926020909101359150565b60008151808452614cb1816020860160208601614e45565b601f01601f19169290920160200192915050565b60008251614cd7818460208701614e45565b9190910192915050565b60008351614cf3818460208801614e45565b835190830190614d07818360208801614e45565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614d7b90830184614c99565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b60208152600061451a6020830184614c99565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715614de757614de7614f09565b604052919050565b60006001600160401b03821115614e0857614e08614f09565b50601f01601f191660200190565b60008219821115614e2957614e29614ec7565b500190565b600082821015614e4057614e40614ec7565b500390565b60005b83811015614e60578181015183820152602001614e48565b838111156117695750506000910152565b600181811c90821680614e8557607f821691505b60208210811415614ea657634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ec057614ec0614ec7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e3657600080fd5b8015158114610e3657600080fd5b6001600160e01b031981168114610e3657600080fdfe697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f302e6a736f6eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220f0db85a3c35611b4775d04f5137da082f4100840cb359a55c06f20ea969e65d564736f6c6343000807003368747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f73617665722d636f6d6d756e6974792f696d6167652f75706c6f61642f76313636363338303530312f6a766a626c73346c67356d74787378686c686e662e706e67697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f3237332e6a736f6e
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061044b5760003560e01c806301ffc9a71461045057806306fdde0314610478578063081812fc1461048d57806308a1f67f146104ad578063095ea7b3146104ce5780630dfc4ef9146104e3578063172a327e146104ec5780631c1b8772146104f55780631dbe17e51461050857806323b872dd1461051b578063297e07621461052e5780632ae6ddc3146105415780632e915ad814610554578063328b18a5146105675780633c1bd083146105705780633eab2b481461058357806342842e0e14610596578063443c0aa4146105a957806346bce096146105c9578063484f4ea9146105e957806349d4d80c146105fc5780634b2dfa7b1461060f5780634bd9351b1461062257806353294b701461062b5780635616f3251461064b578063570be5a11461066b5780636136c1561461067e57806361e1fa751461069e578063634ddfd8146106b15780636352211e146106c4578063671d2a76146106d757806367d13e99146106e05780636841b0a9146106f35780636b7979e8146107135780636ef3a27a1461071b578063706e2dfd1461072e57806370a082311461074e57806370c7038314610761578063715018a614610774578063724039f11461077c578063782300d51461078f5780637c209fc6146107b25780637e65c6f6146107c5578063813e551c146107d857806381c9db77146107f857806382210e5f1461081857806382d706ad1461082b57806384370b7a1461083e57806385c2214e14610847578063895694bf1461085a5780638d5791dc1461086d5780638d859f3e1461088d5780638da5cb5b1461089d57806390a97cb2146108a55780639106e0be146108b857806391dbff7a146108d857806394a05be7146108eb57806395d89b41146108fe5780639694dee514610906578063998ed59614610919578063a1df30731461092c578063a22cb4651461093f578063a621283114610952578063a653bfdc14610965578063aec2054b14610985578063b27d1b7e14610994578063b88d4fde146109a7578063bb53ac39146109ba578063bd8cd14e146109cd578063c04a5414146109ed578063c4a1eefc14610a08578063c757483914610a17578063c7a0e1dc14610a2a578063c87b56dd14610a4d578063c8aaf64b146104e1578063cab34c0814610985578063cafb7bec14610a60578063cb9f22c614610a73578063d3be604514610a93578063d6003e4e14610aa6578063d8f8924514610ac6578063da74d74214610ad9578063da7e928514610aec578063dad964f414610aff578063de66b4c414610b1e578063de88a3ba14610b31578063deaec42c14610b44578063e1aaa2fa14610b57578063e1cdc6f714610b6a578063e681204114610b8a578063e985e9c514610baa578063eb20feab14610bbd578063ec3bc7b114610bd0578063ecd8966414610be3578063f26716c514610c03578063f2fde38b14610c0b578063f3e3f99414610c1e575b600080fd5b61046361045e3660046149c6565b610c27565b60405190151581526020015b60405180910390f35b610480610c79565b60405161046f9190614d9e565b6104a061049b366004614c45565b610d0b565b60405161046f9190614d10565b6104c06104bb366004614c77565b610d32565b60405190815260200161046f565b6104e16104dc36600461497d565b610d63565b005b6104c0603c5481565b6104c060365481565b6104e161050336600461481c565b610dc3565b600f546104a0906001600160a01b031681565b6104e161052936600461488f565b610e39565b6104c061053c366004614c77565b610e57565b6104e161054f366004614c77565b610e73565b6104e161056236600461481c565b610f34565b6104c060175481565b61048061057e366004614c45565b610f74565b6104c0610591366004614c77565b61100e565b6104e16105a436600461488f565b61102a565b6104c06105b7366004614c45565b60236020526000908152604090205481565b6104c06105d7366004614c45565b60226020526000908152604090205481565b600d546104a0906001600160a01b031681565b6104e161060a366004614c77565b611045565b6104e161061d36600461481c565b61109c565b6104c060145481565b6104c0610639366004614c45565b60286020526000908152604090205481565b6104c0610659366004614c45565b60246020526000908152604090205481565b6104e1610679366004614a00565b6110a4565b6104c061068c36600461481c565b60386020526000908152604090205481565b6104e16106ac366004614bb6565b611114565b6104c06106bf366004614c77565b61176f565b6104a06106d2366004614c45565b61178b565b6104c060155481565b6104e16106ee366004614ad2565b6117ac565b6104c0610701366004614c45565b603a6020526000908152604090205481565b6104c0612129565b6104e161072936600461481c565b612139565b6104c061073c366004614c45565b60256020526000908152604090205481565b6104c061075c36600461481c565b61217b565b6104c061076f366004614c77565b6121ac565b6104e16121c8565b6104e161078a366004614c77565b6121dc565b61046361079d36600461481c565b603b6020526000908152604090205460ff1681565b6104e16107c0366004614c77565b612233565b6104e16107d3366004614c77565b61228a565b6104c06107e636600461481c565b60396020526000908152604090205481565b6104c0610806366004614c45565b60266020526000908152604090205481565b6104c061082636600461497d565b6122e1565b610480610839366004614c45565b6122fd565b6104c060195481565b6104e1610855366004614c77565b612316565b6104c0610868366004614c77565b61236d565b6104c061087b366004614c45565b60336020526000908152604090205481565b6104c06801f399b1438a10000081565b6104a0612389565b600c546104a0906001600160a01b031681565b6104c06108c6366004614c45565b60216020526000908152604090205481565b6104c06108e6366004614c77565b612398565b6104e16108f936600461497d565b6123b4565b610480612445565b600e546104a0906001600160a01b031681565b6104e161092736600461497d565b612454565b6104e161093a36600461481c565b612555565b6104e161094d36600461494f565b61258e565b6104e1610960366004614c77565b612599565b6104c0610973366004614c45565b601e6020526000908152604090205481565b6104c06729a2241af62c000081565b6012546104a0906001600160a01b031681565b6104e16109b53660046148d0565b6125f0565b6010546104a0906001600160a01b031681565b6104c06109db36600461481c565b60076020526000908152604090205481565b6104a0739060723c22de586c2fa5efa07a7743f6f4a935f581565b6104c067a688906bd8b0000081565b6013546104a0906001600160a01b031681565b610463610a3836600461481c565b601a6020526000908152604090205460ff1681565b610480610a5b366004614c45565b61260f565b6104c0610a6e366004614c77565b61261a565b6104c0610a81366004614c45565b60296020526000908152604090205481565b6104e1610aa1366004614c77565b612636565b6104c0610ab436600461481c565b603d6020526000908152604090205481565b6104c0610ad436600461481c565b61268d565b610480610ae7366004614c45565b61270e565b610463610afa366004614c45565b612727565b6104c0610b0d366004614c45565b602080526000908152604090205481565b6104e1610b2c366004614c77565b6128c4565b6011546104a0906001600160a01b031681565b600b546104a0906001600160a01b031681565b610480610b65366004614c45565b61291b565b6104c0610b78366004614c45565b60276020526000908152604090205481565b6104c0610b9836600461481c565b60376020526000908152604090205481565b610463610bb8366004614856565b612934565b6104c0610bcb366004614c77565b612962565b6104e1610bde36600461481c565b61297e565b6104c0610bf1366004614c45565b60346020526000908152604090205481565b6104e16129c0565b6104e1610c1936600461481c565b612aee565b6104c060355481565b60006001600160e01b031982166380ac58cd60e01b1480610c5857506001600160e01b03198216635b5e139f60e01b145b80610c7357506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060008054610c8890614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb490614e71565b8015610d015780601f10610cd657610100808354040283529160200191610d01565b820191906000526020600020905b815481529060010190602001808311610ce457829003601f168201915b5050505050905090565b6000610d1682612b2e565b506000908152600460205260409020546001600160a01b031690565b602f6020528160005260406000208181548110610d4e57600080fd5b90600052602060002001600091509150505481565b6000610d6e8261178b565b9050806001600160a01b0316836001600160a01b03161415610d8f57600080fd5b336001600160a01b0382161480610dab5750610dab8133612934565b610db457600080fd5b610dbe8383612b40565b505050565b600c546040516337f9ed1360e01b81526001600160a01b03909116906337f9ed1390610df3908490600401614d10565b600060405180830381600087803b158015610e0d57600080fd5b505af1158015610e21573d6000803e3d6000fd5b50505050610e2d612bae565b610e3681612d6b565b50565b610e433382612ecb565b610e4c57600080fd5b610dbe838383612f2a565b602c6020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b03163314610e89575050565b60008281526030602052604090819020600a5491516332bedefb60e21b815290916001600160a01b03169063cafb7bec90610eca9086908690600401614db1565b60206040518083038186803b158015610ee257600080fd5b505afa158015610ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190614c5e565b815460018101835560009283526020909220909101555050565b33739060723c22de586c2fa5efa07a7743f6f4a935f514610f525750565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b601f6020526000908152604090208054610f8d90614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054610fb990614e71565b80156110065780601f10610fdb57610100808354040283529160200191611006565b820191906000526020600020905b815481529060010190602001808311610fe957829003601f168201915b505050505081565b602a6020528160005260406000208181548110610d4e57600080fd5b610dbe838383604051806020016040528060008152506125f0565b600b546001600160a01b0316331461105b575050565b6000828152602b602052604090819020600a5491516348edffbd60e11b815290916001600160a01b0316906391dbff7a90610eca9086908690600401614db1565b610e2d612bae565b33739060723c22de586c2fa5efa07a7743f6f4a935f5146110c457600080fd5b600f80546001600160a01b039586166001600160a01b0319918216179091556011805494861694821694909417909355601080549285169284169290921790915560128054919093169116179055565b61111d8161178b565b6001600160a01b0316336001600160a01b03161461113a57600080fd5b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd9061117790339030906801f399b1438a10000090600401614d24565b602060405180830381600087803b15801561119157600080fd5b505af11580156111a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c991906149a9565b50600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611206903390309067a688906bd8b0000090600401614d24565b602060405180830381600087803b15801561122057600080fd5b505af1158015611234573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125891906149a9565b50600d5460135460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92611297929116906729a2241af62c000090600401614d85565b602060405180830381600087803b1580156112b157600080fd5b505af11580156112c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e991906149a9565b506000818152601b60209081526040909120855161130992870190614725565b506000818152601c60209081526040909120845161132992860190614725565b506000818152601d60209081526040909120835161134992850190614725565b506729a2241af62c0000603560008282546113649190614e16565b9091555050600f546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156113b657600080fd5b505af11580156113ca573d6000803e3d6000fd5b5050600d54600f5460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb935061140d92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561142757600080fd5b505af115801561143b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145f91906149a9565b506010546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156114ad57600080fd5b505af11580156114c1573d6000803e3d6000fd5b5050600c5460105460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb935061150492909116906753444835ec58000090600401614d85565b602060405180830381600087803b15801561151e57600080fd5b505af1158015611532573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155691906149a9565b506012546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b1580156115a457600080fd5b505af11580156115b8573d6000803e3d6000fd5b5050600c5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb93506115fb92909116906753444835ec58000090600401614d85565b602060405180830381600087803b15801561161557600080fd5b505af1158015611629573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164d91906149a9565b506011546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b15801561169b57600080fd5b505af11580156116af573d6000803e3d6000fd5b5050600d5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb93506116f292909116906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561170c57600080fd5b505af1158015611720573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174491906149a9565b5060008181526033602052604081205461176091839190613033565b61176933610dc3565b50505050565b60316020528160005260406000208181548110610d4e57600080fd5b600080611797836131e3565b90506001600160a01b038116610c7357600080fd5b600060076000600c60009054906101000a90046001600160a01b03166001600160a01b031663b1ea10336040518163ffffffff1660e01b815260040160206040518083038186803b15801561180057600080fd5b505afa158015611814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118389190614839565b6001600160a01b031681526020810191909152604001600020549050821561185d5750815b80611866575060085b601654811061187457600080fd5b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906118b190339030906801f399b1438a10000090600401614d24565b602060405180830381600087803b1580156118cb57600080fd5b505af11580156118df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190391906149a9565b50600c546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611940903390309067a688906bd8b0000090600401614d24565b602060405180830381600087803b15801561195a57600080fd5b505af115801561196e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199291906149a9565b50600d5460135460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb926119d1929116906729a2241af62c000090600401614d85565b602060405180830381600087803b1580156119eb57600080fd5b505af11580156119ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2391906149a9565b50611a2d33612d6b565b600e543360009081526007602052604090819020549051633d9fa62360e01b81526001600160a01b0390921691633d9fa62391611a709160040190815260200190565b600060405180830381600087803b158015611a8a57600080fd5b505af1158015611a9e573d6000803e3d6000fd5b505050506000611aad60165490565b9050611abd601680546001019055565b611ac733826131fe565b611ad18187613218565b6000818152601b602090815260409091208a51611af0928c0190614725565b506000818152601c602090815260409091208951611b10928b0190614725565b506000818152601d602090815260409091208851611b30928a0190614725565b506000818152603360209081526040808320859055601f82529091208651611b5a92880190614725565b506000818152601e602090815260408083208690553383526007909152902054611b91573360009081526007602052604090208190555b3360009081526006602090815260408220805460018101825590835290822001829055603580546729a2241af62c00009290611bce908490614e16565b90915550506010546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611c2057600080fd5b505af1158015611c34573d6000803e3d6000fd5b5050600c5460105460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611c7792909116906753444835ec58000090600401614d85565b602060405180830381600087803b158015611c9157600080fd5b505af1158015611ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc991906149a9565b50600f546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611d1757600080fd5b505af1158015611d2b573d6000803e3d6000fd5b5050600d54600f5460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611d6e92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b158015611d8857600080fd5b505af1158015611d9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc091906149a9565b506012546040516368bf759760e01b81526753444835ec58000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611e0e57600080fd5b505af1158015611e22573d6000803e3d6000fd5b5050600c5460125460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611e6592909116906753444835ec58000090600401614d85565b602060405180830381600087803b158015611e7f57600080fd5b505af1158015611e93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb791906149a9565b506011546040516368bf759760e01b81526729a2241af62c000060048201526001600160a01b03909116906368bf759790602401600060405180830381600087803b158015611f0557600080fd5b505af1158015611f19573d6000803e3d6000fd5b5050600d5460115460405163a9059cbb60e01b81526001600160a01b03928316945063a9059cbb9350611f5c92909116906729a2241af62c000090600401614d85565b602060405180830381600087803b158015611f7657600080fd5b505af1158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae91906149a9565b50611fbb81836001613033565b611fc433610dc3565b603a6000600c60009054906101000a90046001600160a01b03166001600160a01b0316636190c9d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561201657600080fd5b505afa15801561202a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204e9190614c5e565b8152602001908152602001600020600081548092919061206d90614eac565b9091555050336000908152603b602052604090205460ff166120b757336000908152603b60205260408120805460ff19166001179055603c8054916120b183614eac565b91905055505b60405133906120c7908990614cc5565b60405180910390208a6040516120dd9190614cc5565b60405180910390207f348a2af61c3e551d263eaa8735e61cbaaa4dbbcde2de30c684dd75431e5088d78442604051612116929190614db1565b60405180910390a4505050505050505050565b600061213460165490565b905090565b33739060723c22de586c2fa5efa07a7743f6f4a935f51461215957600080fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b03821661219057600080fd5b506001600160a01b031660009081526003602052604090205490565b602e6020528160005260406000208181548110610d4e57600080fd5b6121d0613249565b6121da6000613265565b565b600b546001600160a01b031633146121f2575050565b6000828152602e602052604090819020600a5491516370c7038360e01b815290916001600160a01b0316906370c7038390610eca9086908690600401614db1565b600b546001600160a01b03163314612249575050565b6000828152602d602052604090819020600a54915163895694bf60e01b815290916001600160a01b03169063895694bf90610eca9086908690600401614db1565b600b546001600160a01b031633146122a0575050565b60008281526032602052604090819020600a54915163eb20feab60e01b815290916001600160a01b03169063eb20feab90610eca9086908690600401614db1565b60066020528160005260406000208181548110610d4e57600080fd5b601d6020526000908152604090208054610f8d90614e71565b600b546001600160a01b0316331461232c575050565b6000828152602a602052604090819020600a5491516307d5656960e31b815290916001600160a01b031690633eab2b4890610eca9086908690600401614db1565b602d6020528160005260406000208181548110610d4e57600080fd5b6009546001600160a01b031690565b602b6020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b031633146123ca575050565b6123d3816132b7565b6001600160a01b03821660009081526006602090815260408220805460018101825590835291200181905561240882826131fe565b6001600160a01b038216600090815260076020526040902054612441576001600160a01b03821660009081526007602052604090208190555b5050565b606060018054610c8890614e71565b60165481111561246357600080fd5b61246c8161178b565b6001600160a01b0316336001600160a01b031614806124955750600b546001600160a01b031633145b6124f55760405162461bcd60e51b815260206004820152602760248201527f57616c6c6574206e6f74207175616c696669656420746f207365744661766f756044820152661c9a5d1953919560ca1b606482015260840160405180910390fd5b6001600160a01b03821660009081526007602052604090819020805490839055905133907ff1920cbfe18dff4155b1e46e979d6d82313c39f04760c14fbb8f37a21b36e912906125489084908690614db1565b60405180910390a2505050565b6013546001600160a01b0316331461256c57600080fd5b601380546001600160a01b0319166001600160a01b0392909216919091179055565b612441338383613bf9565b600b546001600160a01b031633146125af575050565b6000828152602f602052604090819020600a5491516308a1f67f60e01b815290916001600160a01b0316906308a1f67f90610eca9086908690600401614db1565b6125fa3383612ecb565b61260357600080fd5b61176984848484613c85565b6060610c7382613ca5565b60306020528160005260406000208181548110610d4e57600080fd5b600b546001600160a01b0316331461264c575050565b60008281526031602052604090819020600a549151630c69bbfb60e31b815290916001600160a01b03169063634ddfd890610eca9086908690600401614db1565b600c546040516370a0823160e01b81526000916001600160a01b0316906370a08231906126be908590600401614d10565b60206040518083038186803b1580156126d657600080fd5b505afa1580156126ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c739190614c5e565b601b6020526000908152604090208054610f8d90614e71565b600c546000906001600160a01b0316637ba14d8c6127448461178b565b6040518263ffffffff1660e01b81526004016127609190614d10565b60206040518083038186803b15801561277857600080fd5b505afa15801561278c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b091906149a9565b80610c735750600c546001600160a01b0316636252b6fd6127d08461178b565b600c5460408051636190c9d560e01b815290516001926001600160a01b031691636190c9d5916004808301926020929190829003018186803b15801561281557600080fd5b505afa158015612829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284d9190614c5e565b6128579190614e2e565b6040518363ffffffff1660e01b8152600401612874929190614d85565b60206040518083038186803b15801561288c57600080fd5b505afa1580156128a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7391906149a9565b600b546001600160a01b031633146128da575050565b6000828152602c602052604090819020600a5491516314bf03b160e11b815290916001600160a01b03169063297e076290610eca9086908690600401614db1565b601c6020526000908152604090208054610f8d90614e71565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60326020528160005260406000208181548110610d4e57600080fd5b33739060723c22de586c2fa5efa07a7743f6f4a935f51461299e57600080fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b031633146129d457565b6000805b6009811015612441576013546129f7906001600160a01b0316826131fe565b612a00816132b7565b600a5460405163d940848960e01b8152600481018390526001600160a01b039091169063d94084899060240160206040518083038186803b158015612a4457600080fd5b505afa158015612a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7c9190614c5e565b612a869083614e16565b6013546001600160a01b03166000908152600660209081526040808320805460018101825590845292829020909201849055815160608101909252603c808352929450612adc92849291614f5990830139613218565b80612ae681614eac565b9150506129d8565b612af6613249565b6001600160a01b038116612b0957600080fd5b610e3681613265565b5490565b80546001019055565b6001600160a01b03163b151590565b612b3781613dae565b610e3657600080fd5b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612b758261178b565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6015544211156121da57600f60009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c0857600080fd5b505af1158015612c1c573d6000803e3d6000fd5b50505050601060009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c7057600080fd5b505af1158015612c84573d6000803e3d6000fd5b50505050601160009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612cd857600080fd5b505af1158015612cec573d6000803e3d6000fd5b50505050601260009054906101000a90046001600160a01b03166001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612d4057600080fd5b505af1158015612d54573d6000803e3d6000fd5b5050505060145442612d669190614e16565b601555565b6001600160a01b0381166000908152601a602052604090205460ff1615612deb576001600160a01b0381166000908152603d60205260408120546019805491929091612db8908490614e2e565b90915550506001600160a01b0381166000908152603d60209081526040808320839055601a9091529020805460ff191690555b600c54604051631ee8536360e21b81526001600160a01b0390911690637ba14d8c90612e1b908490600401614d10565b60206040518083038186803b158015612e3357600080fd5b505afa158015612e47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6b91906149a9565b15610e3657612e798161217b565b60196000828254612e8a9190614e16565b90915550612e9990508161217b565b6001600160a01b0382166000908152603d6020908152604080832093909355601a905220805460ff1916600117905550565b600080612ed78361178b565b9050806001600160a01b0316846001600160a01b03161480612efe5750612efe8185612934565b80612f225750836001600160a01b0316612f1784610d0b565b6001600160a01b0316145b949350505050565b826001600160a01b0316612f3d8261178b565b6001600160a01b031614612f5057600080fd5b6001600160a01b038216612f6357600080fd5b826001600160a01b0316612f768261178b565b6001600160a01b031614612f8957600080fd5b600081815260046020526040902080546001600160a01b0319169055612faf8184613dcb565b6001600160a01b03831660009081526003602052604090208054600019019055612fd98183613f8c565b6001600160a01b03808316600081815260036020908152604080832080546001019055858352600290915280822080546001600160a01b03191684179055518493871691600080516020614f9583398151915291a4505050565b6000805b60098110156131dc57821561305157613051818686613fe0565b61305a8461178b565b6001600160a01b038116600090815260376020526040812080549294506729a2241af62c00009290919061308f908490614e16565b9091555050600084815260346020526040812080546729a2241af62c000092906130ba908490614e16565b925050819055506729a2241af62c0000603660008282546130db9190614e16565b9091555050600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061311a9085906729a2241af62c000090600401614d85565b602060405180830381600087803b15801561313457600080fd5b505af1158015613148573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316c91906149a9565b5042826001600160a01b03167fa421b4aced6f4fcb40d755e461bb29417a90636ae4f2769ff2cb29db7eab7994866729a2241af62c00006040516131b1929190614db1565b60405180910390a36000938452603360205260409093205492806131d481614eac565b915050613037565b5050505050565b6000908152600260205260409020546001600160a01b031690565b61244182826040518060200160405280600081525061438c565b61322182613dae565b61322a57600080fd5b60008281526008602090815260409091208251610dbe92840190614725565b33613252612389565b6001600160a01b0316146121da57600080fd5b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600a54604051636d3a6ba160e11b8152600481018390526001600160a01b039091169063da74d7429060240160006040518083038186803b1580156132fb57600080fd5b505afa15801561330f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133379190810190614a5c565b6000828152601b60209081526040909120825161335a9391929190910190614725565b50600a546040516370d5517d60e11b8152600481018390526001600160a01b039091169063e1aaa2fa9060240160006040518083038186803b15801561339f57600080fd5b505afa1580156133b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133db9190810190614a5c565b6000828152601c6020908152604090912082516133fe9391929190910190614725565b50600a546040516382d706ad60e01b8152600481018390526001600160a01b03909116906382d706ad9060240160006040518083038186803b15801561344357600080fd5b505afa158015613457573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261347f9190810190614a5c565b6000828152601d6020908152604090912082516134a29391929190910190614725565b50600a54604051632994eff760e21b8152600481018390526001600160a01b039091169063a653bfdc9060240160206040518083038186803b1580156134e757600080fd5b505afa1580156134fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351f9190614c5e565b6000828152601e60205260409081902091909155600a549051633c1bd08360e01b8152600481018390526001600160a01b0390911690633c1bd0839060240160006040518083038186803b15801561357657600080fd5b505afa15801561358a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135b29190810190614a5c565b6000828152601f6020908152604090912082516135d59391929190910190614725565b50600a54604051632355e47760e21b8152600481018390526001600160a01b0390911690638d5791dc9060240160206040518083038186803b15801561361a57600080fd5b505afa15801561362e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136529190614c5e565b6000828152603360205260409081902091909155600a5490516336b6593d60e21b8152600481018390526001600160a01b039091169063dad964f49060240160206040518083038186803b1580156136a957600080fd5b505afa1580156136bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e19190614c5e565b60008281526020805260409081902091909155600a549051634883705f60e11b8152600481018390526001600160a01b0390911690639106e0be9060240160206040518083038186803b15801561373757600080fd5b505afa15801561374b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376f9190614c5e565b6000828152602160205260409081902091909155600a54905163235e704b60e11b8152600481018390526001600160a01b03909116906346bce0969060240160206040518083038186803b1580156137c657600080fd5b505afa1580156137da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137fe9190614c5e565b6000828152602260205260409081902091909155600a54905163110f02a960e21b8152600481018390526001600160a01b039091169063443c0aa49060240160206040518083038186803b15801561385557600080fd5b505afa158015613869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388d9190614c5e565b6000828152602360205260409081902091909155600a549051635616f32560e01b8152600481018390526001600160a01b0390911690635616f3259060240160206040518083038186803b1580156138e457600080fd5b505afa1580156138f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391c9190614c5e565b60008281526024602081905260409182902092909255600a54905163706e2dfd60e01b8152600481018490526001600160a01b039091169163706e2dfd910160206040518083038186803b15801561397357600080fd5b505afa158015613987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ab9190614c5e565b6000828152602560205260409081902091909155600a5490516381c9db7760e01b8152600481018390526001600160a01b03909116906381c9db779060240160206040518083038186803b158015613a0257600080fd5b505afa158015613a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a3a9190614c5e565b6000828152602660205260409081902091909155600a54905163e1cdc6f760e01b8152600481018390526001600160a01b039091169063e1cdc6f79060240160206040518083038186803b158015613a9157600080fd5b505afa158015613aa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac99190614c5e565b6000828152602760205260409081902091909155600a54905163053294b760e41b8152600481018390526001600160a01b03909116906353294b709060240160206040518083038186803b158015613b2057600080fd5b505afa158015613b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b589190614c5e565b6000828152602860205260409081902091909155600a5490516365cf916360e11b8152600481018390526001600160a01b039091169063cb9f22c69060240160206040518083038186803b158015613baf57600080fd5b505afa158015613bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613be79190614c5e565b60009182526029602052604090912055565b816001600160a01b0316836001600160a01b03161415613c1857600080fd5b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613c90848484612f2a565b613c9c848484846143ac565b61176957600080fd5b6060613cb082612b2e565b60008281526008602052604081208054613cc990614e71565b80601f0160208091040260200160405190810160405280929190818152602001828054613cf590614e71565b8015613d425780601f10613d1757610100808354040283529160200191613d42565b820191906000526020600020905b815481529060010190602001808311613d2557829003601f168201915b505050505090506000613d6060408051602081019091526000815290565b9050805160001415613d73575092915050565b815115613da5578082604051602001613d8d929190614ce1565b60405160208183030381529060405292505050919050565b612f22846144ad565b600080613dba836131e3565b6001600160a01b0316141592915050565b60005b6001600160a01b0382166000908152600660205260409020805484919083908110613dfb57613dfb614ef3565b906000526020600020015414613e1d5780613e1581614eac565b915050613dce565b6001600160a01b038216600090815260036020526040902054613e4290600190614e2e565b811015613edb576001600160a01b0382166000908152600660205260409020613e6c826001614e16565b81548110613e7c57613e7c614ef3565b906000526020600020015460066000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110613ebd57613ebd614ef3565b60009182526020909120015580613ed381614eac565b915050613e1d565b6001600160a01b0382166000908152600660205260409020805480613f0257613f02614edd565b6000828152602080822083016000199081018390559092019092556001600160a01b0384168252600790526040902054831415610dbe576001600160a01b03821660009081526006602052604081208054909190613f6257613f62614ef3565b60009182526020808320909101546001600160a01b03851683526007909152604090912055505050565b6001600160a01b0381166000818152600660209081526040808320805460018101825590845282842001869055928252600790522054612441576001600160a01b0316600090815260076020526040902055565b826140445760008181526020805260408120805491613ffe83614eac565b9091555050600081815260296020526040812080549161401d83614eac565b90915550506000908152602a60209081526040822080546001810182559083529120015550565b82600114156140ad57600081815260216020526040812080549161406783614eac565b9091555050600081815260296020526040812080549161408683614eac565b90915550506000908152602b60209081526040822080546001810182559083529120015550565b82600214156141165760008181526022602052604081208054916140d083614eac565b909155505060008181526029602052604081208054916140ef83614eac565b90915550506000908152602c60209081526040822080546001810182559083529120015550565b826003141561417f57600081815260236020526040812080549161413983614eac565b9091555050600081815260296020526040812080549161415883614eac565b90915550506000908152602d60209081526040822080546001810182559083529120015550565b82600414156141e85760008181526024602052604081208054916141a283614eac565b909155505060008181526029602052604081208054916141c183614eac565b90915550506000908152602e60209081526040822080546001810182559083529120015550565b826005141561425157600081815260256020526040812080549161420b83614eac565b9091555050600081815260296020526040812080549161422a83614eac565b90915550506000908152602f60209081526040822080546001810182559083529120015550565b82600614156142ba57600081815260266020526040812080549161427483614eac565b9091555050600081815260296020526040812080549161429383614eac565b90915550506000908152603060209081526040822080546001810182559083529120015550565b82600714156143235760008181526027602052604081208054916142dd83614eac565b909155505060008181526029602052604081208054916142fc83614eac565b90915550506000908152603160209081526040822080546001810182559083529120015550565b8260081415610dbe57600081815260286020526040812080549161434683614eac565b9091555050600081815260296020526040812080549161436583614eac565b90915550506000908152603260209081526040822080546001810182559083529120015550565b6143968383614521565b6143a360008484846143ac565b610dbe57600080fd5b60006143c0846001600160a01b0316612b1f565b156144a257604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906143f7903390899088908890600401614d48565b602060405180830381600087803b15801561441157600080fd5b505af1925050508015614441575060408051601f3d908101601f1916820190925261443e918101906149e3565b60015b614488573d80801561446f576040519150601f19603f3d011682016040523d82523d6000602084013e614474565b606091505b50805161448057600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612f22565b506001949350505050565b60606144b882612b2e565b60006144cf60408051602081019091526000815290565b905060008151116144ef576040518060200160405280600081525061451a565b806144f9846145b3565b60405160200161450a929190614ce1565b6040516020818303038152906040525b9392505050565b6001600160a01b03821661453457600080fd5b61453d81613dae565b1561454757600080fd5b61455081613dae565b1561455a57600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020614f95833981519152908290a45050565b606060006145c08361464f565b60010190506000816001600160401b038111156145df576145df614f09565b6040519080825280601f01601f191660200182016040528015614609576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461464257614647565b614613565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061468e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106146b8576904ee2d6d415b85acef8160201b830492506020015b662386f26fc1000083106146d657662386f26fc10000830492506010015b6305f5e10083106146ee576305f5e100830492506008015b612710831061470257612710830492506004015b60648310614714576064830492506002015b600a8310610c735760010192915050565b82805461473190614e71565b90600052602060002090601f0160209004810192826147535760008555614799565b82601f1061476c57805160ff1916838001178555614799565b82800160010185558215614799579182015b8281111561479957825182559160200191906001019061477e565b506147a59291506147a9565b5090565b5b808211156147a557600081556001016147aa565b60006147d16147cc84614def565b614dbf565b90508281528383830111156147e557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261480d57600080fd5b61451a838335602085016147be565b60006020828403121561482e57600080fd5b813561451a81614f1f565b60006020828403121561484b57600080fd5b815161451a81614f1f565b6000806040838503121561486957600080fd5b823561487481614f1f565b9150602083013561488481614f1f565b809150509250929050565b6000806000606084860312156148a457600080fd5b83356148af81614f1f565b925060208401356148bf81614f1f565b929592945050506040919091013590565b600080600080608085870312156148e657600080fd5b84356148f181614f1f565b9350602085013561490181614f1f565b92506040850135915060608501356001600160401b0381111561492357600080fd5b8501601f8101871361493457600080fd5b614943878235602084016147be565b91505092959194509250565b6000806040838503121561496257600080fd5b823561496d81614f1f565b9150602083013561488481614f34565b6000806040838503121561499057600080fd5b823561499b81614f1f565b946020939093013593505050565b6000602082840312156149bb57600080fd5b815161451a81614f34565b6000602082840312156149d857600080fd5b813561451a81614f42565b6000602082840312156149f557600080fd5b815161451a81614f42565b60008060008060808587031215614a1657600080fd5b8435614a2181614f1f565b93506020850135614a3181614f1f565b92506040850135614a4181614f1f565b91506060850135614a5181614f1f565b939692955090935050565b600060208284031215614a6e57600080fd5b81516001600160401b03811115614a8457600080fd5b8201601f81018413614a9557600080fd5b8051614aa36147cc82614def565b818152856020838501011115614ab857600080fd5b614ac9826020830160208601614e45565b95945050505050565b600080600080600080600060e0888a031215614aed57600080fd5b87356001600160401b0380821115614b0457600080fd5b614b108b838c016147fc565b985060208a0135915080821115614b2657600080fd5b614b328b838c016147fc565b975060408a0135915080821115614b4857600080fd5b614b548b838c016147fc565b965060608a0135915080821115614b6a57600080fd5b614b768b838c016147fc565b955060808a0135915080821115614b8c57600080fd5b50614b998a828b016147fc565b93505060a0880135915060c0880135905092959891949750929550565b60008060008060808587031215614bcc57600080fd5b84356001600160401b0380821115614be357600080fd5b614bef888389016147fc565b95506020870135915080821115614c0557600080fd5b614c11888389016147fc565b94506040870135915080821115614c2757600080fd5b50614c34878288016147fc565b949793965093946060013593505050565b600060208284031215614c5757600080fd5b5035919050565b600060208284031215614c7057600080fd5b5051919050565b60008060408385031215614c8a57600080fd5b50508035926020909101359150565b60008151808452614cb1816020860160208601614e45565b601f01601f19169290920160200192915050565b60008251614cd7818460208701614e45565b9190910192915050565b60008351614cf3818460208801614e45565b835190830190614d07818360208801614e45565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614d7b90830184614c99565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b60208152600061451a6020830184614c99565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715614de757614de7614f09565b604052919050565b60006001600160401b03821115614e0857614e08614f09565b50601f01601f191660200190565b60008219821115614e2957614e29614ec7565b500190565b600082821015614e4057614e40614ec7565b500390565b60005b83811015614e60578181015183820152602001614e48565b838111156117695750506000910152565b600181811c90821680614e8557607f821691505b60208210811415614ea657634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415614ec057614ec0614ec7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e3657600080fd5b8015158114610e3657600080fd5b6001600160e01b031981168114610e3657600080fdfe697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f302e6a736f6eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220f0db85a3c35611b4775d04f5137da082f4100840cb359a55c06f20ea969e65d564736f6c63430008070033
Deployed Bytecode Sourcemap
156973:24011:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30051:321;;;;;;:::i;:::-;;:::i;:::-;;;12012:14:1;;12005:22;11987:41;;11975:2;11960:18;30051:321:0;;;;;;;;30954:100;;;:::i;:::-;;;;;;;:::i;32390:187::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;161926:61::-;;;;;;:::i;:::-;;:::i;:::-;;;13113:25:1;;;13101:2;13086:18;161926:61:0;12941:203:1;32047:277:0;;;;;;:::i;:::-;;:::i;:::-;;162830:28;;;;;;162467:43;;;;;;175135:161;;;;;;:::i;:::-;;:::i;158181:94::-;;;;;-1:-1:-1;;;;;158181:94:0;;;33156:286;;;;;;:::i;:::-;;:::i;161718:63::-;;;;;;:::i;:::-;;:::i;167644:283::-;;;;;;:::i;:::-;;:::i;163475:180::-;;;;;;:::i;:::-;;:::i;159027:30::-;;;;;;160521:51;;;;;;:::i;:::-;;:::i;161577:63::-;;;;;;:::i;:::-;;:::i;33513:185::-;;;;;;:::i;:::-;;:::i;160913:66::-;;;;;;:::i;:::-;;;;;;;;;;;;;;160839:67;;;;;;:::i;:::-;;;;;;;;;;;;;;157957:69;;;;;-1:-1:-1;;;;;157957:69:0;;;166198:286;;;;;;:::i;:::-;;:::i;175304:124::-;;;;;;:::i;:::-;;:::i;158848:30::-;;;;;;161279:66;;;;;;:::i;:::-;;;;;;;;;;;;;;160986;;;;;;:::i;:::-;;;;;;;;;;;;;;173043:401;;;;;;:::i;:::-;;:::i;162582:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;171341:1375;;;;;;:::i;:::-;;:::i;162064:63::-;;;;;;:::i;:::-;;:::i;30676:211::-;;;;;;:::i;:::-;;:::i;158885:31::-;;;;;;168526:2807;;;;;;:::i;:::-;;:::i;162701:56::-;;;;;;:::i;:::-;;;;;;;;;;;;;;172747:107;;;:::i;175597:142::-;;;;;;:::i;:::-;;:::i;161059:65::-;;;;;;:::i;:::-;;;;;;;;;;;;;;30436:178;;;;;;:::i;:::-;;:::i;161857:62::-;;;;;;:::i;:::-;;:::i;49445:103::-;;;:::i;167071:280::-;;;;;;:::i;:::-;;:::i;162782:41::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;166783:280;;;;;;:::i;:::-;;:::i;168226:::-;;;;;;:::i;:::-;;:::i;162641:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;161131:67;;;;;;:::i;:::-;;;;;;;;;;;;;;29592:48;;;;;;:::i;:::-;;:::i;160391:56::-;;;;;;:::i;:::-;;:::i;160191:29::-;;;;;;165907:283;;;;;;:::i;:::-;;:::i;161788:62::-;;;;;;:::i;:::-;;:::i;162235:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;157052:40;;157084:8;157052:40;;48833:87;;;:::i;157881:69::-;;;;;-1:-1:-1;;;;;157881:69:0;;;160764:68;;;;;;:::i;:::-;;;;;;;;;;;;;;161647:64;;;;;;:::i;:::-;;:::i;163663:349::-;;;;;;:::i;:::-;;:::i;31123:104::-;;;:::i;158053:95::-;;;;;-1:-1:-1;;;;;158053:95:0;;;173452:412;;;;;;:::i;:::-;;:::i;173872:156::-;;;;;;:::i;:::-;;:::i;32649:180::-;;;;;;:::i;:::-;;:::i;167359:277::-;;;;;;:::i;:::-;;:::i;160454:60::-;;;;;;:::i;:::-;;;;;;;;;;;;;;157198:48;;157239:7;157198:48;;158541:96;;;;;-1:-1:-1;;;;;158541:96:0;;;33769:273;;;;;;:::i;:::-;;:::i;158282:94::-;;;;;-1:-1:-1;;;;;158282:94:0;;;29647:48;;;;;;:::i;:::-;;;;;;;;;;;;;;158744:95;;158797:42;158744:95;;157099:45;;157136:8;157099:45;;158662:75;;;;;-1:-1:-1;;;;;158662:75:0;;;160227:44;;;;;;:::i;:::-;;;;;;;;;;;;;;;;180810:171;;;;;;:::i;:::-;;:::i;161994:63::-;;;;;;:::i;:::-;;:::i;161354:62::-;;;;;;:::i;:::-;;;;;;;;;;;;;;167935:283;;;;;;:::i;:::-;;:::i;162880:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;175436:118;;;;;;:::i;:::-;;:::i;160278:46::-;;;;;;:::i;:::-;;:::i;174053:217::-;;;;;;:::i;:::-;;:::i;160690:67::-;;;;;;:::i;:::-;;;;;;;;;;;;;;166492:283;;;;;;:::i;:::-;;:::i;158438:96::-;;;;;-1:-1:-1;;;;;158438:96:0;;;157757:99;;;;;-1:-1:-1;;;;;157757:99:0;;;160331:53;;;;;;:::i;:::-;;:::i;161205:67::-;;;;;;:::i;:::-;;;;;;;;;;;;;;162517:58;;;;;;:::i;:::-;;;;;;;;;;;;;;32900:189;;;;;;:::i;:::-;;:::i;162134:62::-;;;;;;:::i;:::-;;:::i;172884:151::-;;;;;;:::i;:::-;;:::i;162312:63::-;;;;;;:::i;:::-;;;;;;;;;;;;;;176624:695;;;:::i;49703:159::-;;;;;;:::i;:::-;;:::i;162402:37::-;;;;;;30051:321;30169:4;-1:-1:-1;;;;;;30206:40:0;;-1:-1:-1;;;30206:40:0;;:105;;-1:-1:-1;;;;;;;30263:48:0;;-1:-1:-1;;;30263:48:0;30206:105;:158;;;-1:-1:-1;;;;;;;;;;28846:40:0;;;30328:36;30186:178;30051:321;-1:-1:-1;;30051:321:0:o;30954:100::-;31008:13;31041:5;31034:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30954:100;:::o;32390:187::-;32482:7;32502:23;32517:7;32502:14;:23::i;:::-;-1:-1:-1;32545:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;32545:24:0;;32390:187::o;161926:61::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;32047:277::-;32128:13;32144:23;32159:7;32144:14;:23::i;:::-;32128:39;;32192:5;-1:-1:-1;;;;;32186:11:0;:2;-1:-1:-1;;;;;32186:11:0;;;32178:20;;;;;;26114:10;-1:-1:-1;;;;;32219:21:0;;;;:62;;-1:-1:-1;32244:37:0;32261:5;26114:10;32900:189;:::i;32244:37::-;32211:71;;;;;;32295:21;32304:2;32308:7;32295:8;:21::i;:::-;32117:207;32047:277;;:::o;175135:161::-;175185:4;;:30;;-1:-1:-1;;;175185:30:0;;-1:-1:-1;;;;;175185:4:0;;;;:22;;:30;;175208:6;;175185:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175228:18;:16;:18::i;:::-;175259:29;175281:6;175259:21;:29::i;:::-;175135:161;:::o;33156:286::-;33351:41;26114:10;33384:7;33351:18;:41::i;:::-;33343:50;;;;;;33406:28;33416:4;33422:2;33426:7;33406:9;:28::i;161718:63::-;;;;;;;;;;;;;;;;;;;;167644:283;167754:17;;-1:-1:-1;;;;;167754:17:0;167732:10;:40;167728:53;;167644:283;;:::o;167728:53::-;167793:35;;;;:26;:35;;;;;;;167848:17;;:60;;-1:-1:-1;;;167848:60:0;;167793:35;;-1:-1:-1;;;;;167848:17:0;;:44;;:60;;167820:7;;167902:5;;167848:60;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;167793:126;;;;;;;-1:-1:-1;167793:126:0;;;;;;;;;;;-1:-1:-1;;167644:283:0:o;163475:180::-;163559:10;158797:42;163559:31;163555:44;;163475:180;:::o;163555:44::-;163609:17;:38;;-1:-1:-1;;;;;;163609:38:0;-1:-1:-1;;;;;163609:38:0;;;;;;;;;;163475:180::o;160521:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;161577:63::-;;;;;;;;;;;;;;;;;;;;33513:185;33651:39;33668:4;33674:2;33678:7;33651:39;;;;;;;;;;;;:16;:39::i;166198:286::-;166309:17;;-1:-1:-1;;;;;166309:17:0;166287:10;:40;166283:53;;166198:286;;:::o;166283:53::-;166348:36;;;;:27;:36;;;;;;;166404:17;;:61;;-1:-1:-1;;;166404:61:0;;166348:36;;-1:-1:-1;;;;;166404:17:0;;:45;;:61;;166376:7;;166459:5;;166404:61;;;:::i;175304:124::-;175362:18;:16;:18::i;173043:401::-;173220:10;158797:42;173220:31;173212:40;;;;;;173263:18;:33;;-1:-1:-1;;;;;173263:33:0;;;-1:-1:-1;;;;;;173263:33:0;;;;;;;173307:20;:37;;;;;;;;;;;;;;;173355:18;:33;;;;;;;;;;;;;;;173399:20;:37;;;;;;;;;;;173043:401::o;171341:1375::-;171540:17;171548:8;171540:7;:17::i;:::-;-1:-1:-1;;;;;171526:31:0;:10;-1:-1:-1;;;;;171526:31:0;;171518:40;;;;;;171571:4;;:51;;-1:-1:-1;;;171571:51:0;;-1:-1:-1;;;;;171571:4:0;;;;:17;;:51;;171589:10;;171609:4;;157084:8;;171571:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;171633:4:0;;:56;;-1:-1:-1;;;171633:56:0;;-1:-1:-1;;;;;171633:4:0;;;;:17;;:56;;171651:10;;171671:4;;157136:8;;171633:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;171748:4:0;;171762:15;;171748:46;;-1:-1:-1;;;171748:46:0;;-1:-1:-1;;;;;171748:4:0;;;;:13;;:46;;171762:15;;;157239:7;;171748:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;171834:22:0;;;;:12;:22;;;;;;;;:30;;;;;;;;:::i;:::-;-1:-1:-1;171875:29:0;;;;:19;:29;;;;;;;;:44;;;;;;;;:::i;:::-;-1:-1:-1;171930:32:0;;;;:22;:32;;;;;;;;:49;;;;;;;;:::i;:::-;;157239:7;172034:22;;:40;;;;;;;:::i;:::-;;;;-1:-1:-1;;172116:18:0;;:38;;-1:-1:-1;;;172116:38:0;;172146:7;172116:38;;;13113:25:1;-1:-1:-1;;;;;172116:18:0;;;;:29;;13086:18:1;;172116:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;172165:4:0;;172187:18;;172165:51;;-1:-1:-1;;;172165:51:0;;-1:-1:-1;;;;;172165:4:0;;;;-1:-1:-1;172165:13:0;;-1:-1:-1;172165:51:0;;172187:18;;;;172208:7;;172165:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;172229:18:0;;:38;;-1:-1:-1;;;172229:38:0;;172259:7;172229:38;;;13113:25:1;-1:-1:-1;;;;;172229:18:0;;;;:29;;13086:18:1;;172229:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;172278:4:0;;172300:18;;172278:51;;-1:-1:-1;;;172278:51:0;;-1:-1:-1;;;;;172278:4:0;;;;-1:-1:-1;172278:13:0;;-1:-1:-1;172278:51:0;;172300:18;;;;172321:7;;172278:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;172342:20:0;;:40;;-1:-1:-1;;;172342:40:0;;172374:7;172342:40;;;13113:25:1;-1:-1:-1;;;;;172342:20:0;;;;:31;;13086:18:1;;172342:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;172393:4:0;;172415:20;;172393:53;;-1:-1:-1;;;172393:53:0;;-1:-1:-1;;;;;172393:4:0;;;;-1:-1:-1;172393:13:0;;-1:-1:-1;172393:53:0;;172415:20;;;;172438:7;;172393:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;172459:20:0;;:40;;-1:-1:-1;;;172459:40:0;;172491:7;172459:40;;;13113:25:1;-1:-1:-1;;;;;172459:20:0;;;;:31;;13086:18:1;;172459:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;172510:4:0;;172532:20;;172510:53;;-1:-1:-1;;;172510:53:0;;-1:-1:-1;;;;;172510:4:0;;;;-1:-1:-1;172510:13:0;;-1:-1:-1;172510:53:0;;172532:20;;;;172555:7;;172510:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;172642:27:0;;;;:17;:27;;;;;;172621:56;;172632:8;;172642:27;172621:10;:56::i;:::-;172690:18;172697:10;172690:6;:18::i;:::-;171341:1375;;;;:::o;162064:63::-;;;;;;;;;;;;;;;;;;;;30676:211;30764:7;30784:13;30800:17;30809:7;30800:8;:17::i;:::-;30784:33;-1:-1:-1;;;;;;30836:19:0;;30828:28;;;;;168526:2807;168819:18;168840:13;:38;168854:4;;;;;;;;;-1:-1:-1;;;;;168854:4:0;-1:-1:-1;;;;;168854:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;168840:38:0;;;;;;;;;;;;-1:-1:-1;168840:38:0;;;-1:-1:-1;168895:9:0;;168891:59;;-1:-1:-1;168934:4:0;168891:59;168966:15;168962:62;;-1:-1:-1;169011:1:0;168962:62;169057:9;12625:14;169044:10;:32;169036:41;;;;;;169090:4;;:51;;-1:-1:-1;;;169090:51:0;;-1:-1:-1;;;;;169090:4:0;;;;:17;;:51;;169108:10;;169128:4;;157084:8;;169090:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;169152:4:0;;:56;;-1:-1:-1;;;169152:56:0;;-1:-1:-1;;;;;169152:4:0;;;;:17;;:56;;169170:10;;169190:4;;157136:8;;169152:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;169267:4:0;;169281:15;;169267:46;;-1:-1:-1;;;169267:46:0;;-1:-1:-1;;;;;169267:4:0;;;;:13;;:46;;169281:15;;;157239:7;;169267:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;169326:33;169348:10;169326:21;:33::i;:::-;169372:9;;169408:10;169372:9;169394:25;;;:13;:25;;;;;;;;169372:48;;-1:-1:-1;;;169372:48:0;;-1:-1:-1;;;;;169372:9:0;;;;:21;;:48;;;;13113:25:1;;;13101:2;13086:18;;12941:203;169372:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;169454:15;169472:19;:9;12625:14;;12533:114;169472:19;169454:37;;169502:21;:9;12744:19;;12762:1;12744:19;;;12655:127;169502:21;169534:30;169544:10;169556:7;169534:9;:30::i;:::-;169597:27;169610:7;169619:4;169597:12;:27::i;:::-;169676:21;;;;:12;:21;;;;;;;;:29;;;;;;;;:::i;:::-;-1:-1:-1;169716:28:0;;;;:19;:28;;;;;;;;:43;;;;;;;;:::i;:::-;-1:-1:-1;169770:31:0;;;;:22;:31;;;;;;;;:48;;;;;;;;:::i;:::-;-1:-1:-1;169829:26:0;;;;:17;:26;;;;;;;;:39;;;169881:17;:26;;;;;:38;;;;;;;;:::i;:::-;-1:-1:-1;169930:34:0;;;;:25;:34;;;;;;;;:47;;;170008:10;169994:25;;:13;:25;;;;;;169990:98;;170055:10;170041:25;;;;:13;:25;;;;;:35;;;169990:98;170176:10;170164:23;;;;:11;:23;;;;;;;:37;;;;;;;;;;;;;;;;;170302:22;:40;;157239:7;;170164:23;170302:40;;157239:7;;170302:40;:::i;:::-;;;;-1:-1:-1;;170384:18:0;;:38;;-1:-1:-1;;;170384:38:0;;170414:7;170384:38;;;13113:25:1;-1:-1:-1;;;;;170384:18:0;;;;:29;;13086:18:1;;170384:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;170433:4:0;;170455:18;;170433:51;;-1:-1:-1;;;170433:51:0;;-1:-1:-1;;;;;170433:4:0;;;;-1:-1:-1;170433:13:0;;-1:-1:-1;170433:51:0;;170455:18;;;;170476:7;;170433:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;170497:18:0;;:38;;-1:-1:-1;;;170497:38:0;;170527:7;170497:38;;;13113:25:1;-1:-1:-1;;;;;170497:18:0;;;;:29;;13086:18:1;;170497:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;170546:4:0;;170568:18;;170546:51;;-1:-1:-1;;;170546:51:0;;-1:-1:-1;;;;;170546:4:0;;;;-1:-1:-1;170546:13:0;;-1:-1:-1;170546:51:0;;170568:18;;;;170589:7;;170546:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;170610:20:0;;:40;;-1:-1:-1;;;170610:40:0;;170642:7;170610:40;;;13113:25:1;-1:-1:-1;;;;;170610:20:0;;;;:31;;13086:18:1;;170610:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;170661:4:0;;170683:20;;170661:53;;-1:-1:-1;;;170661:53:0;;-1:-1:-1;;;;;170661:4:0;;;;-1:-1:-1;170661:13:0;;-1:-1:-1;170661:53:0;;170683:20;;;;170706:7;;170661:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;170727:20:0;;:40;;-1:-1:-1;;;170727:40:0;;170759:7;170727:40;;;13113:25:1;-1:-1:-1;;;;;170727:20:0;;;;:31;;13086:18:1;;170727:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;170778:4:0;;170800:20;;170778:53;;-1:-1:-1;;;170778:53:0;;-1:-1:-1;;;;;170778:4:0;;;;-1:-1:-1;170778:13:0;;-1:-1:-1;170778:53:0;;170800:20;;;;170823:7;;170778:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;170891:37;170902:7;170911:10;170923:4;170891:10;:37::i;:::-;170941:18;170948:10;170941:6;:18::i;:::-;171037:21;:35;171059:4;;;;;;;;;-1:-1:-1;;;;;171059:4:0;-1:-1:-1;;;;;171059:10:0;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;171037:35;;;;;;;;;;;;:37;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;171122:10:0;171112:21;;;;:9;:21;;;;;;;;171107:113;;171160:10;171150:21;;;;:9;:21;;;;;:28;;-1:-1:-1;;171150:28:0;171174:4;171150:28;;;171193:13;:15;;;;;;:::i;:::-;;;;;;171107:113;171260:65;;171314:10;;171260:65;;171298:14;;171260:65;:::i;:::-;;;;;;;;171291:5;171260:65;;;;;;:::i;:::-;;;;;;;;;171265:7;171274:15;171260:65;;;;;;;:::i;:::-;;;;;;;;168780:2553;;168526:2807;;;;;;;:::o;172747:107::-;172800:7;172827:19;:9;12625:14;;12533:114;172827:19;172820:26;;172747:107;:::o;175597:142::-;175668:10;158797:42;175668:31;175660:40;;;;;;175711:9;:20;;-1:-1:-1;;;;;;175711:20:0;-1:-1:-1;;;;;175711:20:0;;;;;;;;;;175597:142::o;30436:178::-;30524:7;-1:-1:-1;;;;;30552:19:0;;30544:28;;;;;;-1:-1:-1;;;;;;30590:16:0;;;;;:9;:16;;;;;;;30436:178::o;161857:62::-;;;;;;;;;;;;;;;;;;;;49445:103;48719:13;:11;:13::i;:::-;49510:30:::1;49537:1;49510:18;:30::i;:::-;49445:103::o:0;167071:280::-;167180:17;;-1:-1:-1;;;;;167180:17:0;167158:10;:40;167154:53;;167071:280;;:::o;167154:53::-;167219:34;;;;:25;:34;;;;;;;167273:17;;:59;;-1:-1:-1;;;167273:59:0;;167219:34;;-1:-1:-1;;;;;167273:17:0;;:43;;:59;;167245:7;;167326:5;;167273:59;;;:::i;166783:280::-;166892:17;;-1:-1:-1;;;;;166892:17:0;166870:10;:40;166866:53;;166783:280;;:::o;166866:53::-;166931:34;;;;:25;:34;;;;;;;166985:17;;:59;;-1:-1:-1;;;166985:59:0;;166931:34;;-1:-1:-1;;;;;166985:17:0;;:43;;:59;;166957:7;;167038:5;;166985:59;;;:::i;168226:280::-;168335:17;;-1:-1:-1;;;;;168335:17:0;168313:10;:40;168309:53;;168226:280;;:::o;168309:53::-;168374:34;;;;:25;:34;;;;;;;168428:17;;:59;;-1:-1:-1;;;168428:59:0;;168374:34;;-1:-1:-1;;;;;168428:17:0;;:43;;:59;;168400:7;;168481:5;;168428:59;;;:::i;29592:48::-;;;;;;;;;;;;;;;;;;;;160391:56;;;;;;;;;;;;;;;;:::i;165907:283::-;166017:17;;-1:-1:-1;;;;;166017:17:0;165995:10;:40;165991:53;;165907:283;;:::o;165991:53::-;166056:35;;;;:26;:35;;;;;;;166111:17;;:60;;-1:-1:-1;;;166111:60:0;;166056:35;;-1:-1:-1;;;;;166111:17:0;;:44;;:60;;166083:7;;166165:5;;166111:60;;;:::i;161788:62::-;;;;;;;;;;;;;;;;;;;;48833:87;48906:6;;-1:-1:-1;;;;;48906:6:0;;48833:87::o;161647:64::-;;;;;;;;;;;;;;;;;;;;163663:349;163763:17;;-1:-1:-1;;;;;163763:17:0;163741:10;:40;163737:53;;163663:349;;:::o;163737:53::-;163802:19;163813:7;163802:10;:19::i;:::-;-1:-1:-1;;;;;163832:19:0;;;;;;:11;:19;;;;;;;:33;;;;;;;;;;;;;;;;163876:26;163844:6;163857:7;163876:9;:26::i;:::-;-1:-1:-1;;;;;163919:21:0;;;;;;:13;:21;;;;;;163915:90;;-1:-1:-1;;;;;163962:21:0;;;;;;:13;:21;;;;;:31;;;163915:90;163663:349;;:::o;31123:104::-;31179:13;31212:7;31205:14;;;;;:::i;173452:412::-;173537:9;12625:14;173531:2;:25;;173523:34;;;;;;173590:11;173598:2;173590:7;:11::i;:::-;-1:-1:-1;;;;;173576:25:0;:10;-1:-1:-1;;;;;173576:25:0;;:69;;;-1:-1:-1;173627:17:0;;-1:-1:-1;;;;;173627:17:0;173605:10;:40;173576:69;173568:121;;;;-1:-1:-1;;;173568:121:0;;13783:2:1;173568:121:0;;;13765:21:1;13822:2;13802:18;;;13795:30;13861:34;13841:18;;;13834:62;-1:-1:-1;;;13912:18:1;;;13905:37;13959:19;;173568:121:0;;;;;;;;-1:-1:-1;;;;;173730:21:0;;173702:25;173730:21;;;:13;:21;;;;;;;;;173762:26;;;;173806:50;;173822:10;;173806:50;;;;173730:21;;173786:2;;173806:50;:::i;:::-;;;;;;;;173512:352;173452:412;;:::o;173872:156::-;173963:15;;-1:-1:-1;;;;;173963:15:0;173949:10;:29;173941:38;;;;;;173992:15;:28;;-1:-1:-1;;;;;;173992:28:0;-1:-1:-1;;;;;173992:28:0;;;;;;;;;;173872:156::o;32649:180::-;32769:52;26114:10;32802:8;32812;32769:18;:52::i;167359:277::-;167467:17;;-1:-1:-1;;;;;167467:17:0;167445:10;:40;167441:53;;167359:277;;:::o;167441:53::-;167506:33;;;;:24;:33;;;;;;;167559:17;;:58;;-1:-1:-1;;;167559:58:0;;167506:33;;-1:-1:-1;;;;;167559:17:0;;:42;;:58;;167531:7;;167611:5;;167559:58;;;:::i;33769:273::-;33943:41;26114:10;33976:7;33943:18;:41::i;:::-;33935:50;;;;;;33996:38;34010:4;34016:2;34020:7;34029:4;33996:13;:38::i;180810:171::-;180917:13;180950:23;180965:7;180950:14;:23::i;161994:63::-;;;;;;;;;;;;;;;;;;;;167935:283;168045:17;;-1:-1:-1;;;;;168045:17:0;168023:10;:40;168019:53;;167935:283;;:::o;168019:53::-;168084:35;;;;:26;:35;;;;;;;168139:17;;:60;;-1:-1:-1;;;168139:60:0;;168084:35;;-1:-1:-1;;;;;168139:17:0;;:44;;:60;;168111:7;;168193:5;;168139:60;;;:::i;175436:118::-;175524:4;;:22;;-1:-1:-1;;;175524:22:0;;175497:7;;-1:-1:-1;;;;;175524:4:0;;:14;;:22;;175539:6;;175524:22;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;160278:46::-;;;;;;;;;;;;;;;;:::i;174053:217::-;174155:4;;174118;;-1:-1:-1;;;;;174155:4:0;:15;174171:16;174179:7;174171;:16::i;:::-;174155:33;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:107;;;-1:-1:-1;174205:4:0;;-1:-1:-1;;;;;174205:4:0;:21;174227:16;174235:7;174227;:16::i;:::-;174245:4;;:12;;;-1:-1:-1;;;174245:12:0;;;;174260:1;;-1:-1:-1;;;;;174245:4:0;;:10;;:12;;;;;;;;;;;;;;:4;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:16;;;;:::i;:::-;174205:57;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;166492:283::-;166602:17;;-1:-1:-1;;;;;166602:17:0;166580:10;:40;166576:53;;166492:283;;:::o;166576:53::-;166641:35;;;;:26;:35;;;;;;;166696:17;;:60;;-1:-1:-1;;;166696:60:0;;166641:35;;-1:-1:-1;;;;;166696:17:0;;:44;;:60;;166668:7;;166750:5;;166696:60;;;:::i;160331:53::-;;;;;;;;;;;;;;;;:::i;32900:189::-;-1:-1:-1;;;;;33046:25:0;;;33022:4;33046:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;32900:189::o;162134:62::-;;;;;;;;;;;;;;;;;;;;172884:151;172956:10;158797:42;172956:31;172948:40;;;;;;173001:4;:26;;-1:-1:-1;;;;;;173001:26:0;-1:-1:-1;;;;;173001:26:0;;;;;;;;;;172884:151::o;176624:695::-;176699:17;;-1:-1:-1;;;;;176699:17:0;176677:10;:40;176673:53;;176624:695::o;176673:53::-;176875:25;;176913:399;176937:1;176933;:5;176913:399;;;176970:15;;176960:29;;-1:-1:-1;;;;;176970:15:0;176987:1;176960:9;:29::i;:::-;177006:13;177017:1;177006:10;:13::i;:::-;177057:17;;:45;;-1:-1:-1;;;177057:45:0;;;;;13113:25:1;;;-1:-1:-1;;;;;177057:17:0;;;;:42;;13086:18:1;;177057:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;177036:66;;;;:::i;:::-;177131:15;;-1:-1:-1;;;;;177131:15:0;177119:28;;;;:11;:28;;;;;;;;:36;;177131:15;177119:36;;;;;;;;;;;;;;;;;177172:128;;;;;;;;;;;;177036:66;;-1:-1:-1;177172:128:0;;177153:1;;177172:128;;;;;;:12;:128::i;:::-;176940:3;;;;:::i;:::-;;;;176913:399;;49703:159;48719:13;:11;:13::i;:::-;-1:-1:-1;;;;;49792:22:0;::::1;49784:31;;;::::0;::::1;;49826:28;49845:8;49826:18;:28::i;12533:114::-:0;12625:14;;12533:114::o;12655:127::-;12744:19;;12762:1;12744:19;;;12655:127::o;1070:326::-;-1:-1:-1;;;;;1365:19:0;;:23;;;1070:326::o;42686:107::-;42768:16;42776:7;42768;:16::i;:::-;42760:25;;;;;41994:174;42069:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;42069:29:0;-1:-1:-1;;;;;42069:29:0;;;;;;;;:24;;42123:23;42069:24;42123:14;:23::i;:::-;-1:-1:-1;;;;;42114:46:0;;;;;;;;;;;41994:174;;:::o;174787:340::-;174856:16;;174838:15;:34;174834:286;;;174889:18;;;;;;;;;-1:-1:-1;;;;;174889:18:0;-1:-1:-1;;;;;174889:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;174931:18;;;;;;;;;-1:-1:-1;;;;;174931:18:0;-1:-1:-1;;;;;174931:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;174975:20;;;;;;;;;-1:-1:-1;;;;;174975:20:0;-1:-1:-1;;;;;174975:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175019:20;;;;;;;;;-1:-1:-1;;;;;175019:20:0;-1:-1:-1;;;;;175019:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175102:6;;175084:15;:24;;;;:::i;:::-;175065:16;:43;174787:340::o;174303:476::-;-1:-1:-1;;;;;174373:20:0;;;;;;:12;:20;;;;;;;;174369:193;;;-1:-1:-1;;;;;174428:30:0;;;;;;:22;:30;;;;;;174410:14;:48;;174428:30;;174410:14;;:48;;174428:30;;174410:48;:::i;:::-;;;;-1:-1:-1;;;;;;;174473:30:0;;174506:1;174473:30;;;:22;:30;;;;;;;;:34;;;174522:12;:20;;;;;:28;;-1:-1:-1;;174522:28:0;;;174369:193;174578:4;;:23;;-1:-1:-1;;;174578:23:0;;-1:-1:-1;;;;;174578:4:0;;;;:15;;:23;;174594:6;;174578:23;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174574:198;;;174636:17;174646:6;174636:9;:17::i;:::-;174618:14;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;174701:17:0;;-1:-1:-1;174711:6:0;174701:9;:17::i;:::-;-1:-1:-1;;;;;174668:30:0;;;;;;:22;:30;;;;;;;;:50;;;;174733:12;:20;;;:27;;-1:-1:-1;;174733:27:0;174756:4;174733:27;;;174303:476;:::o;36021:315::-;36139:4;36156:13;36172:23;36187:7;36172:14;:23::i;:::-;36156:39;;36225:5;-1:-1:-1;;;;;36214:16:0;:7;-1:-1:-1;;;;;36214:16:0;;:65;;;;36247:32;36264:5;36271:7;36247:16;:32::i;:::-;36214:113;;;;36320:7;-1:-1:-1;;;;;36296:31:0;:20;36308:7;36296:11;:20::i;:::-;-1:-1:-1;;;;;36296:31:0;;36214:113;36206:122;36021:315;-1:-1:-1;;;;36021:315:0:o;40629:1246::-;40788:4;-1:-1:-1;;;;;40761:31:0;:23;40776:7;40761:14;:23::i;:::-;-1:-1:-1;;;;;40761:31:0;;40753:40;;;;;;-1:-1:-1;;;;;40812:16:0;;40804:25;;;;;;41011:4;-1:-1:-1;;;;;40984:31:0;:23;40999:7;40984:14;:23::i;:::-;-1:-1:-1;;;;;40984:31:0;;40976:40;;;;;;41088:24;;;;:15;:24;;;;;41081:31;;-1:-1:-1;;;;;;41081:31:0;;;41566:41;41104:7;41602:4;41566:26;:41::i;:::-;-1:-1:-1;;;;;41622:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;41622:20:0;;;41659:36;41683:7;41692:2;41659:23;:36::i;:::-;-1:-1:-1;;;;;41710:13:0;;;;;;;:9;:13;;;;;;;;:18;;41727:1;41710:18;;;41750:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;41750:21:0;;;;;41789:27;41758:7;;41789:27;;;-1:-1:-1;;;;;;;;;;;41789:27:0;;32117:207;32047:277;;:::o;175808:808::-;175932:13;;175980:629;175991:1;175987;:5;175980:629;;;176013:7;176009:50;;;176022:37;176036:1;176039:7;176048:10;176022:13;:37::i;:::-;176084:19;176092:10;176084:7;:19::i;:::-;-1:-1:-1;;;;;176120:30:0;;;;;;:23;:30;;;;;:40;;176076:27;;-1:-1:-1;157184:7:0;;176120:30;;;:40;;157184:7;;176120:40;:::i;:::-;;;;-1:-1:-1;;176175:40:0;;;;:28;:40;;;;;:50;;157184:7;;176175:40;:50;;157184:7;;176175:50;:::i;:::-;;;;;;;;157184:7;176240:28;;:38;;;;;;;:::i;:::-;;;;-1:-1:-1;;176293:4:0;;:28;;-1:-1:-1;;;176293:28:0;;-1:-1:-1;;;;;176293:4:0;;;;:13;;:28;;176307:5;;157184:7;;176293:28;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;176488:15;176464:5;-1:-1:-1;;;;;176371:147:0;;176410:10;157184:7;176371:147;;;;;;;:::i;:::-;;;;;;;;176548:29;;;;:17;:29;;;;;;;;176594:3;;;;:::i;:::-;;;;175980:629;;;175921:695;;175808:808;;;:::o;35296:117::-;35362:7;35389:16;;;:7;:16;;;;;;-1:-1:-1;;;;;35389:16:0;;35296:117::o;36678:110::-;36754:26;36764:2;36768:7;36754:26;;;;;;;;;;;;:9;:26::i;47608:192::-;47733:16;47741:7;47733;:16::i;:::-;47725:25;;;;;;47761:19;;;;:10;:19;;;;;;;;:31;;;;;;;;:::i;48998:96::-;26114:10;49062:7;:5;:7::i;:::-;-1:-1:-1;;;;;49062:23:0;;49054:32;;;;;50022:191;50115:6;;;-1:-1:-1;;;;;50132:17:0;;;-1:-1:-1;;;;;;50132:17:0;;;;;;;50165:40;;50115:6;;;50132:17;50115:6;;50165:40;;50096:16;;50165:40;50085:128;50022:191;:::o;164020:1879::-;164123:17;;:37;;-1:-1:-1;;;164123:37:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164123:17:0;;;;:30;;13086:18:1;;164123:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;164123:37:0;;;;;;;;;;;;:::i;:::-;164101:19;;;;:12;:19;;;;;;;;:59;;;;:19;;:59;;;;;;:::i;:::-;-1:-1:-1;164200:17:0;;:68;;-1:-1:-1;;;164200:68:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164200:17:0;;;;:37;;13086:18:1;;164200:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;164200:68:0;;;;;;;;;;;;:::i;:::-;164171:26;;;;:19;:26;;;;;;;;:97;;;;:26;;:97;;;;;;:::i;:::-;-1:-1:-1;164311:17:0;;:61;;-1:-1:-1;;;164311:61:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164311:17:0;;;;:54;;13086:18:1;;164311:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;164311:61:0;;;;;;;;;;;;:::i;:::-;164279:29;;;;:22;:29;;;;;;;;:93;;;;:29;;:93;;;;;;:::i;:::-;-1:-1:-1;164418:17:0;;:64;;-1:-1:-1;;;164418:64:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164418:17:0;;;;:57;;13086:18:1;;164418:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;164383:32;;;;:25;:32;;;;;;;:99;;;;164520:17;;:42;;-1:-1:-1;;;164520:42:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164520:17:0;;;;:35;;13086:18:1;;164520:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;164520:42:0;;;;;;;;;;;;:::i;:::-;164493:24;;;;:17;:24;;;;;;;;:69;;;;:24;;:69;;;;;;:::i;:::-;-1:-1:-1;164600:17:0;;:42;;-1:-1:-1;;;164600:42:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164600:17:0;;;;:35;;13086:18:1;;164600:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;164573:24;;;;:17;:24;;;;;;;:69;;;;164720:17;;:71;;-1:-1:-1;;;164720:71:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164720:17:0;;;;:64;;13086:18:1;;164720:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;164678:39;;;;:32;:39;;;;;;;:113;;;;164845:17;;:72;;-1:-1:-1;;;164845:72:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164845:17:0;;;;:65;;13086:18:1;;164845:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;164802:40;;;;:33;:40;;;;;;;:115;;;;164970:17;;:71;;-1:-1:-1;;;164970:71:0;;;;;13113:25:1;;;-1:-1:-1;;;;;164970:17:0;;;;:64;;13086:18:1;;164970:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;164928:39;;;;:32;:39;;;;;;;:113;;;;165093:17;;:70;;-1:-1:-1;;;165093:70:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165093:17:0;;;;:63;;13086:18:1;;165093:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165052:38;;;;:31;:38;;;;;;;:111;;;;165215:17;;:70;;-1:-1:-1;;;165215:70:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165215:17:0;;;;:63;;13086:18:1;;165215:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165174:38;;;;:31;:38;;;;;;;;;:111;;;;165336:17;;:69;;-1:-1:-1;;;165336:69:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165336:17:0;;;;:62;;13086:18:1;165336:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165296:37;;;;:30;:37;;;;;;;:109;;;;165458:17;;:71;;-1:-1:-1;;;165458:71:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165458:17:0;;;;:64;;13086:18:1;;165458:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165416:39;;;;:32;:39;;;;;;;:113;;;;165582:17;;:71;;-1:-1:-1;;;165582:71:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165582:17:0;;;;:64;;13086:18:1;;165582:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165540:39;;;;:32;:39;;;;;;;:113;;;;165705:17;;:70;;-1:-1:-1;;;165705:70:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165705:17:0;;;;:63;;13086:18:1;;165705:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165664:38;;;;:31;:38;;;;;;;:111;;;;165825:17;;:66;;-1:-1:-1;;;165825:66:0;;;;;13113:25:1;;;-1:-1:-1;;;;;165825:17:0;;;;:59;;13086:18:1;;165825:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165788:34;;;;:27;:34;;;;;;:103;164020:1879::o;42311:286::-;42466:8;-1:-1:-1;;;;;42457:17:0;:5;-1:-1:-1;;;;;42457:17:0;;;42449:26;;;;;;-1:-1:-1;;;;;42486:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;42486:46:0;;;;;;;;;;42548:41;;11987::1;;;42548::0;;11960:18:1;42548:41:0;;;;;;;42311:286;;;:::o;34923:259::-;35079:28;35089:4;35095:2;35099:7;35079:9;:28::i;:::-;35126:47;35149:4;35155:2;35159:7;35168:4;35126:22;:47::i;:::-;35118:56;;;;;46812:640;46901:13;46927:23;46942:7;46927:14;:23::i;:::-;46963;46989:19;;;:10;:19;;;;;46963:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47019:18;47040:10;31968:9;;;;;;;;;-1:-1:-1;31968:9:0;;;31891:94;47040:10;47019:31;;47132:4;47126:18;47148:1;47126:23;47122:72;;;-1:-1:-1;47173:9:0;46812:640;-1:-1:-1;;46812:640:0:o;47122:72::-;47298:23;;:27;47294:108;;47373:4;47379:9;47356:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;47342:48;;;;46812:640;;;:::o;47294:108::-;47421:23;47436:7;47421:14;:23::i;35726:128::-;35791:4;;35815:17;35824:7;35815:8;:17::i;:::-;-1:-1:-1;;;;;35815:31:0;;;;35726:128;-1:-1:-1;;35726:128:0:o;39783:509::-;39896:9;39922:45;-1:-1:-1;;;;;39929:19:0;;;;;;:11;:19;;;;;:22;;39955:7;;39929:19;39949:1;;39929:22;;;;;;:::i;:::-;;;;;;;;;:33;39922:45;;39964:3;;;;:::i;:::-;;;;39922:45;;;-1:-1:-1;;;;;39993:17:0;;;;;;:9;:17;;;;;;:21;;40013:1;;39993:21;:::i;:::-;39988:1;:27;39980:120;;;-1:-1:-1;;;;;40062:19:0;;;;;;:11;:19;;;;;40082:5;:1;40086;40082:5;:::i;:::-;40062:26;;;;;;;;:::i;:::-;;;;;;;;;40037:11;:19;40049:6;-1:-1:-1;;;;;40037:19:0;-1:-1:-1;;;;;40037:19:0;;;;;;;;;;;;40057:1;40037:22;;;;;;;;:::i;:::-;;;;;;;;;;:51;40017:3;;;;:::i;:::-;;;;39980:120;;;-1:-1:-1;;;;;40112:19:0;;;;;;:11;:19;;;;;:25;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;40112:25:0;;;;;;;;;;;;-1:-1:-1;;;;;40154:21:0;;;;:13;:21;;;;;;:32;;40150:121;;;-1:-1:-1;;;;;40237:19:0;;;;;;:11;:19;;;;;:22;;:19;;;:22;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;40213:21:0;;;;:13;:21;;;;;;;:46;39885:407;39783:509;;:::o;39539:236::-;-1:-1:-1;;;;;39624:19:0;;;;;;:11;:19;;;;;;;;:33;;;;;;;;;;;;;;;;;39672:21;;;:13;:21;;;;39668:100;;-1:-1:-1;;;;;39725:21:0;;;;;:13;:21;;;;;:31;39539:236::o;177327:3266::-;177414:6;177410:344;;177437:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;177491:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;177616:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;177410:344::-;177770:1;177775;177770:6;177766:348;;;177793:38;;;;:33;:38;;;;;:40;;;;;;:::i;:::-;;;;-1:-1:-1;;177848:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;177974:32:0;;;;:27;:32;;;;;;;:46;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;177766:348::-;178130:1;178135;178130:6;178126:344;;;178153:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;178207:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;178332:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;178126:344::-;178486:1;178491;178486:6;178482:340;;;178509:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;178562:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;178686:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;178482:340::-;178838:1;178843;178838:6;178834:340;;;178861:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;178914:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;179038:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;178834:340::-;179190:1;179195;179190:6;179186:336;;;179213:35;;;;:30;:35;;;;;:37;;;;;;:::i;:::-;;;;-1:-1:-1;;179265:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;179388:29:0;;;;:24;:29;;;;;;;:43;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;179186:336::-;179538:1;179543;179538:6;179534:344;;;179561:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;179615:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;179740:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;179534:344::-;179894:1;179899;179894:6;179890:344;;;179917:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;179971:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;180096:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;179890:344::-;180250:1;180255;180250:6;180246:340;;;180273:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;180326:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;180450:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;177327:3266:0:o;37015:228::-;37144:18;37150:2;37154:7;37144:5;:18::i;:::-;37181:53;37212:1;37216:2;37220:7;37229:4;37181:22;:53::i;:::-;37173:62;;;;;43357:934;43511:4;43532:15;:2;-1:-1:-1;;;;;43532:13:0;;:15::i;:::-;43528:756;;;43585:174;;-1:-1:-1;;;43585:174:0;;-1:-1:-1;;;;;43585:36:0;;;;;:174;;26114:10;;43679:4;;43706:7;;43736:4;;43585:174;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43585:174:0;;;;;;;;-1:-1:-1;;43585:174:0;;;;;;;;;;;;:::i;:::-;;;43564:665;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43942:13:0;;43938:276;;43985:8;;;43938:276;44164:6;44158:13;44149:6;44145:2;44141:15;44134:38;43564:665;-1:-1:-1;;;;;;43823:51:0;-1:-1:-1;;;43823:51:0;;-1:-1:-1;43816:58:0;;43528:756;-1:-1:-1;44268:4:0;43357:934;;;;;;:::o;31298:344::-;31387:13;31413:23;31428:7;31413:14;:23::i;:::-;31449:21;31473:10;31968:9;;;;;;;;;-1:-1:-1;31968:9:0;;;31891:94;31473:10;31449:34;;31538:1;31520:7;31514:21;:25;:120;;;;;;;;;;;;;;;;;31583:7;31592:18;:7;:16;:18::i;:::-;31566:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;31514:120;31494:140;31298:344;-1:-1:-1;;;31298:344:0:o;37579:836::-;-1:-1:-1;;;;;37659:16:0;;37651:25;;;;;;37696:16;37704:7;37696;:16::i;:::-;37695:17;37687:26;;;;;;37870:16;37878:7;37870;:16::i;:::-;37869:17;37861:26;;;;;;-1:-1:-1;;;;;38236:13:0;;;;;;:9;:13;;;;;;;;:18;;38253:1;38236:18;;;38278:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;38278:21:0;;;;;38317:33;38286:7;;38236:13;;-1:-1:-1;;;;;;;;;;;38317:33:0;38236:13;;38317:33;163663:349;;:::o;10203:716::-;10259:13;10310:14;10327:17;10338:5;10327:10;:17::i;:::-;10347:1;10327:21;10310:38;;10363:20;10397:6;-1:-1:-1;;;;;10386:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10386:18:0;-1:-1:-1;10363:41:0;-1:-1:-1;10528:28:0;;;10544:2;10528:28;10585:288;-1:-1:-1;;10617:5:0;-1:-1:-1;;;10754:2:0;10743:14;;10738:30;10617:5;10725:44;10815:2;10806:11;;;-1:-1:-1;10840:10:0;10836:21;;10852:5;;10836:21;10585:288;;;-1:-1:-1;10894:6:0;10203:716;-1:-1:-1;;;10203:716:0:o;23149:948::-;23202:7;;-1:-1:-1;;;23280:17:0;;23276:106;;-1:-1:-1;;;23318:17:0;;;-1:-1:-1;23364:2:0;23354:12;23276:106;-1:-1:-1;;;23400:5:0;:17;23396:106;;-1:-1:-1;;;23438:17:0;;;-1:-1:-1;23484:2:0;23474:12;23396:106;23529:8;23520:5;:17;23516:106;;23567:8;23558:17;;;-1:-1:-1;23604:2:0;23594:12;23516:106;23649:7;23640:5;:16;23636:103;;23686:7;23677:16;;;-1:-1:-1;23722:1:0;23712:11;23636:103;23766:7;23757:5;:16;23753:103;;23803:7;23794:16;;;-1:-1:-1;23839:1:0;23829:11;23753:103;23883:7;23874:5;:16;23870:103;;23920:7;23911:16;;;-1:-1:-1;23956:1:0;23946:11;23870:103;24000:7;23991:5;:16;23987:68;;24038:1;24028:11;24083:6;23149:948;-1:-1:-1;;23149:948:0:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:336:1;78:5;107:52;123:35;151:6;123:35;:::i;:::-;107:52;:::i;:::-;98:61;;182:6;175:5;168:21;222:3;213:6;208:3;204:16;201:25;198:45;;;239:1;236;229:12;198:45;288:6;283:3;276:4;269:5;265:16;252:43;342:1;335:4;326:6;319:5;315:18;311:29;304:40;14:336;;;;;:::o;355:221::-;398:5;451:3;444:4;436:6;432:17;428:27;418:55;;469:1;466;459:12;418:55;491:79;566:3;557:6;544:20;537:4;529:6;525:17;491:79;:::i;581:247::-;640:6;693:2;681:9;672:7;668:23;664:32;661:52;;;709:1;706;699:12;661:52;748:9;735:23;767:31;792:5;767:31;:::i;833:251::-;903:6;956:2;944:9;935:7;931:23;927:32;924:52;;;972:1;969;962:12;924:52;1004:9;998:16;1023:31;1048:5;1023:31;:::i;1089:388::-;1157:6;1165;1218:2;1206:9;1197:7;1193:23;1189:32;1186:52;;;1234:1;1231;1224:12;1186:52;1273:9;1260:23;1292:31;1317:5;1292:31;:::i;:::-;1342:5;-1:-1:-1;1399:2:1;1384:18;;1371:32;1412:33;1371:32;1412:33;:::i;:::-;1464:7;1454:17;;;1089:388;;;;;:::o;1482:456::-;1559:6;1567;1575;1628:2;1616:9;1607:7;1603:23;1599:32;1596:52;;;1644:1;1641;1634:12;1596:52;1683:9;1670:23;1702:31;1727:5;1702:31;:::i;:::-;1752:5;-1:-1:-1;1809:2:1;1794:18;;1781:32;1822:33;1781:32;1822:33;:::i;:::-;1482:456;;1874:7;;-1:-1:-1;;;1928:2:1;1913:18;;;;1900:32;;1482:456::o;1943:794::-;2038:6;2046;2054;2062;2115:3;2103:9;2094:7;2090:23;2086:33;2083:53;;;2132:1;2129;2122:12;2083:53;2171:9;2158:23;2190:31;2215:5;2190:31;:::i;:::-;2240:5;-1:-1:-1;2297:2:1;2282:18;;2269:32;2310:33;2269:32;2310:33;:::i;:::-;2362:7;-1:-1:-1;2416:2:1;2401:18;;2388:32;;-1:-1:-1;2471:2:1;2456:18;;2443:32;-1:-1:-1;;;;;2487:30:1;;2484:50;;;2530:1;2527;2520:12;2484:50;2553:22;;2606:4;2598:13;;2594:27;-1:-1:-1;2584:55:1;;2635:1;2632;2625:12;2584:55;2658:73;2723:7;2718:2;2705:16;2700:2;2696;2692:11;2658:73;:::i;:::-;2648:83;;;1943:794;;;;;;;:::o;2742:382::-;2807:6;2815;2868:2;2856:9;2847:7;2843:23;2839:32;2836:52;;;2884:1;2881;2874:12;2836:52;2923:9;2910:23;2942:31;2967:5;2942:31;:::i;:::-;2992:5;-1:-1:-1;3049:2:1;3034:18;;3021:32;3062:30;3021:32;3062:30;:::i;3129:315::-;3197:6;3205;3258:2;3246:9;3237:7;3233:23;3229:32;3226:52;;;3274:1;3271;3264:12;3226:52;3313:9;3300:23;3332:31;3357:5;3332:31;:::i;:::-;3382:5;3434:2;3419:18;;;;3406:32;;-1:-1:-1;;;3129:315:1:o;3449:245::-;3516:6;3569:2;3557:9;3548:7;3544:23;3540:32;3537:52;;;3585:1;3582;3575:12;3537:52;3617:9;3611:16;3636:28;3658:5;3636:28;:::i;3699:245::-;3757:6;3810:2;3798:9;3789:7;3785:23;3781:32;3778:52;;;3826:1;3823;3816:12;3778:52;3865:9;3852:23;3884:30;3908:5;3884:30;:::i;3949:249::-;4018:6;4071:2;4059:9;4050:7;4046:23;4042:32;4039:52;;;4087:1;4084;4077:12;4039:52;4119:9;4113:16;4138:30;4162:5;4138:30;:::i;4474:735::-;4624:6;4632;4640;4648;4701:3;4689:9;4680:7;4676:23;4672:33;4669:53;;;4718:1;4715;4708:12;4669:53;4757:9;4744:23;4776:31;4801:5;4776:31;:::i;:::-;4826:5;-1:-1:-1;4883:2:1;4868:18;;4855:32;4896:33;4855:32;4896:33;:::i;:::-;4948:7;-1:-1:-1;5007:2:1;4992:18;;4979:32;5020:33;4979:32;5020:33;:::i;:::-;5072:7;-1:-1:-1;5131:2:1;5116:18;;5103:32;5144:33;5103:32;5144:33;:::i;:::-;4474:735;;;;-1:-1:-1;4474:735:1;;-1:-1:-1;;4474:735:1:o;5487:635::-;5567:6;5620:2;5608:9;5599:7;5595:23;5591:32;5588:52;;;5636:1;5633;5626:12;5588:52;5663:16;;-1:-1:-1;;;;;5691:30:1;;5688:50;;;5734:1;5731;5724:12;5688:50;5757:22;;5810:4;5802:13;;5798:27;-1:-1:-1;5788:55:1;;5839:1;5836;5829:12;5788:55;5868:2;5862:9;5893:48;5909:31;5937:2;5909:31;:::i;5893:48::-;5964:2;5957:5;5950:17;6004:7;5999:2;5994;5990;5986:11;5982:20;5979:33;5976:53;;;6025:1;6022;6015:12;5976:53;6038:54;6089:2;6084;6077:5;6073:14;6068:2;6064;6060:11;6038:54;:::i;:::-;6111:5;5487:635;-1:-1:-1;;;;;5487:635:1:o;6127:1283::-;6290:6;6298;6306;6314;6322;6330;6338;6391:3;6379:9;6370:7;6366:23;6362:33;6359:53;;;6408:1;6405;6398:12;6359:53;6435:23;;-1:-1:-1;;;;;6507:14:1;;;6504:34;;;6534:1;6531;6524:12;6504:34;6557:50;6599:7;6590:6;6579:9;6575:22;6557:50;:::i;:::-;6547:60;;6660:2;6649:9;6645:18;6632:32;6616:48;;6689:2;6679:8;6676:16;6673:36;;;6705:1;6702;6695:12;6673:36;6728:52;6772:7;6761:8;6750:9;6746:24;6728:52;:::i;:::-;6718:62;;6833:2;6822:9;6818:18;6805:32;6789:48;;6862:2;6852:8;6849:16;6846:36;;;6878:1;6875;6868:12;6846:36;6901:52;6945:7;6934:8;6923:9;6919:24;6901:52;:::i;:::-;6891:62;;7006:2;6995:9;6991:18;6978:32;6962:48;;7035:2;7025:8;7022:16;7019:36;;;7051:1;7048;7041:12;7019:36;7074:52;7118:7;7107:8;7096:9;7092:24;7074:52;:::i;:::-;7064:62;;7179:3;7168:9;7164:19;7151:33;7135:49;;7209:2;7199:8;7196:16;7193:36;;;7225:1;7222;7215:12;7193:36;;7248:52;7292:7;7281:8;7270:9;7266:24;7248:52;:::i;:::-;7238:62;;;7347:3;7336:9;7332:19;7319:33;7309:43;;7399:3;7388:9;7384:19;7371:33;7361:43;;6127:1283;;;;;;;;;;:::o;7415:812::-;7531:6;7539;7547;7555;7608:3;7596:9;7587:7;7583:23;7579:33;7576:53;;;7625:1;7622;7615:12;7576:53;7652:23;;-1:-1:-1;;;;;7724:14:1;;;7721:34;;;7751:1;7748;7741:12;7721:34;7774:50;7816:7;7807:6;7796:9;7792:22;7774:50;:::i;:::-;7764:60;;7877:2;7866:9;7862:18;7849:32;7833:48;;7906:2;7896:8;7893:16;7890:36;;;7922:1;7919;7912:12;7890:36;7945:52;7989:7;7978:8;7967:9;7963:24;7945:52;:::i;:::-;7935:62;;8050:2;8039:9;8035:18;8022:32;8006:48;;8079:2;8069:8;8066:16;8063:36;;;8095:1;8092;8085:12;8063:36;;8118:52;8162:7;8151:8;8140:9;8136:24;8118:52;:::i;:::-;7415:812;;;;-1:-1:-1;8108:62:1;;8217:2;8202:18;8189:32;;-1:-1:-1;;;7415:812:1:o;8232:180::-;8291:6;8344:2;8332:9;8323:7;8319:23;8315:32;8312:52;;;8360:1;8357;8350:12;8312:52;-1:-1:-1;8383:23:1;;8232:180;-1:-1:-1;8232:180:1:o;8417:184::-;8487:6;8540:2;8528:9;8519:7;8515:23;8511:32;8508:52;;;8556:1;8553;8546:12;8508:52;-1:-1:-1;8579:16:1;;8417:184;-1:-1:-1;8417:184:1:o;8606:248::-;8674:6;8682;8735:2;8723:9;8714:7;8710:23;8706:32;8703:52;;;8751:1;8748;8741:12;8703:52;-1:-1:-1;;8774:23:1;;;8844:2;8829:18;;;8816:32;;-1:-1:-1;8606:248:1:o;8859:257::-;8900:3;8938:5;8932:12;8965:6;8960:3;8953:19;8981:63;9037:6;9030:4;9025:3;9021:14;9014:4;9007:5;9003:16;8981:63;:::i;:::-;9098:2;9077:15;-1:-1:-1;;9073:29:1;9064:39;;;;9105:4;9060:50;;8859:257;-1:-1:-1;;8859:257:1:o;9121:276::-;9252:3;9290:6;9284:13;9306:53;9352:6;9347:3;9340:4;9332:6;9328:17;9306:53;:::i;:::-;9375:16;;;;;9121:276;-1:-1:-1;;9121:276:1:o;9402:470::-;9581:3;9619:6;9613:13;9635:53;9681:6;9676:3;9669:4;9661:6;9657:17;9635:53;:::i;:::-;9751:13;;9710:16;;;;9773:57;9751:13;9710:16;9807:4;9795:17;;9773:57;:::i;:::-;9846:20;;9402:470;-1:-1:-1;;;;9402:470:1:o;9877:203::-;-1:-1:-1;;;;;10041:32:1;;;;10023:51;;10011:2;9996:18;;9877:203::o;10085:375::-;-1:-1:-1;;;;;10343:15:1;;;10325:34;;10395:15;;;;10390:2;10375:18;;10368:43;10442:2;10427:18;;10420:34;;;;10275:2;10260:18;;10085:375::o;10465:488::-;-1:-1:-1;;;;;10734:15:1;;;10716:34;;10786:15;;10781:2;10766:18;;10759:43;10833:2;10818:18;;10811:34;;;10881:3;10876:2;10861:18;;10854:31;;;10659:4;;10902:45;;10927:19;;10919:6;10902:45;:::i;:::-;10894:53;10465:488;-1:-1:-1;;;;;;10465:488:1:o;10958:300::-;-1:-1:-1;;;;;11176:32:1;;;;11158:51;;11240:2;11225:18;;11218:34;11146:2;11131:18;;10958:300::o;13357:219::-;13506:2;13495:9;13488:21;13469:4;13526:44;13566:2;13555:9;13551:18;13543:6;13526:44;:::i;14171:248::-;14345:25;;;14401:2;14386:18;;14379:34;14333:2;14318:18;;14171:248::o;14424:275::-;14495:2;14489:9;14560:2;14541:13;;-1:-1:-1;;14537:27:1;14525:40;;-1:-1:-1;;;;;14580:34:1;;14616:22;;;14577:62;14574:88;;;14642:18;;:::i;:::-;14678:2;14671:22;14424:275;;-1:-1:-1;14424:275:1:o;14704:186::-;14752:4;-1:-1:-1;;;;;14774:30:1;;14771:56;;;14807:18;;:::i;:::-;-1:-1:-1;14873:2:1;14852:15;-1:-1:-1;;14848:29:1;14879:4;14844:40;;14704:186::o;14895:128::-;14935:3;14966:1;14962:6;14959:1;14956:13;14953:39;;;14972:18;;:::i;:::-;-1:-1:-1;15008:9:1;;14895:128::o;15028:125::-;15068:4;15096:1;15093;15090:8;15087:34;;;15101:18;;:::i;:::-;-1:-1:-1;15138:9:1;;15028:125::o;15158:258::-;15230:1;15240:113;15254:6;15251:1;15248:13;15240:113;;;15330:11;;;15324:18;15311:11;;;15304:39;15276:2;15269:10;15240:113;;;15371:6;15368:1;15365:13;15362:48;;;-1:-1:-1;;15406:1:1;15388:16;;15381:27;15158:258::o;15421:380::-;15500:1;15496:12;;;;15543;;;15564:61;;15618:4;15610:6;15606:17;15596:27;;15564:61;15671:2;15663:6;15660:14;15640:18;15637:38;15634:161;;;15717:10;15712:3;15708:20;15705:1;15698:31;15752:4;15749:1;15742:15;15780:4;15777:1;15770:15;15634:161;;15421:380;;;:::o;15806:135::-;15845:3;-1:-1:-1;;15866:17:1;;15863:43;;;15886:18;;:::i;:::-;-1:-1:-1;15933:1:1;15922:13;;15806:135::o;15946:127::-;16007:10;16002:3;15998:20;15995:1;15988:31;16038:4;16035:1;16028:15;16062:4;16059:1;16052:15;16210:127;16271:10;16266:3;16262:20;16259:1;16252:31;16302:4;16299:1;16292:15;16326:4;16323:1;16316:15;16342:127;16403:10;16398:3;16394:20;16391:1;16384:31;16434:4;16431:1;16424:15;16458:4;16455:1;16448:15;16474:127;16535:10;16530:3;16526:20;16523:1;16516:31;16566:4;16563:1;16556:15;16590:4;16587:1;16580:15;16606:131;-1:-1:-1;;;;;16681:31:1;;16671:42;;16661:70;;16727:1;16724;16717:12;16742:118;16828:5;16821:13;16814:21;16807:5;16804:32;16794:60;;16850:1;16847;16840:12;16865:131;-1:-1:-1;;;;;;16939:32:1;;16929:43;;16919:71;;16986:1;16983;16976:12
Swarm Source
ipfs://f0db85a3c35611b4775d04f5137da082f4100840cb359a55c06f20ea969e65d5
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.