Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 129 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Favourite NF... | 4171535 | 904 days ago | IN | 0 GLMR | 0.01871598 | ||||
| Set Favourite NF... | 4134604 | 909 days ago | IN | 0 GLMR | 0.00716324 | ||||
| Set Favourite NF... | 4126729 | 910 days ago | IN | 0 GLMR | 0.0067005 | ||||
| Set Favourite NF... | 4121661 | 911 days ago | IN | 0 GLMR | 0.00487102 | ||||
| Set Favourite NF... | 4121635 | 911 days ago | IN | 0 GLMR | 0.00669825 | ||||
| Set Favourite NF... | 4114183 | 912 days ago | IN | 0 GLMR | 0.00705813 | ||||
| Set Favourite NF... | 4114173 | 912 days ago | IN | 0 GLMR | 0.0070686 | ||||
| Set Favourite NF... | 4114128 | 912 days ago | IN | 0 GLMR | 0.00721512 | ||||
| Set Favourite NF... | 4113869 | 912 days ago | IN | 0 GLMR | 0.0070069 | ||||
| Set Favourite NF... | 4113853 | 912 days ago | IN | 0 GLMR | 0.00699679 | ||||
| Set Favourite NF... | 4113842 | 912 days ago | IN | 0 GLMR | 0.00695947 | ||||
| Set Favourite NF... | 4113817 | 912 days ago | IN | 0 GLMR | 0.01016263 | ||||
| Set Favourite NF... | 4113028 | 912 days ago | IN | 0 GLMR | 0.00644426 | ||||
| Set Favourite NF... | 4113001 | 912 days ago | IN | 0 GLMR | 0.00742706 | ||||
| Set Favourite NF... | 4112854 | 912 days ago | IN | 0 GLMR | 0.00744664 | ||||
| Set Favourite NF... | 4108313 | 913 days ago | IN | 0 GLMR | 0.00672289 | ||||
| Set Favourite NF... | 4108185 | 913 days ago | IN | 0 GLMR | 0.00727938 | ||||
| Set Favourite NF... | 4108069 | 913 days ago | IN | 0 GLMR | 0.00780767 | ||||
| Set Favourite NF... | 4108026 | 913 days ago | IN | 0 GLMR | 0.00784368 | ||||
| Set Favourite NF... | 4107984 | 913 days ago | IN | 0 GLMR | 0.00782991 | ||||
| Set Favourite NF... | 4107955 | 913 days ago | IN | 0 GLMR | 0.01160636 | ||||
| Set Favourite NF... | 4107815 | 913 days ago | IN | 0 GLMR | 0.00678725 | ||||
| Set Favourite NF... | 4107324 | 913 days ago | IN | 0 GLMR | 0.0053099 | ||||
| Set Favourite NF... | 4100225 | 914 days ago | IN | 0 GLMR | 0.004913 | ||||
| Set Favourite NF... | 4094077 | 915 days ago | IN | 0 GLMR | 0.01069301 |
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-07-15
*/
// 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 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);
}
}
}
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;
}
}
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 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);
}
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;
uint256 public total_holders;
/**
* @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
// 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;
if (_balances[from] == 0 && total_holders > 0) {
total_holders--;
}
add_nft_before_transfer(tokenId, to);
if (_balances[to] == 0) {
total_holders++;
}
_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
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender());
}
/**
* @dev Leaves the contract without It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the
*/
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
*/
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 Addresses {
// Wallets
address public community_wallet =
0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
address public development_wallet =
0x9060723c22dE586c2fA5eFa07A7743F6f4a935f5;
address public managment_wallet =
0xc8895f6f85D870589C42fd6d531c855bddD27B0f;
// Contracts
uint256 public contracts_id = 1;
Clock public Cycle;
User public Qualification;
ERC20 public Able;
Sinergy public SinergyBronze;
Sinergy public SinergySilver;
Sinergy public SinergyGold;
Test public VideoTest;
SinergySale public AbleSale;
Migration public MigrationSinergy;
MigrationSale public MigrationSinergySale;
BaseReward public StablecoinBaseReward;
ValueReward public StablecoinValueReward;
ValueReward public AbleValueReward;
ConstancyReward public StablecoinConstancyReward;
ConstancyReward public AbleConstancyReward;
ConfidenceReward public StablecoinConfidenceReward;
ConfidenceReward public AbleConfidenceReward;
SinergyNovember public NovemberSinergyBronzeContract; // Noviembre 2022
SinergyApril public AprilSinergyBronzeContract; // Abril 2023
SinergySaleMigration public AprilSinergySaleContract; // Abril 2023
Migration public AprilMigrationSinergy; // Abril 2023
ERC20Migration public AprilAbleContract; // April 2023
ERC20Migration public NovemberAbleContract; // November 2022
ERC20Migration public TripleMigration; // November 2022
// ERC20s
ERC20 public Stablecoin;
ERC20 public USDC;
ERC20 public USDT;
// Decimals
uint256 public USDC_DECIMALS = 6;
uint256 public USDT_DECIMALS = 6;
function RefreshAll() public {
RefreshCycle();
RefreshQualification();
RefreshAble();
RefreshSinergyBronze();
RefreshSinergySilver();
RefreshSinergyGold();
RefreshVideoTest();
RefreshAbleSale();
RefreshMigrationSinergy();
RefreshMigrationSinergySale();
RefreshStablecoinBaseReward();
RefreshAbleConstancyReward();
RefreshStablecoinValueReward();
RefreshAbleValueReward();
RefreshStablecoinConstancyReward();
RefreshStablecoinConfidenceReward();
RefreshAbleConfidenceReward();
}
function RefreshCycle() public {
if (address(Cycle) == address(0)) return;
Cycle.RefreshContracts();
}
function RefreshQualification() public {
if (address(Qualification) == address(0)) return;
Qualification.RefreshContracts();
}
function RefreshAble() public {
if (address(Able) == address(0)) return;
Able.RefreshContracts();
}
function RefreshSinergyBronze() public {
if (address(SinergyBronze) == address(0)) return;
SinergyBronze.RefreshContracts();
}
function RefreshSinergySilver() public {
if (address(SinergySilver) == address(0)) return;
SinergySilver.RefreshContracts();
}
function RefreshSinergyGold() public {
if (address(SinergyGold) == address(0)) return;
SinergyGold.RefreshContracts();
}
function RefreshVideoTest() public {
if (address(VideoTest) == address(0)) return;
VideoTest.RefreshContracts();
}
function RefreshAbleSale() public {
if (address(AbleSale) == address(0)) return;
AbleSale.RefreshContracts();
}
function RefreshMigrationSinergy() public {
if (address(MigrationSinergy) == address(0)) return;
MigrationSinergy.RefreshContracts();
}
function RefreshMigrationSinergySale() public {
if (address(MigrationSinergySale) == address(0)) return;
MigrationSinergySale.RefreshContracts();
}
function RefreshStablecoinBaseReward() public {
if (address(StablecoinBaseReward) == address(0)) return;
StablecoinBaseReward.RefreshContracts();
}
function RefreshAbleConstancyReward() public {
if (address(AbleConstancyReward) == address(0)) return;
AbleConstancyReward.RefreshContracts();
}
function RefreshStablecoinValueReward() public {
if (address(StablecoinValueReward) == address(0)) return;
StablecoinValueReward.RefreshContracts();
}
function RefreshAbleValueReward() public {
if (address(AbleValueReward) == address(0)) return;
AbleValueReward.RefreshContracts();
}
function RefreshStablecoinConstancyReward() public {
if (address(StablecoinConstancyReward) == address(0)) return;
StablecoinConstancyReward.RefreshContracts();
}
function RefreshStablecoinConfidenceReward() public {
if (address(StablecoinConfidenceReward) == address(0)) return;
StablecoinConfidenceReward.RefreshContracts();
}
function RefreshAbleConfidenceReward() public {
if (address(AbleConfidenceReward) == address(0)) return;
AbleConfidenceReward.RefreshContracts();
}
function IsOwner(address wallet) public view returns (bool) {
return (wallet == community_wallet ||
wallet == development_wallet ||
wallet == managment_wallet);
}
// Set Functions
function SetCommunityWallet(address wallet) public {
require(
msg.sender == community_wallet,
"Only community wallet can change the community wallet"
);
community_wallet = wallet;
}
function SetDevelopmentWallet(address wallet) public {
require(
msg.sender == development_wallet,
"Only development wallet can change the community wallet"
);
development_wallet = wallet;
}
function SetManagmentWallet(address wallet) public {
require(
msg.sender == managment_wallet,
"Only management wallet can change the community wallet"
);
managment_wallet = wallet;
}
function SetClock(address wallet) public {
require(IsOwner(msg.sender), "Only Owner can modify Clock Contract.");
Cycle = Clock(wallet);
contracts_id++;
}
function SetUser(address wallet) public {
require(IsOwner(msg.sender), "Only Owner can modify User Contract.");
Qualification = User(wallet);
contracts_id++;
}
function SetAble(address wallet) public {
require(IsOwner(msg.sender), "Only Owner can modify Able Contract.");
Able = ERC20(wallet);
contracts_id++;
}
function SetSinergyBronze(address sinergy) public {
require(
IsOwner(msg.sender),
"Only Owner can modify Sinergy Bronze Contract"
);
SinergyBronze = Sinergy(sinergy);
contracts_id++;
}
function SetSinergySilver(address sinergy) public {
require(
IsOwner(msg.sender),
"Only Owner can modify Sinergy Silver Contract"
);
SinergySilver = Sinergy(sinergy);
contracts_id++;
}
function SetSinergyGold(address sinergy) public {
require(
IsOwner(msg.sender),
"Only Owner can modify Sinergy Gold Contract"
);
SinergyGold = Sinergy(sinergy);
contracts_id++;
}
function SetTest(address wallet) public {
require(IsOwner(msg.sender), "Only Owner can modify Test Contract.");
VideoTest = Test(wallet);
contracts_id++;
}
function SetSinergySale(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify SinergySale Contract."
);
AbleSale = SinergySale(wallet);
contracts_id++;
}
function SetMigrationSinergy(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify MigrationSinergy Contract."
);
MigrationSinergy = Migration(wallet);
contracts_id++;
}
function SetMigrationSinergySale(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify MigrationSinergySale Contract."
);
MigrationSinergySale = MigrationSale(wallet);
contracts_id++;
}
function SetStablecoinBaseReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify StablecoinBaseReward Contract."
);
StablecoinBaseReward = BaseReward(wallet);
contracts_id++;
}
function SetStablecoinValueReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify StablecoinValueReward Contract."
);
StablecoinValueReward = ValueReward(wallet);
contracts_id++;
}
function SetAbleValueReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AbleValueReward Contract."
);
AbleValueReward = ValueReward(wallet);
contracts_id++;
}
function SetStablecoinConstancyReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify StablecoinConstancyReward Contract."
);
StablecoinConstancyReward = ConstancyReward(wallet);
contracts_id++;
}
function SetAbleConstancyReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AbleConstancyReward Contract."
);
AbleConstancyReward = ConstancyReward(wallet);
contracts_id++;
}
function SetStablecoinConfidenceReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify StablecoinConfidenceReward Contract."
);
StablecoinConfidenceReward = ConfidenceReward(wallet);
contracts_id++;
}
function SetAbleConfidenceReward(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AbleConfidenceReward Contract."
);
AbleConfidenceReward = ConfidenceReward(wallet);
contracts_id++;
}
function SetNovemberSinergyBronzeContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify NovemberSinergyBronzeContract Contract."
);
NovemberSinergyBronzeContract = SinergyNovember(wallet);
contracts_id++;
}
function SetAprilSinergyBronzeContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AprilSinergyBronzeContract Contract."
);
AprilSinergyBronzeContract = SinergyApril(wallet);
contracts_id++;
}
function SetAprilSinergySaleContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AprilSinergySaleContract Contract."
);
AprilSinergySaleContract = SinergySaleMigration(wallet);
contracts_id++;
}
function SetAprilAbleContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify AprilAble Contract."
);
AprilAbleContract = ERC20Migration(wallet);
contracts_id++;
}
function SetAprilMigrationSinergy(address wallet) public {
require(
IsOwner(msg.sender),
"Only owner can modify AprilMigrationSinergy"
);
AprilMigrationSinergy = Migration(wallet);
}
function SetNovemberAbleContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify NovemberAble Contract."
);
NovemberAbleContract = ERC20Migration(wallet);
contracts_id++;
}
function SetTripleMigrationContract(address wallet) public {
require(
IsOwner(msg.sender),
"Only Owner can modify TripleMigration Contract."
);
TripleMigration = ERC20Migration(wallet);
contracts_id++;
}
function SetStablecoin(address wallet) public {
require(IsOwner(msg.sender), "Only owners can set stablecoin.");
Stablecoin = ERC20(wallet);
}
function SetUSDC(address wallet) public {
require(IsOwner(msg.sender), "Only owners can set USDC.");
USDC = ERC20(wallet);
}
function SetUSDT(address wallet) public {
require(IsOwner(msg.sender), "Only owners can set USDT.");
USDT = ERC20(wallet);
}
// Set Decimals
function SetUSDCDecimals(uint256 decimals) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the USDC Decimals."
);
USDC_DECIMALS = decimals;
}
function SetUSDTDecimals(uint256 decimals) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the USDC Decimals."
);
USDT_DECIMALS = decimals;
}
}
contract Router {
// Addresses
Addresses Wallets = Addresses(0xF7Ca5aeb3d2DBC0012f153224e22a1757c8f83F5);
// Contracts
uint256 public contracts_id = 1;
Clock Cycle;
User Qualification;
ERC20 Able;
Sinergy public SinergyBronze;
Sinergy SinergySilver;
Sinergy SinergyGold;
Test VideoTest;
SinergySale AbleSale;
Migration public MigrationSinergy;
MigrationSale MigrationSinergySale;
BaseReward StablecoinBaseReward;
ValueReward StablecoinValueReward;
ValueReward AbleValueReward;
ConstancyReward StablecoinConstancyReward;
ConstancyReward AbleConstancyReward;
ConfidenceReward StablecoinConfidenceReward;
ConfidenceReward AbleConfidenceReward;
SinergyNovember NovemberSinergyBronzeContract; // Noviembre 2022
SinergyApril AprilSinergyBronzeContract; // Abril 2023
SinergySaleMigration AprilSinergySaleContract; // Abril 2023
Migration AprilMigrationSinergy; // Abril 2023
ERC20Migration AprilAbleContract; // April 2023
ERC20Migration NovemberAbleContract; // November 2022
ERC20Migration TripleMigration; // November 2022
// ERC20s
ERC20 public Stablecoin;
ERC20 public USDC;
ERC20 public USDT;
function RefreshContracts() public {
uint256 w_contracts_id = Wallets.contracts_id();
if (contracts_id == w_contracts_id) return;
contracts_id = w_contracts_id;
Cycle = Clock(Wallets.Cycle());
Qualification = User(Wallets.Qualification());
Able = ERC20(Wallets.Able());
SinergyBronze = Sinergy(Wallets.SinergyBronze());
SinergySilver = Sinergy(Wallets.SinergySilver());
SinergyGold = Sinergy(Wallets.SinergyGold());
VideoTest = Test(Wallets.VideoTest());
AbleSale = SinergySale(Wallets.AbleSale());
MigrationSinergy = Migration(Wallets.MigrationSinergy());
MigrationSinergySale = MigrationSale(Wallets.MigrationSinergySale());
StablecoinBaseReward = BaseReward(Wallets.StablecoinBaseReward());
StablecoinValueReward = ValueReward(Wallets.StablecoinValueReward());
AbleValueReward = ValueReward(Wallets.AbleValueReward());
StablecoinConstancyReward = ConstancyReward(
Wallets.StablecoinConstancyReward()
);
AbleConstancyReward = ConstancyReward(Wallets.AbleConstancyReward());
StablecoinConfidenceReward = ConfidenceReward(
Wallets.StablecoinConfidenceReward()
);
AbleConfidenceReward = ConfidenceReward(Wallets.AbleConfidenceReward());
NovemberSinergyBronzeContract = SinergyNovember(
Wallets.NovemberSinergyBronzeContract()
);
AprilSinergyBronzeContract = SinergyApril(
Wallets.AprilSinergyBronzeContract()
);
AprilSinergySaleContract = SinergySaleMigration(
Wallets.AprilSinergySaleContract()
);
AprilMigrationSinergy = Migration(Wallets.AprilMigrationSinergy());
AprilAbleContract = ERC20Migration(Wallets.AprilAbleContract());
NovemberAbleContract = ERC20Migration(Wallets.NovemberAbleContract());
TripleMigration = ERC20Migration(Wallets.TripleMigration());
Stablecoin = ERC20(Wallets.Stablecoin());
USDC = ERC20(Wallets.USDC());
USDT = ERC20(Wallets.USDT());
}
function SetAddresses(address wallet) public {
require(Wallets.IsOwner(msg.sender), "Only owner can set Addresses.");
Wallets = Addresses(wallet);
}
}
contract SinergySaleMigration {
// Constants
uint256 public constant TIME_OF_CYCLE = 1 days;
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
ERC20Migration public ABLE =
ERC20Migration(0x0b85cCA1814eE40C6E83E3591F3819eC7e87d0A5);
ERC20 public TOKEN = ERC20(0x0b85cCA1814eE40C6E83E3591F3819eC7e87d0A5);
ERC20 public BUSD = ERC20(0x765277EebeCA2e31912C9946eAe1021199B39C61);
// ERC721 Contract
SinergyMigration public SinergyContract =
SinergyMigration(0xaeFDeD1Efb9f370F3663493755a1Da0A4E6F17E6);
// 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() {}
// 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 = SinergyMigration(_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 SinergySale is Router {
// Constants
uint256 public MAX_AMOUNT_SELL_TOKEN = 90 ether;
uint256 public MIN_AMOUNT_SELL_TOKEN = 9 ether;
uint256 public MIN_AMOUNT_TOKENS_TO_SELL;
uint256 public TOKEN_PRICE = 3; // 1 TOKEN = 3 STABLECOIN
uint256 public LIMIT_POST_BY_CYCLE = 1;
uint256 public PENALIZATION_PLACES = 3;
uint256 public LIMIT_POST_BY_WALLET = 9;
// Global Variables
bool public need_be_qualified_to_sell;
uint256 public TOTAL_TOKENS_SOLD;
mapping(uint256 => uint256) public tokens_sold_by_cycle;
// ERC20 Contracts
ERC20 public ABLE;
ERC20 public TOKEN;
ERC20 public STABLECOIN;
// Sell List
uint256[] public sell_list;
mapping(uint256 => bool) public is_in_sell_list;
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;
// User Data
mapping(address => mapping(uint256 => uint256)) public post_by_cycle;
mapping(address => uint256) public amount_sold_of;
mapping(address => uint256) public post_amount_of;
mapping(address => mapping(uint256 => uint256))
public amount_bought_by_cycle_of;
address public last_wallet_qualified_who_bought;
// 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 SellTokenPenalization(
uint256 indexed nft_id,
address indexed buyer,
address indexed seller,
uint256 amount
);
event SwapList(uint256 indexed nft_id);
// Constructor
constructor(ERC20 _able, ERC20 _busd, ERC20 _token) {
ABLE = _able;
TOKEN = _token;
STABLECOIN = _busd;
}
// Migrate Functions
function Migrate_Send_Sell_List(
uint256 token_id,
uint256 selling_amount
) public {
require(
msg.sender == address(MigrationSinergySale),
"Only Migration Contract can migrate sell list."
);
selling_amount_of[token_id] = selling_amount;
total_selling_amount += selling_amount;
_SetNftToSellList(token_id);
}
function Migrate_Send_Driven_List(
uint256 token_id,
uint256 selling_amount
) public {
require(
msg.sender == address(MigrationSinergySale),
"Only Migration Contract can migrate driven list."
);
selling_amount_of[token_id] = selling_amount;
total_selling_amount += selling_amount;
_SetNftToDrivenList(token_id);
}
// Public Methods
function Sell(uint256 _amount, uint256 _tokenID) public {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
require(
_amount >= MIN_AMOUNT_SELL_TOKEN,
"The amount to sell is too low."
);
require(
(selling_amount_of[_tokenID] + _amount) <= MAX_AMOUNT_SELL_TOKEN,
"The amount to sell is too high."
);
require(
SinergyBronze.ownerOf(_tokenID) == msg.sender,
"You are not the owner of this NFT."
);
require(
!IsSelling(_tokenID),
"This NFT is already selling tokens on Sinergy Sale"
);
require(
CanSell(msg.sender),
"You already get the limit of post by cycle."
);
require(
amount_of_post_of[msg.sender] < LIMIT_POST_BY_WALLET,
"This wallet cannot post more sells on the list."
);
if (need_be_qualified_to_sell) {
require(
Qualification.IsQualified(msg.sender),
"You have to be qualified to sell"
);
}
TOKEN.transferFrom(msg.sender, address(this), _amount);
selling_amount_of[_tokenID] += _amount;
total_selling_amount += _amount;
post_by_cycle[msg.sender][cycle]++;
if (CanBeInDrivenList(msg.sender)) {
_SetNftToDrivenList(_tokenID);
turns_in_driven_list_of[msg.sender]++;
} else {
_SetNftToSellList(_tokenID);
}
}
function Buy(uint256 _amount, bool incrementBDD) public {
require(
Qualification.is_updated(msg.sender, Cycle.cycle()),
"You have to update first."
);
require(
_amount <= total_selling_amount,
"Sinergy Sale doesn't have enought Able to sell that amount."
);
// Transferimos los STABLECOIN a este contrato
STABLECOIN.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 _SellAbleFromList
// Transferimos 33% para el Admin
STABLECOIN.transfer(
Wallets.managment_wallet(),
((_amount * TOKEN_PRICE) / 3)
);
// Transferimos 33% para el Bote del Regalo Diario de Able
STABLECOIN.transfer(
address(StablecoinBaseReward),
((_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) = _FindSellers(
_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++) {
_RemoveFirstNftFromSellList();
}
for (uint256 i = 0; i < nfts_to_remove_driven; i++) {
_RemoveFirstNftFromDrivenList();
}
// Aumentamos el BDD de esta billetera en ABLE
if (incrementBDD)
ABLE.IncreasePoints(_amount * TOKEN_PRICE, msg.sender);
// Aumentamos la cantidad de tokens vendidos.
TOTAL_TOKENS_SOLD += _amount;
tokens_sold_by_cycle[Cycle.cycle()] += _amount;
// Aumentamos la cantidad de tokens comprados por ciclo.
amount_bought_by_cycle_of[msg.sender][Cycle.cycle()] +=
_amount *
TOKEN_PRICE;
if (Qualification.IsQualified(msg.sender)) {
last_wallet_qualified_who_bought = msg.sender;
}
}
function QuitSell(uint256 tokenID) public {
require(
Qualification.is_updated(msg.sender, Cycle.cycle()),
"You have to update first."
);
require(IsSelling(tokenID), "This NFT is not selling.");
require(
SinergyBronze.ownerOf(tokenID) == msg.sender,
"You are not the owner of this NFT."
);
require(
selling_amount_of[tokenID] > 0,
"Your NFT doesnt have anything to sell in the list."
);
require(
total_selling_amount >= selling_amount_of[tokenID],
"The amount that you are selling is greater than all the other sells. :("
);
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]) {
_RemoveNftFromSellList(_GetIndexOfNftFromSellList(tokenID));
} else {
_RemoveNftFromDrivenList(_GetIndexOfNftFromDrivenList(tokenID));
}
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Get Methods
function GetSellListLength() public view returns (uint256) {
return sell_list.length;
}
function GetDrivenListLength() public view returns (uint256) {
return driven_list.length;
}
// Set Functions
function SetMinAmountTokensToSell(uint256 amount) public {
require(
IsOwner(msg.sender),
"Only owner can modify the MIN_AMOUNT_TOKENS_TO_SELL."
);
MIN_AMOUNT_TOKENS_TO_SELL = amount;
}
function SetLimitPostByCycle(uint256 new_limit) public {
require(
IsOwner(msg.sender),
"You are not qualified to call this function."
);
LIMIT_POST_BY_CYCLE = new_limit;
}
function SetMaxAmountSellToken(uint256 amount) public {
require(
IsOwner(msg.sender),
"You are not qualified to call this function"
);
MAX_AMOUNT_SELL_TOKEN = amount;
}
function SetMinAmountSellToken(uint256 amount) public {
require(
IsOwner(msg.sender),
"You are not qualified to call this function"
);
MIN_AMOUNT_SELL_TOKEN = amount;
}
function SetPriceToken(uint256 amount) public {
require(
IsOwner(msg.sender),
"You are not qualified to call this function"
);
TOKEN_PRICE = amount * (1 ether);
}
function SetPenalizePlaces(uint256 places) public {
require(
IsOwner(msg.sender),
"You are not qualified to set the penalize places."
);
PENALIZATION_PLACES = places;
}
function SetNeedBeQualifiedToSell() public {
require(
IsOwner(msg.sender),
"You are not qualified to set the need be qualified to sell."
);
need_be_qualified_to_sell = !need_be_qualified_to_sell;
}
function SetLimitPostByWallet(uint256 limit) public {
require(
IsOwner(msg.sender),
"You are not qualified to set the need be qualified to sell."
);
LIMIT_POST_BY_WALLET = limit;
}
// Communication
function TryToSwap(uint256 _tokenID) public {
require(
msg.sender == address(SinergyBronze),
"Only SinergyContract can call to this function."
);
if (
IsSelling(_tokenID) &&
is_in_sell_list[_tokenID] &&
(_GetIndexOfNftFromSellList(_tokenID) > driven_list.length)
) {
_RemoveNftFromSellList(_GetIndexOfNftFromSellList(_tokenID));
_SetNftToDrivenList(_tokenID);
emit SwapList(_tokenID);
}
}
// Helpers
function IsSelling(uint256 _tokenID) public view returns (bool) {
return is_in_sell_list[_tokenID] || is_in_driven_list[_tokenID];
}
// If the owner of the NFT was not qualified in the previous
// cycle, the NFT will be penalized.
function IsNftPenalized(uint256 tokenID) public view returns (bool) {
address wallet = SinergyBronze.ownerOf(tokenID);
return
!Qualification.qualified_history(wallet, Cycle.cycle() - 1) ||
(Able.balanceOf(wallet) < MIN_AMOUNT_TOKENS_TO_SELL);
}
// Sell Helpers
function IsSellTurn() public view returns (bool) {
return (turn == 2);
}
function SellListIsEmpty() public view returns (bool) {
return sell_list.length == 0;
}
function CanUseSell() public view returns (bool) {
return (!SellListIsEmpty() && (IsSellTurn() || DrivenListIsEmpty()));
}
function CanSell(address wallet) public view returns (bool) {
if (
post_by_cycle[wallet][Cycle.cycle()] < LIMIT_POST_BY_CYCLE &&
Able.balanceOf(wallet) >= MIN_AMOUNT_TOKENS_TO_SELL
) {
return true;
}
return false;
}
// Driven Helpers
function CanBeInDrivenList(address wallet) public view returns (bool) {
return
ABLE.won_able_reward(wallet) &&
ABLE.amount_of_wins_able_reward_of(wallet) >
turns_in_driven_list_of[wallet];
}
function IsDrivenTurn() public view returns (bool) {
return turn == 0 || turn == 1;
}
function DrivenListIsEmpty() public view returns (bool) {
return driven_list.length == 0;
}
function CanUseDriven() public view returns (bool) {
return (!DrivenListIsEmpty() && (IsDrivenTurn() || SellListIsEmpty()));
}
// Private Methods
function _SetNftToSellList(uint256 _tokenID) private {
sell_list.push(_tokenID);
is_in_sell_list[_tokenID] = true;
emit SellList(_tokenID, true, false);
}
function _SetNftToDrivenList(uint256 _tokenID) private {
driven_list.push(_tokenID);
is_in_driven_list[_tokenID] = true;
emit SellList(_tokenID, true, true);
}
function _RemoveFirstNftFromSellList() 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 _RemoveFirstNftFromDrivenList() 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 _RemoveNftFromSellList(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 _RemoveNftFromDrivenList(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 _GetIndexOfNftFromSellList(
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 _GetIndexOfNftFromDrivenList(
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 _SellAbleFromList(
uint256 _amount,
uint256 _tokenID,
address buyer
) private {
address owner = SinergyBronze.ownerOf(_tokenID);
selling_amount_of[_tokenID] -= _amount;
total_selling_amount -= _amount;
// 33% van directo al usuario
STABLECOIN.transfer(owner, ((_amount * TOKEN_PRICE) / 3));
amount_sold_of[owner] += ((_amount * TOKEN_PRICE) / 3);
emit SellToken(_tokenID, buyer, owner, _amount);
}
function _SellAbleFromListPenalize(
uint256 _amount,
uint256 _tokenID,
address buyer
) private {
address owner = SinergyBronze.ownerOf(_tokenID);
selling_amount_of[_tokenID] -= _amount;
total_selling_amount -= _amount;
// 16.5% van directo al usuario
STABLECOIN.transfer(owner, ((_amount * TOKEN_PRICE) / 6));
amount_sold_of[owner] += ((_amount * TOKEN_PRICE) / 6);
// 16.5% van directo al regalo diario de Able
STABLECOIN.transfer(
address(StablecoinBaseReward),
((_amount * TOKEN_PRICE) / 6)
);
emit SellTokenPenalization(_tokenID, buyer, owner, _amount);
}
// Turn Helper
function _IncrementTurn() private {
if (turn == 2) {
turn = 0;
} else {
turn++;
}
}
function _FindSellers(
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 (
CanUseDriven() && 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++;
}
if (IsNftPenalized(nft_id)) {
_SellAbleFromListPenalize(_amount, nft_id, buyer);
} else {
_SellAbleFromList(_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];
if (IsNftPenalized(nft_id)) {
_SellAbleFromListPenalize(
selling_amount_of[nft_id],
nft_id,
buyer
);
} else {
_SellAbleFromList(
selling_amount_of[nft_id],
nft_id,
buyer
);
}
nfts_to_remove_driven++;
}
idx_driven++;
_IncrementTurn();
}
// Sell List
while (CanUseSell() && 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++;
}
if (IsNftPenalized(nft_id)) {
_SellAbleFromListPenalize(_amount, nft_id, buyer);
} else {
_SellAbleFromList(_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];
if (IsNftPenalized(nft_id)) {
_SellAbleFromListPenalize(
selling_amount_of[nft_id],
nft_id,
buyer
);
} else {
_SellAbleFromList(
selling_amount_of[nft_id],
nft_id,
buyer
);
}
nfts_to_remove_sell++;
}
idx_sell++;
_IncrementTurn();
}
}
return (nfts_to_remove_sell, nfts_to_remove_driven);
}
}
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);
// Owners
Addresses public Wallets =
Addresses(0xbc4E59AE11A28214f84FCc1c9B0535355D408BBf);
// ERC20's
ERC20 CDA = ERC20(0x8e3153a724aF487Fd11fB4C4cDA508984dEDf3c4);
ERC20 ABLE = ERC20(0xd9B9c7A1B42f1ad78D9C3Dd5C7F0381277ddc9Bb);
ERC20 STABLECOIN = 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_SALE.last_wallet_qualified_who_bought()
];
if (_ref != 0) {
_reference = _ref;
}
if (_reference == 0) {
_reference = 8;
}
require(_reference < _tokenIds.current());
STABLECOIN.transferFrom(msg.sender, address(this), PRICE);
update_qualified_nfts(msg.sender);
ABLE_SALE.TryToSwap(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 STABLECOIN'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));
STABLECOIN.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 STABLECOIN 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
);
STABLECOIN.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) {}
function claimPassiveReward() public {}
function claimConstancyReward() public {}
function claimResources() public {
require(msg.sender == developmentWallet);
STABLECOIN.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 pure returns (bool) {
// This is a Random code just to make compile the interface of the Migration Contract without Warnings.
return (tokenID == 0);
}
// Update Functions
function update_qualified_nfts(address wallet) private {}
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 {}
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 {}
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);
}
}
contract SinergyNovember is ERC721, ERC721URIStorage, Ownable {
// Constants
uint256 public constant PRICE = 36 ether;
uint256 public constant REWARD = 3 ether;
uint256 public constant TO_DEVELOPMENT = 3 ether;
// MSG_FAIL_TRANSFER
string constant MSG_FAIL_TRANSFER_XBUSD = "BUSD TRANSFER FAILED";
string constant MSG_FAIL_TRANSFER_BUSD = "BUSD TRANSFER FAILED";
string constant MSG_FAIL_TRANSFER_CDA = "CDA TRANSFER FAILED";
string constant MSG_FAIL_TRANSFER_ABLE = "ABLE TRANSFER FAILED";
string constant MSG_FAIL_OWNER_NFT = "You are not the owner of this NFT";
// MSG_FAIL_EVENT
string constant MSG_FAIL_EVENT_ATTENDANCE =
"You already are in the list of this event";
string constant MSG_FAIL_EVENT_NOT_EXIST = "This event doesn't exist yet";
string constant MSG_FAIL_NFT_NOT_EXIST = "This NFT doesn't exist yet";
// MSG_FAIL_REWARD
string constant MSG_FAIL_REWARD = "You don't have any reward to claim";
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(0x38e43FCEEE68373e08a30714123010b8d841364d);
// ERC20's
ERC20 CDA = ERC20(0x38e43FCEEE68373e08a30714123010b8d841364d);
ERC20 ABLE = ERC20(0xB13D289830F6512dFf4C6ce97f121F29bD400E39);
ERC20 BUSD = ERC20(0xd9C7C02dBF4451d89040cd2a576b615327ccF38b);
// Able Sale
SinergySale public ABLE_SALE =
SinergySale(0xd9C7C02dBF4451d89040cd2a576b615327ccF38b);
SinergySale public TRIPLE_SALE =
SinergySale(0xd9C7C02dBF4451d89040cd2a576b615327ccF38b);
// 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;
// Constructor
constructor(uint256 initial_tokenID) ERC721("Saver Sinergy", "Sinergy") {
while (_tokenIds.current() < initial_tokenID) {
_tokenIds.increment();
}
timeToNextReward = block.timestamp + oneDay;
}
// Migration
mapping(address => bool) public isRecover;
// 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;
// Events
event Mint(
uint256 id,
uint256 date,
string indexed name,
string indexed valueProposal,
address indexed wallet
);
event PassiveReward(
uint256 amount,
address indexed wallet,
uint256 indexed date
);
event Resources(uint256 indexed date, uint256 amount);
// Public Functions
// Migration
function migrate() public {
require(!isRecover[msg.sender], "You already migrated.");
uint256 amountNFTs = ContractMigration.balanceOf(msg.sender);
for (uint256 i = 0; i < amountNFTs; i++) {
get_my_nfts[msg.sender][i] = ContractMigration.get_my_nfts(
msg.sender,
i
);
recoverNFT(get_my_nfts[msg.sender][i]);
}
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);
// 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);
recoverFirstLevelReferences(
get_first_level_amount_reference[nftID],
nftID
);
recoverSecondLevelReferences(
get_second_level_amount_reference[nftID],
nftID
);
recoverThirdLevelReferences(
get_third_level_amount_reference[nftID],
nftID
);
recoverFourLevelReferences(
get_four_level_amount_reference[nftID],
nftID
);
recoverFiveLevelReferences(
get_five_level_amount_reference[nftID],
nftID
);
recoverSixLevelReferences(get_six_level_amount_reference[nftID], nftID);
recoverSevenLevelReferences(
get_seven_level_amount_reference[nftID],
nftID
);
recoverEightLevelReferences(
get_eight_level_amount_reference[nftID],
nftID
);
recoverNineLevelReferences(
get_nine_level_amount_reference[nftID],
nftID
);
}
function recoverFirstLevelReferences(
uint256 amount,
uint256 nftID
) private {
for (uint256 i = 0; i < amount; i++) {
get_first_level_references[nftID][i] = ContractMigration
.get_first_level_references(nftID, i);
}
}
function recoverSecondLevelReferences(
uint256 amount,
uint256 nftID
) private {
for (uint256 i = 0; i < amount; i++) {
get_second_level_references[nftID][i] = ContractMigration
.get_second_level_references(nftID, i);
}
}
function recoverThirdLevelReferences(
uint256 amount,
uint256 nftID
) private {
for (uint256 i = 0; i < amount; i++) {
get_third_level_references[nftID][i] = ContractMigration
.get_third_level_references(nftID, i);
}
}
function recoverFourLevelReferences(uint256 amount, uint256 nftID) private {
for (uint256 i = 0; i < amount; i++) {
get_four_level_references[nftID][i] = ContractMigration
.get_four_level_references(nftID, i);
}
}
function recoverFiveLevelReferences(uint256 amount, uint256 nftID) private {
for (uint256 i = 0; i < amount; i++) {
get_five_level_references[nftID][i] = ContractMigration
.get_five_level_references(nftID, i);
}
}
function recoverSixLevelReferences(uint256 amount, uint256 nftID) private {
for (uint256 i = 0; i < amount; i++) {
get_six_level_references[nftID][i] = ContractMigration
.get_six_level_references(nftID, i);
}
}
function recoverSevenLevelReferences(
uint256 amount,
uint256 nftID
) private {
for (uint256 i = 0; i < amount; i++) {
get_seven_level_references[nftID][i] = ContractMigration
.get_seven_level_references(nftID, i);
}
}
function recoverEightLevelReferences(
uint256 amount,
uint256 nftID
) private {
for (uint256 i = 0; i < amount; i++) {
get_eight_level_references[nftID][i] = ContractMigration
.get_eight_level_references(nftID, i);
}
}
function recoverNineLevelReferences(uint256 amount, uint256 nftID) private {
for (uint256 i = 0; i < amount; i++) {
get_nine_level_references[nftID][i] = ContractMigration
.get_nine_level_references(nftID, i);
}
}
// NFT
function createNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
string memory _uri,
string memory _imageURL,
uint256 _timestamp
) public {}
function modifyNFT(
string memory _name,
string memory _inscription,
string memory _valueProposal,
uint256 _tokenID
) public {
require(msg.sender == ownerOf(_tokenID), MSG_FAIL_OWNER_NFT);
require(
BUSD.transferFrom(msg.sender, address(this), PRICE),
MSG_FAIL_TRANSFER_BUSD
);
// 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 {}
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) {
if (wallet == address(0)) return balanceOf(msg.sender);
return 0;
}
function claimPassiveReward() public {}
function claimConstancyReward() public {}
function claimResources() public {
require(
msg.sender == communityWallet,
"You are not qualified to call this function"
);
BUSD.transfer(communityWallet, resourcesAmount);
CDA.transfer(communityWallet, CDA.balanceOf(address(this)));
ABLE.transfer(communityWallet, ABLE.balanceOf(address(this)));
// 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,
"You are not qualified to call this function"
);
ABLE = ERC20(_ableAddress);
}
function setFavouriteNFT(uint256 id) public {
require(_tokenIds.current() > id, "This NFT doesn't exist yet");
favourite_nft[msg.sender] = id;
update(msg.sender);
}
function changeCommunityWallet(address newAddress) public {
require(
msg.sender == communityWallet,
"You are not able to call this function"
);
communityWallet = newAddress;
}
function getDifference(
uint256 a,
uint256 b
) private pure returns (uint256) {
if (a > b) {
return a - b;
}
return b - a;
}
// Booleans
function nft_was_qualified(uint256 tokenID) public view returns (bool) {
if (tokenID == 0) return balanceOf(msg.sender) == 0;
return true;
}
// Update Functions
function update_qualified_nfts(address wallet) private {}
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 {}
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,
"Only Development Wallet can call to this function."
);
ABLE_SALE = ableSale;
}
function set_triple_sale(SinergySale tripleSale) public {
require(
msg.sender == developmentWallet,
"Only Development Wallet can call to this function."
);
TRIPLE_SALE = tripleSale;
}
function set_passive_rewards(uint256 amount) public {
require(
msg.sender == address(ABLE_SALE) ||
msg.sender == address(TRIPLE_SALE),
"Only ABLE_SALE or TRIPLE_SALE can call to this function"
);
passiveReward[passiveRewardID] += amount;
}
function set_active_rewards(uint256 tokenID, uint256 amount) public {
require(
msg.sender == address(ABLE_SALE) ||
msg.sender == address(TRIPLE_SALE),
"Only ABLE_SALE or TRIPLE_SALE can call to this function"
);
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),
"Only ABLE_SALE or TRIPLE_SALE can call to this function"
);
constancyReward[passiveRewardID] += amount;
}
// Private Functions
// Distribute 9 generations
function distribute(
uint256 tokenID,
uint256 _reference,
bool created
) private {}
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);
}
}
contract SinergyApril 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;
// 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 {}
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) {}
// Update Functions
function update_qualified_nfts(address wallet) private {}
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 {}
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 Sinergy is ERC721, ERC721URIStorage, Ownable, Router {
// Prices
uint256 public PRICE = 36 ether;
uint256 public ABLE_PRICE = 12 ether;
// Amounts to transfer
uint256 public PERCENT_REWARD = 1;
uint256 public PERCENT_DIVIDE_REWARD = 12;
uint256 public PERCENT_STABLECOIN_VALUE_REWARD = 1;
uint256 public PERCENT_DIVIDE_STABLECOIN_VALUE_REWARD = 12;
uint256 public PERCENT_STABLECOIN_CONSTANCY_REWARD = 1;
uint256 public PERCENT_DIVIDE_STABLECOIN_CONSTANCY_REWARD = 12;
uint256 public PERCENT_STABLECOIN_CONFIDENCE_REWARD = 1;
uint256 public PERCENT_DIVIDE_STABLECOIN_CONFIDENCE_REWARD = 12;
uint256 public PERCENT_ABLE_VALUE_REWARD = 1;
uint256 public PERCENT_DIVIDE_ABLE_VALUE_REWARD = 3;
uint256 public PERCENT_ABLE_CONSTANCY_REWARD = 1;
uint256 public PERCENT_DIVIDE_ABLE_CONSTANCY_REWARD = 3;
uint256 public PERCENT_ABLE_CONFIDENCE_REWARD = 1;
uint256 public PERCENT_DIVIDE_ABLE_CONFIDENCE_REWARD = 3;
// 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";
// Requirements to earn affiliate rewards
uint256 public MIN_AMOUNT_FIRST_LEVEL_CONNECTIONS = 3;
// Counters
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 public starting_nft_id;
uint256 public initial_tokenID = 1301;
// Constructor
constructor() ERC721("Offer Sinergy", "Sinergy") {
while (_tokenIds.current() < initial_tokenID) {
_tokenIds.increment();
}
address development_wallet = Wallets.development_wallet();
// Mint NFT
uint256 tokenID = _tokenIds.current();
_tokenIds.increment();
_safeMint(development_wallet, 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[development_wallet] = tokenID;
_setTokenURI(
tokenID,
"ipfs://QmRi1DvgDu6zAJwpbURGNBBQTM82ZCNZAyTkEArbKZKm1U/273.json"
);
get_my_nfts[development_wallet].push(tokenID);
starting_nft_id = initial_tokenID;
total_holders++;
is_holder[development_wallet] = true;
}
// NFT's
mapping(uint256 => uint256) public nfts_qualified_by_cycle;
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;
// 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;
// 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 HandleRecover(
address wallet,
uint256 tokenId,
address migration_contract,
uint256 month_contract
) public {
if (msg.sender != address(MigrationSinergy)) return;
_RecoverNFT(tokenId, migration_contract, month_contract);
get_my_nfts[wallet].push(tokenId);
if (balanceOf(wallet) == 0) {
total_holders++;
}
_safeMint(wallet, tokenId);
if (favourite_nft[wallet] == 0) {
favourite_nft[wallet] = tokenId;
}
if (IsQualified(wallet)) {
nfts_qualified++;
}
}
function HandlerRecoverFirstLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_first_level_references[tokenId].push(
ContractMigration.get_first_level_references(tokenId, index)
);
}
function HandlerRecoverSecondLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_second_level_references[tokenId].push(
ContractMigration.get_second_level_references(tokenId, index)
);
}
function HandlerRecoverThirdLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_third_level_references[tokenId].push(
ContractMigration.get_third_level_references(tokenId, index)
);
}
function HandlerRecoverFourLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_four_level_references[tokenId].push(
ContractMigration.get_four_level_references(tokenId, index)
);
}
function HandlerRecoverFiveLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_five_level_references[tokenId].push(
ContractMigration.get_five_level_references(tokenId, index)
);
}
function HandlerRecoverSixLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_six_level_references[tokenId].push(
ContractMigration.get_six_level_references(tokenId, index)
);
}
function HandlerRecoverSevenLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_seven_level_references[tokenId].push(
ContractMigration.get_seven_level_references(tokenId, index)
);
}
function HandlerRecoverEightLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
get_eight_level_references[tokenId].push(
ContractMigration.get_eight_level_references(tokenId, index)
);
}
function HandlerRecoverNineLevel(
uint256 tokenId,
uint256 index,
address contract_migration
) public {
if (msg.sender != address(MigrationSinergy)) return;
SinergyMigration ContractMigration = SinergyMigration(
contract_migration
);
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 {
if (!IsUpdated(msg.sender)) return;
// Get Reference
uint256 _reference = favourite_nft[
AbleSale.last_wallet_qualified_who_bought()
];
if (_ref != 0) {
_reference = _ref;
}
if (_reference == 0) {
_reference = 8;
}
require(_reference < _tokenIds.current());
Stablecoin.transferFrom(msg.sender, address(this), PRICE);
Able.transferFrom(msg.sender, address(this), ABLE_PRICE);
UpdateQualifiedNfts(msg.sender);
if (balanceOf(msg.sender) > 0) {
AbleSale.TryToSwap(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;
}
get_my_nfts[msg.sender].push(tokenID);
// Transfer to Rewards
_TransferValueRewards();
_TransferConstancyRewards();
_TransferConfidenceRewards();
// Distribute Stablecoin's in 9 generations
_Distribute(tokenID, _reference, true);
// Qualification.Update(msg.sender);
// Aumentamos la cantidad de NFTs creados en este ciclo
nfts_created_by_cycle[GetCycle()]++;
// 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 {
if (!IsUpdated(msg.sender) || msg.sender != ownerOf(_tokenID)) return;
Stablecoin.transferFrom(msg.sender, address(this), PRICE);
Able.transferFrom(msg.sender, address(this), ABLE_PRICE);
// Modify the NFT
get_nft_name[_tokenID] = _name;
get_nft_inscription[_tokenID] = _inscription;
get_nft_value_proposal[_tokenID] = _valueProposal;
// Transfer to Rewards
_TransferValueRewards();
_TransferConstancyRewards();
_TransferConfidenceRewards();
// Distribute Stablecoin in 9 generations
_Distribute(_tokenID, get_nft_reference[_tokenID], false);
// Qualification.Update(msg.sender);
}
function NftWasQualified(uint256 tokenID) public view returns (bool) {
return
IsQualified(ownerOf(tokenID)) ||
Qualification.qualified_history(ownerOf(tokenID), GetCycle() - 1);
}
function CreateGenesisNfts() public {
if (msg.sender != address(MigrationSinergy)) return;
// Crear 8 NFTs para la billetera destinada a Desarrollo y Mantenimiento
// Estos NFTs deben estar vinculados entre si
address community_wallet = Wallets.community_wallet();
for (uint256 i = 0; i < 9; i++) {
_safeMint(community_wallet, i);
_setTokenURI(
i,
"ipfs://QmRi1DvgDu6zAJwpbURGNBBQTM82ZCNZAyTkEArbKZKm1U/0.json"
);
_RecoverNFT(i, address(AprilSinergyBronzeContract), 4);
get_my_nfts[community_wallet].push(i);
nft_affiliate_rewards_earned[i] = AprilSinergyBronzeContract
.nft_affiliate_rewards_earned(i);
}
}
function CloseCycle() public {
if (msg.sender != address(Cycle)) return;
nfts_qualified_by_cycle[GetCycle()] = nfts_qualified;
}
function UpdateQualifiedNfts(address wallet) public {
if (is_qualified[wallet]) {
nfts_qualified -= amount_nfts_considered[wallet];
amount_nfts_considered[wallet] = 0;
is_qualified[wallet] = false;
}
if (IsQualified(wallet)) {
nfts_qualified += balanceOf(wallet);
amount_nfts_considered[wallet] = balanceOf(wallet);
is_qualified[wallet] = true;
}
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
function IsUpdated(address wallet) public view returns (bool) {
return Qualification.is_updated(wallet, GetCycle());
}
function IsQualified(address wallet) public view returns (bool) {
return Qualification.IsQualified(wallet);
}
// Get Functions
function GetAbleBalance(address wallet) public view returns (uint256) {
return Able.balanceOf(wallet);
}
function GetCycle() public view returns (uint256) {
return Cycle.cycle();
}
function GetAmountOfNftMinted() public view returns (uint256) {
return _tokenIds.current();
}
function GetAbleToValueReward() public view returns (uint256) {
return
(ABLE_PRICE * PERCENT_ABLE_VALUE_REWARD) /
PERCENT_DIVIDE_ABLE_VALUE_REWARD;
}
function GetAbleToConstancyReward() public view returns (uint256) {
return
(ABLE_PRICE * PERCENT_ABLE_CONSTANCY_REWARD) /
PERCENT_DIVIDE_ABLE_CONSTANCY_REWARD;
}
function GetAbleToConfidenceReward() public view returns (uint256) {
return
(ABLE_PRICE * PERCENT_ABLE_CONFIDENCE_REWARD) /
PERCENT_DIVIDE_ABLE_CONFIDENCE_REWARD;
}
function GetStablecoinToPassiveReward() public view returns (uint256) {
return
(PRICE * PERCENT_STABLECOIN_VALUE_REWARD) /
PERCENT_DIVIDE_STABLECOIN_VALUE_REWARD;
}
function GetStablecoinToConstancyReward() public view returns (uint256) {
return
(PRICE * PERCENT_STABLECOIN_CONSTANCY_REWARD) /
PERCENT_DIVIDE_STABLECOIN_CONSTANCY_REWARD;
}
function GetStablecoinToConfidenceReward() public view returns (uint256) {
return
(PRICE * PERCENT_STABLECOIN_CONFIDENCE_REWARD) /
PERCENT_DIVIDE_STABLECOIN_CONFIDENCE_REWARD;
}
function GetStablecoinToReward() public view returns (uint256) {
return (PRICE * PERCENT_REWARD) / PERCENT_DIVIDE_REWARD;
}
// Set Functions
function SetFavouriteNFT(address wallet, uint256 id) public {
if (id > _tokenIds.current()) return;
if (
msg.sender != ownerOf(id) && msg.sender != address(MigrationSinergy)
) return;
uint256 previousFavourite = favourite_nft[wallet];
favourite_nft[wallet] = id;
emit ChangeFavourite(msg.sender, previousFavourite, id);
}
// Percentages
// Able Value Reward
function SetAbleValueRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_ABLE_VALUE_REWARD = amount;
}
function SetAbleValueRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_ABLE_VALUE_REWARD = amount;
}
// Able Constancy Reward
function SetAbleConstancyRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_ABLE_CONSTANCY_REWARD = amount;
}
function SetAbleConstancyRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_ABLE_CONSTANCY_REWARD = amount;
}
// Able Confidence Reward
function SetAbleConfidenceRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_ABLE_CONSTANCY_REWARD = amount;
}
function SetAbleConfidenceRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_ABLE_CONFIDENCE_REWARD = amount;
}
// Stablecoin Value Reward
function SetStablecoinValueRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_STABLECOIN_VALUE_REWARD = amount;
}
function SetStablecoinValueRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_STABLECOIN_VALUE_REWARD = amount;
}
// Stablecoin Constancy Reward
function SetStablecoinConstancyRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_STABLECOIN_CONSTANCY_REWARD = amount;
}
function SetStablecoinConstancyRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_STABLECOIN_CONSTANCY_REWARD = amount;
}
// Stablecoin Confidence Reward
function SetStablecoinConfidenceRewardPercent(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_STABLECOIN_CONFIDENCE_REWARD = amount;
}
function SetStablecoinConfidenceRewardPercentDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_STABLECOIN_CONFIDENCE_REWARD = amount;
}
// Affiliative Rewards
function SetStablecoinPercentReward(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_REWARD = amount;
}
function SetStablecoinPercentRewardDivide(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PERCENT_DIVIDE_REWARD = amount;
}
// Prices
function SetStablecoinPrice(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
PRICE = amount * (1 ether);
}
function SetAblePrice(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
ABLE_PRICE = amount * (1 ether);
}
function SetMinAmountFirstLevelConnections(uint256 amount) public {
if (!IsOwner(msg.sender)) return;
MIN_AMOUNT_FIRST_LEVEL_CONNECTIONS = amount;
}
// Private Functions
function _TransferValueRewards() private {
Able.transfer(address(AbleValueReward), GetAbleToValueReward());
Stablecoin.transfer(
address(StablecoinValueReward),
GetStablecoinToPassiveReward()
);
}
function _TransferConstancyRewards() private {
Able.transfer(address(AbleConstancyReward), GetAbleToConstancyReward());
Stablecoin.transfer(
address(StablecoinConstancyReward),
GetStablecoinToConstancyReward()
);
}
function _TransferConfidenceRewards() private {
Able.transfer(
address(AbleConfidenceReward),
GetAbleToConfidenceReward()
);
Stablecoin.transfer(
address(StablecoinConfidenceReward),
GetStablecoinToConfidenceReward()
);
}
// Distribute 9 generations
function _Distribute(
uint256 tokenID,
uint256 _reference,
bool created
) private {
address owner;
uint256 i = 0;
uint256 reward_amount = GetStablecoinToReward();
uint256 commission_reference = _reference;
while (i < 9) {
if (created) _SetReferences(i, tokenID, _reference);
owner = ownerOf(commission_reference);
commission_reference = _TrnasferStablecoin(
owner,
commission_reference,
reward_amount
);
_reference = get_nft_reference[_reference];
i++;
}
}
/*
This function transfer the stablecoin to those NFTs that have the rights to receive it.
And also returns the NFT father of the NFT that receive the transaction.
*/
function _TrnasferStablecoin(
address owner,
uint256 token_id,
uint256 reward_amount
) public returns (uint256) {
while (
get_first_level_amount_reference[token_id] <
MIN_AMOUNT_FIRST_LEVEL_CONNECTIONS &&
token_id != 0
) {
token_id = get_nft_reference[token_id];
owner = ownerOf(token_id);
}
Stablecoin.transfer(owner, reward_amount);
total_stablecoin_earned[owner] += reward_amount;
nft_affiliate_rewards_earned[token_id] += reward_amount;
total_stablecoin_distributed += reward_amount;
// Emit events
emit AffiliateRewardEvent(
token_id,
reward_amount,
owner,
block.timestamp
);
return get_nft_reference[token_id];
}
function _SetReferences(uint256 i, uint256 tokenID, uint256 ref) private {
if (i == 0) {
get_first_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_first_level_references[ref].push(tokenID);
return;
}
if (i == 1) {
get_second_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_second_level_references[ref].push(tokenID);
return;
}
if (i == 2) {
get_third_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_third_level_references[ref].push(tokenID);
return;
}
if (i == 3) {
get_four_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_four_level_references[ref].push(tokenID);
return;
}
if (i == 4) {
get_five_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_five_level_references[ref].push(tokenID);
return;
}
if (i == 5) {
get_six_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_six_level_references[ref].push(tokenID);
return;
}
if (i == 6) {
get_seven_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_seven_level_references[ref].push(tokenID);
return;
}
if (i == 7) {
get_eight_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_eight_level_references[ref].push(tokenID);
return;
}
if (i == 8) {
get_nine_level_amount_reference[ref]++;
get_total_amount_references[ref]++;
get_nine_level_references[ref].push(tokenID);
return;
}
}
function _RecoverNFT(
uint256 nftID,
address contract_migration,
uint256 month
) private {
SinergyApril ContractMigration = SinergyApril(contract_migration);
SinergyNovember ContractMigrationNovember = SinergyNovember(
contract_migration
);
// 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);
if (month == 4) {
nft_affiliate_rewards_earned[nftID] += ContractMigration
.nft_affiliate_rewards_earned(nftID);
} else if (month == 11) {
nft_affiliate_rewards_earned[nftID] += ContractMigrationNovember
.get_nft_rewards_claimed(nftID);
}
}
// 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 MigrationApril {
// Constants
uint256 public constant AMOUNT_LIMIT_TO_MIGRATE = 21;
// Contracts
SinergyMigration ContractMigration =
SinergyMigration(0xEa063b5A744616a161272a013a626A1cBD80Ee1B);
SinergyMigration Contract =
SinergyMigration(0xaeFDeD1Efb9f370F3663493755a1Da0A4E6F17E6);
// ERC20
ERC20 public ABLE = ERC20(0x0b85cCA1814eE40C6E83E3591F3819eC7e87d0A5);
// 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 {}
// Recover by level
function recoverFirstLevelReferences(uint256 nftID) public {}
function recoverSecondLevelReferences(uint256 nftID) public {}
function recoverThirdLevelReferences(uint256 nftID) public {}
function recoverFourLevelReferences(uint256 nftID) public {}
function recoverFiveLevelReferences(uint256 nftID) public {}
function recoverSixLevelReferences(uint256 nftID) public {}
function recoverSevenLevelReferences(uint256 nftID) public {}
function recoverEightLevelReferences(uint256 nftID) public {}
function recoverNineLevelReferences(uint256 nftID) public {}
// 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 {}
function set_able(ERC20 _able) public {
if (msg.sender != developmentWallet) return;
ABLE = ERC20(_able);
}
}
contract Migration is Router {
// Constants
uint256 public constant AMOUNT_LIMIT_TO_MIGRATE = 21;
// 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;
mapping(address => address) public migration_contract_of;
uint256 public starting_nft_id;
uint256[] public recovered_nfts;
uint256 public recovered_nfts_amount;
constructor() {
isRecover[Wallets.development_wallet()] = true;
}
// Main recover
function Migrate() public {
address community_wallet = Wallets.community_wallet();
address development_wallet = Wallets.development_wallet();
// Add msg.sender == development_wallet to migrate the community_wallet faster
require(
!isRecover[msg.sender] || msg.sender == development_wallet,
"Your wallet is recover."
);
if (
(msg.sender == community_wallet ||
msg.sender == development_wallet) &&
!isRecover[community_wallet]
) {
SinergyBronze.CreateGenesisNfts();
isRecover[community_wallet] = true;
HandleRecoverNftsAmountForAdmin();
return;
}
if (msg.sender == development_wallet) return;
if (AprilMigrationSinergy.isRecover(msg.sender)) {
// Migrar del ultimo contrato
_MigrateApril(AprilSinergyBronzeContract, msg.sender);
migration_contract_of[msg.sender] = address(
AprilSinergyBronzeContract
);
} else {
// Migrar del primer contrato
_MigrateNovember(NovemberSinergyBronzeContract, msg.sender);
migration_contract_of[msg.sender] = address(
NovemberSinergyBronzeContract
);
}
}
// Recover by level
function RecoverFirstLevelReferences(uint256 nftID) public {
require(
msg.sender == SinergyBronze.ownerOf(nftID) &&
!first_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_first_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
first_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverFirstLevel(
nftID,
first_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!second_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_second_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
second_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverSecondLevel(
nftID,
second_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!third_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_third_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
third_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverThirdLevel(
nftID,
third_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!four_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_four_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
four_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverFourLevel(
nftID,
four_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!five_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_five_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
five_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverFiveLevel(
nftID,
five_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!six_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_six_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
six_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverSixLevel(
nftID,
six_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!seven_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_seven_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
seven_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverSevenLevel(
nftID,
seven_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!eight_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_eight_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
eight_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverEightLevel(
nftID,
eight_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
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 == SinergyBronze.ownerOf(nftID) &&
!nine_level_references_recover[nftID]
);
SinergyMigration ContractMigration = SinergyMigration(
migration_contract_of[msg.sender]
);
uint256 migrated;
uint256 amount = ContractMigration.get_nine_level_amount_reference(
nftID
);
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE &&
nine_level_references_recover_amount[nftID] < amount
) {
SinergyBronze.HandlerRecoverNineLevel(
nftID,
nine_level_references_recover_amount[nftID],
migration_contract_of[msg.sender]
);
migrated++;
nine_level_references_recover_amount[nftID]++;
}
if (nine_level_references_recover_amount[nftID] == amount) {
nine_level_references_recover[nftID] = true;
}
}
// Helpers
function HandleRecoverNftsAmountForAdmin() private {
for (uint8 i = 0; i < 9; i++) {
recovered_nfts.push(i);
recovered_nfts_amount++;
}
}
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Private Functions
function _MigrateApril(
SinergyApril ContractMigration,
address wallet
) private {
uint256 affiliate_rewards;
uint256 amount = ContractMigration.balanceOf(wallet);
uint256 migrated;
uint256 nftID;
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE && nfts_migrated[wallet] < amount
) {
nftID = ContractMigration.get_my_nfts(
wallet,
nfts_migrated[wallet]
);
recovered_nfts.push(nftID);
SinergyBronze.HandleRecover(
wallet,
nftID,
address(ContractMigration),
4
);
nftRecover[nftID] = true;
recovered_nfts_amount++;
// nft_affiliate_rewards_earned[nftID] += ContractMigration.nft_affiliate_rewards_earned(nftID);
nfts_migrated[wallet]++;
migrated++;
}
if (nfts_migrated[wallet] == amount) {
Able.transfer(wallet, affiliate_rewards);
isRecover[wallet] = true;
}
}
function _MigrateNovember(
SinergyNovember ContractMigration,
address wallet
) private {
uint256 affiliate_rewards;
uint256 amount = ContractMigration.balanceOf(wallet);
uint256 migrated;
uint256 nftID;
while (
migrated < AMOUNT_LIMIT_TO_MIGRATE && nfts_migrated[wallet] < amount
) {
nftID = ContractMigration.get_my_nfts(
wallet,
nfts_migrated[wallet]
);
recovered_nfts.push(nftID);
SinergyBronze.HandleRecover(
wallet,
nftID,
address(ContractMigration),
11
);
nftRecover[nftID] = true;
recovered_nfts_amount++;
affiliate_rewards += ContractMigration.get_nft_balance_to_claim(
nftID
);
nfts_migrated[wallet]++;
migrated++;
}
if (nfts_migrated[wallet] == amount) {
Able.transfer(wallet, affiliate_rewards);
isRecover[wallet] = true;
}
}
}
contract MigrationSale is Router {
bool public is_migrated;
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Before to call this function, we have to send enought Able to the
// new Sinergy Sale Contract.
function Migrate() public {
require(IsOwner(msg.sender), "Only owners can migrate the Sale List.");
require(!is_migrated, "The Sale List are already migrated.");
_MigrateSellList();
_MigrateDrivenList();
is_migrated = true;
}
function _MigrateSellList() private {
uint256 amount = AprilSinergySaleContract.get_sell_list_length();
for (uint256 i = 0; i < amount; i++) {
uint256 token_id = AprilSinergySaleContract.sell_list(i);
uint256 selling_amount = AprilSinergySaleContract.selling_amount_of(
token_id
);
AbleSale.Migrate_Send_Sell_List(token_id, selling_amount);
}
}
function _MigrateDrivenList() private {
uint256 amount = AprilSinergySaleContract.get_driven_list_length();
for (uint256 i = 0; i < amount; i++) {
uint256 token_id = AprilSinergySaleContract.driven_list(i);
uint256 selling_amount = AprilSinergySaleContract.selling_amount_of(
token_id
);
AbleSale.Migrate_Send_Driven_List(token_id, selling_amount);
}
}
}
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 pure returns (bool) {
// This is a Random code just to make compile the interface of the Migration Contract without Warnings.
if (wallet == address(0)) return false;
if (passive) return false;
return true;
}
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.amount_of_wins_able_reward_of(wallet);
}
function get_total_amount(bool passive) private view returns (uint256) {
if (passive) {
return SinergyContract.nfts_qualified();
}
return ABLE.able_rewards_claimed();
}
}
contract BaseReward is Router {
// Token
ERC20 public Token = ERC20(0xB856De7DAFf71A0d7eAFD4CC22A7db6F762179de);
uint256 public POTENCIAL = 9;
// Attributes
uint256 public total_distributed;
mapping(uint256 => uint256) public raised_amount;
mapping(uint256 => uint256) public claimed_amount;
mapping(address => mapping(uint256 => bool)) public has_claimed;
mapping(address => uint256) public amount_earned;
mapping(address => mapping(uint256 => bool))
public is_participate_on_this_reward;
mapping(uint256 => uint256) public total_wallets_on_this_reward;
mapping(uint256 => uint256) public total_amount_on_this_reward;
mapping(address => mapping(uint256 => uint256))
public user_amount_on_this_reward;
// Events
event RewardClaimed(uint256 amount, address indexed wallet);
constructor(address _token) {
Token = ERC20(_token);
}
// Public Functions
function ViewAmountToClaim(address wallet) public view returns (uint256) {
uint256 cycle = Cycle.cycle();
if (has_claimed[wallet][cycle]) return 0;
uint256 user_amount = GetUserAmount(wallet);
uint256 total_amount = GetTotalAmount();
uint256 amount_to_claim = (user_amount * raised_amount[cycle - 1]) /
total_amount;
if (
amount_to_claim >
(raised_amount[cycle - 1] - claimed_amount[cycle - 1])
) {
return (raised_amount[cycle - 1] - claimed_amount[cycle - 1]) / 9; // Entregamos 1/9 del bote a ese usuario.
}
return amount_to_claim;
}
function CanUpdate(address wallet) public view returns (bool) {
if (wallet == address(Cycle)) return true;
return false;
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Set Functions
function SetPotencial(uint256 value) public {
require(
IsOwner(msg.sender),
"You are not qualified to set the Potencial"
);
POTENCIAL = value;
}
// Virtual Functions
function Update() public virtual {
require(
CanUpdate(msg.sender),
"You are not qualified to update the Reward."
);
raised_amount[Cycle.cycle() - 1] = Token.balanceOf(address(this));
}
function Claim() public virtual {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
require(
CanClaim(msg.sender),
"You are not qualified to claim the Reward."
);
require(
is_participate_on_this_reward[msg.sender][cycle - 1],
"You dont participate on this reward."
);
uint256 amount = ViewAmountToClaim(msg.sender);
Token.transfer(msg.sender, amount);
has_claimed[msg.sender][cycle] = true;
amount_earned[msg.sender] += amount;
Able.DecreasePoints(msg.sender, amount / POTENCIAL);
Qualification.IncreaseStablecoinEarnedOnAbleReward(msg.sender, amount);
emit RewardClaimed(amount, msg.sender);
}
function CanClaim(address wallet) public view virtual returns (bool) {
uint256 cycle = Cycle.cycle();
return (!has_claimed[wallet][cycle] &&
Qualification.IsQualified(wallet) &&
!Able.increase_points_in_cycle(wallet, cycle));
}
function CanIncreaseRewards(
address wallet
) public view virtual returns (bool) {
if (wallet == address(Able) || IsOwner(wallet)) return true;
return false;
}
function GetUserAmount(address wallet) public view returns (uint256) {
return user_amount_on_this_reward[wallet][Cycle.cycle() - 1];
}
function GetTotalAmount() public view returns (uint256) {
// return Able.qualified_points_by_cycle(Cycle.cycle() - 1);
return total_amount_on_this_reward[Cycle.cycle() - 1];
}
function SetToken(address token) public {
require(
IsOwner(msg.sender),
"Only owner can modify the token of this reward."
);
Token = ERC20(token);
}
function SetIsParticipateOnThisReward(address wallet) public virtual {
uint256 cycle = Cycle.cycle();
if (!is_participate_on_this_reward[wallet][cycle] && CanClaim(wallet)) {
is_participate_on_this_reward[wallet][cycle] = true;
total_wallets_on_this_reward[cycle]++;
total_amount_on_this_reward[cycle] += Able.points_of(wallet);
user_amount_on_this_reward[wallet][cycle] = Able.points_of(wallet);
}
}
function WithdrawAllFunds() public {
require(IsOwner(msg.sender), "Only owners can call to this function.");
Token.transfer(msg.sender, Token.balanceOf(address(this)));
}
}
contract ValueReward is BaseReward {
constructor(address _token) BaseReward(_token) {}
// Override Functions
function Claim() public virtual override {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
require(
CanClaim(msg.sender),
"You are not qualified to claim the Reward."
);
require(
is_participate_on_this_reward[msg.sender][cycle - 1],
"You dont participate on this reward."
);
uint256 amount = ViewAmountToClaim(msg.sender);
Token.transfer(msg.sender, amount);
has_claimed[msg.sender][cycle] = true;
amount_earned[msg.sender] += amount;
emit RewardClaimed(amount, msg.sender);
}
function CanClaim(
address wallet
) public view virtual override returns (bool) {
uint256 cycle = Cycle.cycle();
return (!has_claimed[wallet][cycle] &&
Qualification.IsQualified(wallet));
}
function CanIncreaseRewards(
address wallet
) public view override returns (bool) {
if (wallet == address(SinergyBronze) || wallet == address(AbleSale))
return true;
return false;
}
// Get Functions
// function GetUserAmount(
// address wallet
// ) public view override returns (uint256) {
// return SinergyBronze.balanceOf(wallet);
// }
// function GetTotalAmount() public view override returns (uint256) {
// return SinergyBronze.nfts_qualified_by_cycle(Cycle.cycle() - 1);
// }
function SetIsParticipateOnThisReward(address wallet) public override {
uint256 cycle = Cycle.cycle();
if (!is_participate_on_this_reward[wallet][cycle] && CanClaim(wallet)) {
is_participate_on_this_reward[wallet][cycle] = true;
total_wallets_on_this_reward[cycle]++;
total_amount_on_this_reward[cycle] += SinergyBronze.balanceOf(
wallet
);
user_amount_on_this_reward[wallet][cycle] = SinergyBronze.balanceOf(
wallet
);
}
}
}
contract ConstancyReward is BaseReward {
// Attributes
uint256 public AMOUNT_USERS_NEED_TO_CLAIM = 21;
constructor(address _token) BaseReward(_token) {}
// Public Functions
function SetAmoutUsersNeedToClaim(uint256 amount) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the amount of users needeed to claim."
);
AMOUNT_USERS_NEED_TO_CLAIM = amount;
}
// Override Functions
function Claim() public virtual override {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
require(
CanClaim(msg.sender),
"You are not qualified to claim the Reward."
);
require(
is_participate_on_this_reward[msg.sender][cycle - 1],
"You dont participate on this reward."
);
uint256 amount = ViewAmountToClaim(msg.sender);
Token.transfer(msg.sender, amount);
has_claimed[msg.sender][cycle] = true;
amount_earned[msg.sender] += amount;
emit RewardClaimed(amount, msg.sender);
}
function CanClaim(
address wallet
) public view virtual override returns (bool) {
uint256 cycle = Cycle.cycle();
return (!has_claimed[wallet][cycle] &&
Qualification.IsQualified(wallet) &&
Able.able_rewards_claimed() >= AMOUNT_USERS_NEED_TO_CLAIM &&
Able.amount_of_wins_able_reward_of(wallet) > 0);
}
// Private Functions
function CanIncreaseRewards(
address wallet
) public view virtual override returns (bool) {
if (wallet == address(SinergyBronze) || wallet == address(AbleSale))
return true;
return false;
}
// Get Functions
// function GetUserAmount(
// address wallet
// ) public view virtual override returns (uint256) {
// return Able.amount_of_wins_able_reward_of(wallet);
// }
// function GetTotalAmount() public view virtual override returns (uint256) {
// return Able.qualified_able_rewards_claimed();
// }
function SetIsParticipateOnThisReward(address wallet) public override {
uint256 cycle = Cycle.cycle();
if (!is_participate_on_this_reward[wallet][cycle] && CanClaim(wallet)) {
is_participate_on_this_reward[wallet][cycle] = true;
total_wallets_on_this_reward[cycle]++;
total_amount_on_this_reward[cycle] += Able
.amount_of_wins_able_reward_of(wallet);
user_amount_on_this_reward[wallet][cycle] = Able
.amount_of_wins_able_reward_of(wallet);
}
}
}
contract ConfidenceReward is BaseReward {
// Attributes
uint256 public MIN_AMOUNT_OF_ABLE = 3690 ether;
constructor(address _token) BaseReward(_token) {}
// Override Functions
function Claim() public virtual override {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
require(
CanClaim(msg.sender),
"You are not qualified to claim the Reward."
);
require(
is_participate_on_this_reward[msg.sender][cycle - 1],
"You dont participate on this reward."
);
uint256 amount = ViewAmountToClaim(msg.sender);
Token.transfer(msg.sender, amount);
has_claimed[msg.sender][cycle] = true;
amount_earned[msg.sender] += amount;
emit RewardClaimed(amount, msg.sender);
}
function CanClaim(
address wallet
) public view virtual override returns (bool) {
uint256 cycle = Cycle.cycle();
return (Qualification.IsQualified(wallet) &&
Able.balanceOf(wallet) >= MIN_AMOUNT_OF_ABLE &&
!Able.has_transfer(wallet, cycle - 1));
}
// Set Functions
function SetMinAmountOfAble(uint256 value) public {
require(IsOwner(msg.sender), "Only owners can call to this function.");
MIN_AMOUNT_OF_ABLE = value;
}
// Get Functions
// function GetUserAmount(
// address wallet
// ) public view virtual override returns (uint256) {
// uint256 amount = Able.balanceOf(wallet);
// if (amount < MIN_AMOUNT_OF_ABLE) return 0;
// return amount;
// }
// function GetTotalAmount() public view virtual override returns (uint256) {
// return Qualification.amount_of_staking_wallets();
// }
// Private Functions
function CanIncreaseRewards(
address wallet
) public view virtual override returns (bool) {
if (wallet == address(AbleSale) || wallet == address(SinergyBronze))
return true;
return false;
}
function SetIsParticipateOnThisReward(address wallet) public override {
uint256 cycle = Cycle.cycle();
if (!is_participate_on_this_reward[wallet][cycle] && CanClaim(wallet)) {
is_participate_on_this_reward[wallet][cycle] = true;
total_wallets_on_this_reward[cycle]++;
total_amount_on_this_reward[cycle]++;
user_amount_on_this_reward[wallet][cycle] = 1;
}
}
}
contract Clock is Router {
uint256 public TIME_OF_CYCLE = 1 days;
uint256 public cycle = 1;
uint256 public timestamp_to_next_cycle;
constructor() {
timestamp_to_next_cycle = block.timestamp + TIME_OF_CYCLE;
}
event CycleChange(uint256 indexed date, uint256 indexed cycle);
function Update() public {
if (block.timestamp > timestamp_to_next_cycle) {
timestamp_to_next_cycle = block.timestamp + TIME_OF_CYCLE;
Able.CloseCycle();
SinergyBronze.CloseCycle();
cycle++;
UpdateRewards();
emit CycleChange(block.timestamp, cycle);
}
}
function UpdateRewards() public {
StablecoinBaseReward.Update();
StablecoinConfidenceReward.Update();
StablecoinConstancyReward.Update();
StablecoinValueReward.Update();
AbleConfidenceReward.Update();
AbleConstancyReward.Update();
AbleValueReward.Update();
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Set Functions
function SetTimeOfCycle(uint256 new_time) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the time of the cycle."
);
TIME_OF_CYCLE = new_time;
}
}
contract Test is Router {
// Attributes
bool public play_list;
uint256 public play_list_first_video_id;
uint256 public play_list_last_video_id;
uint256 public cycle_start_play_list;
uint256 public cycle_close_play_list;
uint256 public id;
mapping(uint256 => string) public youtube_id;
mapping(uint256 => string) public first_question;
mapping(uint256 => string) public second_question;
mapping(uint256 => string) public third_question;
mapping(uint256 => string) public first_real_answer;
mapping(uint256 => string) public second_real_answer;
mapping(uint256 => string) public third_real_answer;
mapping(uint256 => string) public first_fake_answer_1;
mapping(uint256 => string) public second_fake_answer_1;
mapping(uint256 => string) public third_fake_answer_1;
mapping(uint256 => string) public first_fake_answer_2;
mapping(uint256 => string) public second_fake_answer_2;
mapping(uint256 => string) public third_fake_answer_2;
mapping(address => mapping(uint256 => bool)) public answer_of;
// Events
event Answer(uint256 indexed date, bool res, address indexed wallet);
// Public Functions
function UploadVideoAndFirstQuestion(
string memory _youtube_id,
string memory _first_question,
string memory _first_real_answer,
string memory _first_fake_answer_1,
string memory _first_fake_answer_2
) public {
require(
IsOwner(msg.sender),
"You are not qualified to upload a video."
);
youtube_id[id] = _youtube_id;
first_question[id] = _first_question;
first_real_answer[id] = _first_real_answer;
first_fake_answer_1[id] = _first_fake_answer_1;
first_fake_answer_2[id] = _first_fake_answer_2;
id++;
}
function UploadSecondQuestion(
string memory _second_question,
string memory _second_real_answer,
string memory _second_fake_answer_1,
string memory _second_fake_answer_2
) public {
require(
IsOwner(msg.sender),
"You are not qualified to upload a video."
);
second_question[id - 1] = _second_question;
second_real_answer[id - 1] = _second_real_answer;
second_fake_answer_1[id - 1] = _second_fake_answer_1;
second_fake_answer_2[id - 1] = _second_fake_answer_2;
}
function UploadThirdQuestion(
string memory _third_question,
string memory _third_real_answer,
string memory _third_fake_answer_1,
string memory _third_fake_answer_2
) public {
require(
IsOwner(msg.sender),
"You are not qualified to upload a video."
);
third_question[id - 1] = _third_question;
third_real_answer[id - 1] = _third_real_answer;
third_fake_answer_1[id - 1] = _third_fake_answer_1;
third_fake_answer_2[id - 1] = _third_fake_answer_2;
}
function AnswerVideo(
string memory answer_1,
string memory answer_2,
string memory answer_3,
uint256 _id
) public {
uint256 cycle = Cycle.cycle();
require(
Qualification.is_updated(msg.sender, cycle),
"You have to update first."
);
bool first = (keccak256(abi.encodePacked((answer_1))) ==
keccak256(abi.encodePacked((first_real_answer[_id]))));
bool second = (keccak256(abi.encodePacked((answer_2))) ==
keccak256(abi.encodePacked((second_real_answer[_id]))));
bool third = (keccak256(abi.encodePacked((answer_3))) ==
keccak256(abi.encodePacked((third_real_answer[_id]))));
answer_of[msg.sender][cycle] = first && second && third;
Qualification.Update(msg.sender);
emit Answer(block.timestamp, first && second && third, msg.sender);
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Set functions
function UsePlayList() public {
require(
IsOwner(msg.sender),
"You are not qualified to change the sort of the videos."
);
play_list = !play_list;
cycle_start_play_list = Cycle.cycle();
cycle_close_play_list =
cycle_start_play_list +
(play_list_last_video_id - play_list_first_video_id);
}
function SetFirstVideoOfPlayList(uint256 _id) public {
require(
IsOwner(msg.sender),
"Only owner can set the first video of the play list"
);
play_list_first_video_id = _id;
}
function SetLastVideoOfPlayList(uint256 _id) public {
require(
IsOwner(msg.sender),
"Only owner can set the last video of the play list"
);
play_list_last_video_id = _id;
}
}
// Modificado
contract User is Router {
uint256 public MIN_POINTS_TO_QUALIFY = 3 ether;
uint256 public PERCENT_TO_INCREASE = 10090;
uint256 public AMOUNT_TO_DIVIDE = 10000;
mapping(address => mapping(uint256 => uint256)) public points_per_cycle;
mapping(address => uint256) public stablecoin_earned_on_able_reward;
mapping(address => uint256) public cycleToCheck;
// User
mapping(address => mapping(uint256 => bool)) public is_updated;
// 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;
// Qualification
mapping(address => mapping(uint256 => bool)) public qualified_sinergy; // At least 1 NFT of Sinergy
mapping(address => mapping(uint256 => bool)) public qualified_able; // More Able than Points
mapping(address => mapping(uint256 => bool)) public qualified_usdc; // More USDC than Points
mapping(address => mapping(uint256 => bool)) public qualified_usdt; // More USDT than Points
mapping(address => mapping(uint256 => bool)) public qualified_min_points; // More Points than 3
mapping(address => mapping(uint256 => bool))
public qualified_increase_points; // Increase Points by cycle
mapping(address => mapping(uint256 => bool)) public qualified_video; // Answer correctly the video
mapping(address => mapping(uint256 => bool)) public qualified_history; // History of Qualification cycle by cycle
// Confidence Reward Data
mapping(address => bool) public is_staking;
uint256 public amount_of_staking_wallets;
// Events
event CloseCycle(
address indexed wallet,
uint256 cycle,
bool qualifiedSinergy,
bool qualifiedUSDT,
bool qualifiedUSDC,
bool qualifiedSaver,
bool qualifiedBDD,
bool qualifiedDonatedPerDay,
bool qualifiedVideo
);
event UpdateEvent(uint256 indexed date, address indexed wallet);
constructor() {}
function IsQualified(address wallet) public view returns (bool) {
if (IsOwner(wallet)) return true;
uint256 cycle = Cycle.cycle();
return (qualified_sinergy[wallet][cycle - 1] &&
qualified_able[wallet][cycle - 1] &&
qualified_usdc[wallet][cycle - 1] &&
qualified_usdt[wallet][cycle - 1] &&
qualified_min_points[wallet][cycle - 1] &&
qualified_increase_points[wallet][cycle - 1] &&
qualified_video[wallet][cycle - 1]);
}
function CheckDay(address wallet) public {
uint256 cycle = Cycle.cycle();
if (cycle >= cycleToCheck[wallet]) {
cycleToCheck[wallet] = cycle + 1;
_SetSavingsRecord(wallet, cycle);
_CloseCycle(wallet, cycle - 1);
}
}
function IsQualifiedBySinergy(address wallet) public view returns (bool) {
bool bronze = false;
bool silver = false;
bool gold = false;
if (address(SinergyBronze) != address(0)) {
bronze = SinergyBronze.balanceOf(wallet) > 0;
}
if (address(SinergySilver) != address(0)) {
silver = SinergySilver.balanceOf(wallet) > 0;
}
if (address(SinergyGold) != address(0)) {
gold = SinergyGold.balanceOf(wallet) > 0;
}
return (bronze || silver || gold);
}
function IsQualifiedByAble(address wallet) public view returns (bool) {
return (Able.balanceOf(wallet) > Able.points_of(wallet));
}
function IsQualifiedByUSDC(address wallet) public view returns (bool) {
return (GetBalanceOfUSDC(wallet) > Able.points_of(wallet));
}
function IsQualifiedByUSDT(address wallet) public view returns (bool) {
return (GetBalanceOfUSDT(wallet) > Able.points_of(wallet));
}
function IsQualifiedByPoints(address wallet) public view returns (bool) {
return (Able.points_of(wallet) > MIN_POINTS_TO_QUALIFY);
}
function IsQualifiedByIncreasePoints(
address wallet
) public view returns (bool) {
uint256 points = Able.points_of(wallet);
if (points == 0) return false;
uint256 cycle = Cycle.cycle();
if (cycle > 1) {
return (points_per_cycle[wallet][cycle - 1] >=
GetPointsToIncrease(points_per_cycle[wallet][cycle - 2]));
}
return false;
}
function IsQualifiedByVideo(address wallet) public view returns (bool) {
return VideoTest.answer_of(wallet, Cycle.cycle() - 1);
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Update Functions
function Update(address wallet) public {
Cycle.Update();
Able.UpdateQualifiedPoints(wallet);
CheckDay(wallet);
Able.CheckAbleReward(wallet);
UpdateSinergy(wallet);
UpdateRewards(wallet);
is_updated[wallet][Cycle.cycle()] = true;
emit UpdateEvent(block.timestamp, wallet);
}
function UpdateSinergy(address wallet) public {
if (address(SinergyBronze) != address(0)) {
SinergyBronze.UpdateQualifiedNfts(wallet);
}
if (address(SinergySilver) != address(0)) {
SinergySilver.UpdateQualifiedNfts(wallet);
}
if (address(SinergyGold) != address(0)) {
SinergyGold.UpdateQualifiedNfts(wallet);
}
}
function UpdateRewards(address wallet) public {
StablecoinBaseReward.SetIsParticipateOnThisReward(wallet);
StablecoinValueReward.SetIsParticipateOnThisReward(wallet);
StablecoinConstancyReward.SetIsParticipateOnThisReward(wallet);
StablecoinConfidenceReward.SetIsParticipateOnThisReward(wallet);
AbleValueReward.SetIsParticipateOnThisReward(wallet);
AbleConstancyReward.SetIsParticipateOnThisReward(wallet);
AbleConfidenceReward.SetIsParticipateOnThisReward(wallet);
}
// Set functions
function ResetStablecoinEarnedOnAbleReward(address wallet) public {
require(
msg.sender == address(Able),
"Only Able can reset stablecoin earned on Able reward."
);
stablecoin_earned_on_able_reward[wallet] = 0;
}
function IncreaseStablecoinEarnedOnAbleReward(
address wallet,
uint256 amount
) public {
require(
msg.sender == address(StablecoinBaseReward),
"Only Stablecoin Base Reward contract can increase stablecoin earned on Able reward."
);
stablecoin_earned_on_able_reward[wallet] += amount;
}
function SetPercentToIncrease(uint256 amount) public {
require(
IsOwner(msg.sender),
"You cant modify the percent of points to increase."
);
PERCENT_TO_INCREASE = amount;
}
function SetAmountToDivide(uint256 amount) public {
require(IsOwner(msg.sender), "You cant modify the amount to divide.");
AMOUNT_TO_DIVIDE = amount;
}
function SetMinAmountOfPointsToQualify(uint256 amount) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the minimum amount of points to qualify."
);
MIN_POINTS_TO_QUALIFY = amount;
}
// Get functions
function GetBalanceOfUSDC(address wallet) public view returns (uint256) {
uint256 USDC_DECIMALS = Wallets.USDC_DECIMALS();
uint256 balance = USDC.balanceOf(wallet);
if (USDC_DECIMALS == 18) {
return balance;
}
return balance * 10 ** (18 - USDC_DECIMALS);
}
function GetBalanceOfUSDT(address wallet) public view returns (uint256) {
uint256 USDT_DECIMALS = Wallets.USDT_DECIMALS();
uint256 balance = USDT.balanceOf(wallet);
if (USDT_DECIMALS == 18) {
return balance;
}
return balance * 10 ** (18 - USDT_DECIMALS);
}
function GetPointsToIncrease(uint256 amount) public view returns (uint256) {
return (amount * PERCENT_TO_INCREASE) / AMOUNT_TO_DIVIDE;
}
// Private functions
function _SetSavingsRecord(address wallet, uint256 cycle) private {
lastAmountUSDC[wallet] = GetBalanceOfUSDC(wallet);
lastAmountUSDT[wallet] = GetBalanceOfUSDT(wallet);
usdcRecord[wallet][cycle] = lastAmountUSDC[wallet];
usdtRecord[wallet][cycle] = lastAmountUSDT[wallet];
}
function _CloseCycle(address wallet, uint256 cycle) private {
points_per_cycle[wallet][cycle] = Able.points_of(wallet);
qualified_sinergy[wallet][cycle] = IsQualifiedBySinergy(wallet);
qualified_able[wallet][cycle] = IsQualifiedByAble(wallet);
qualified_usdt[wallet][cycle] = IsQualifiedByUSDT(wallet);
qualified_usdc[wallet][cycle] = IsQualifiedByUSDC(wallet);
qualified_min_points[wallet][cycle] = IsQualifiedByPoints(wallet);
qualified_increase_points[wallet][cycle] = IsQualifiedByIncreasePoints(
wallet
);
qualified_video[wallet][cycle] = IsQualifiedByVideo(wallet);
qualified_history[wallet][cycle] = IsQualified(wallet);
if (!qualified_history[wallet][cycle]) {
_ResetStablecoinEarnedOnAbleReward(wallet);
}
uint256 able_amount = Able.balanceOf(wallet);
if (is_staking[wallet]) {
is_staking[wallet] = false;
amount_of_staking_wallets--;
}
if (able_amount >= StablecoinConfidenceReward.MIN_AMOUNT_OF_ABLE()) {
is_staking[wallet] = true;
amount_of_staking_wallets++;
}
emit CloseCycle(
wallet,
cycle,
qualified_sinergy[wallet][cycle],
qualified_usdt[wallet][cycle],
qualified_usdc[wallet][cycle],
qualified_able[wallet][cycle],
qualified_min_points[wallet][cycle],
qualified_increase_points[wallet][cycle],
qualified_video[wallet][cycle]
);
}
function _ResetStablecoinEarnedOnAbleReward(address wallet) private {
stablecoin_earned_on_able_reward[wallet] = 0;
}
}
contract ERC20Migration 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 = 1 days;
// 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(0x818ec0A7Fe18Ff94269904fCED6AE3DaE6d6dC0b); // USDC (6 decimals)
uint256 public USDC_DECIMALS = 6;
ERC20 public USDT = ERC20(0xeFAeeE334F0Fd1712f9a8cc375f427D9Cdd40d73); // USDT (6 decimals)
uint256 public USDT_DECIMALS = 6;
ERC20 public STABLECOIN = ERC20(0x765277EebeCA2e31912C9946eAe1021199B39C61); // STABLECOIN (18 decimals)
uint256 public BUSD_DECIMALS = 18;
// Contract Migration
ERC20Migration public AbleMigration =
ERC20Migration(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_ABLE_REWARD = 21;
// 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(STABLECOIN.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"
);
STABLECOIN = 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_ABLE_REWARD) return false;
for (uint256 i = cycle - CYCLES_FOR_ABLE_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 STABLECOIN.balanceOf(wallet);
}
return STABLECOIN.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(
STABLECOIN.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_ABLE_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 {}
}
// This is the main contract here!
contract ERC20 is Context, IERC20, IERC20Metadata, Router {
// Migration Saver
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;
// Able
uint256 public initial_supply = 369000000 * 10 ** 18;
uint256 public development_supply = 1845000 * 10 ** 18;
mapping(address => mapping(uint256 => bool)) public has_transfer;
// Holders
uint256 public total_holders;
uint256 public qualified_holders;
mapping(address => bool) public is_holder;
mapping(address => string) public personal_purpose;
mapping(address => string) public community_purpose;
// Saver Reward
uint256 public POTENCIAL_ABLE = 1;
uint256 public CYCLES_FOR_ABLE_REWARD = 21;
mapping(address => bool) public is_listed_to_claim_able;
mapping(address => uint256) public amount_of_wins_able_reward_of;
mapping(address => bool) public won_able_reward;
mapping(address => uint256) public total_able_earned_of;
mapping(address => uint256) public cycle_to_able_reward;
uint256 public able_rewards_claimed;
uint256 public qualified_able_rewards_claimed; // Cantidad de premios able de cuentas calificadas actualmente
uint256 public total_able_distributed;
address[] public wallet_winners;
// Points
uint256 public total_points;
uint256 public amount_of_wallets_with_points;
mapping(address => uint256) public points_of;
address public last_wallet_who_bought_able;
mapping(address => mapping(uint256 => bool))
public increase_points_in_cycle;
// Qualified Points
mapping(uint256 => uint256) public qualified_points_by_cycle;
uint256 public qualified_points;
uint256 public total_qualified_wallets;
mapping(address => bool) public is_qualified;
// Informacion
string public management_info;
// Events
event ClaimAbleEvent(
uint256 indexed date,
uint256 amount,
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 Points(
address indexed wallet,
uint256 cycle,
uint256 amount,
bool increase
);
event AbleQualification(
uint256 indexed date,
address indexed wallet,
bool status
);
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
// Recover Saver
function GetAbleToRecover(
address wallet,
ERC20Migration _Able,
bool triple
) public view returns (uint256) {
uint256 default_amount = _Able.balanceOf(wallet);
if (triple) {
default_amount += TripleMigration.balanceOf(wallet);
}
return default_amount;
}
function Migrate() public {
require(!isRecover[msg.sender]);
if (AprilAbleContract.isRecover(msg.sender)) {
_MigrateAble(msg.sender, AprilAbleContract, false);
} else {
_MigrateAble(msg.sender, NovemberAbleContract, true);
}
}
// Points
function BurnPoints(uint256 amount) public {
require(
points_of[msg.sender] >= amount,
"You dont have this amount of points to burn it."
);
DecreasePoints(msg.sender, amount);
}
// Esta nueva funcion la tiene que llamar SinergySale cada vez que alguien compra ABLE
function IncreasePoints(uint256 amount_spended, address wallet) public {
require(
msg.sender == address(AbleSale),
"Only Sinergy Sale can increase points."
);
uint256 cycle = Cycle.cycle();
if (amount_spended > 0 && points_of[wallet] == 0) {
amount_of_wallets_with_points++;
}
if (is_qualified[wallet]) {
qualified_points -= points_of[wallet];
is_qualified[wallet] = false;
total_qualified_wallets--;
qualified_holders--;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed -= amount_of_wins_able_reward_of[
wallet
];
}
}
points_of[wallet] += amount_spended;
total_points += amount_spended;
if (Qualification.IsQualified(wallet)) {
qualified_points += points_of[wallet];
is_qualified[wallet] = true;
total_qualified_wallets++;
qualified_holders++;
last_wallet_who_bought_able = msg.sender;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed += amount_of_wins_able_reward_of[
wallet
];
}
}
increase_points_in_cycle[wallet][cycle] = true;
// Emit Event
emit Points(wallet, cycle, amount_spended, true);
}
function DecreasePoints(address wallet, uint256 amount) public {
require(
_CanDecreasePoints(msg.sender, wallet),
"You are not qualified to try to Decrease Points."
);
require(
amount <= points_of[wallet],
"You dont have that amount of points to decrease it."
);
bool previousStatus = is_qualified[wallet];
if (is_qualified[wallet]) {
qualified_points -= points_of[wallet];
is_qualified[wallet] = false;
total_qualified_wallets--;
qualified_holders--;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed -= amount_of_wins_able_reward_of[
wallet
];
}
}
points_of[wallet] -= amount;
total_points -= amount;
// We asked for amount != 0, because the user can reduce zero points having zero points.
if (points_of[wallet] == 0 && amount != 0) {
amount_of_wallets_with_points--;
}
if (Qualification.IsQualified(wallet)) {
qualified_points += points_of[wallet];
is_qualified[wallet] = true;
total_qualified_wallets++;
qualified_holders++;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed += amount_of_wins_able_reward_of[
wallet
];
}
}
if (previousStatus != is_qualified[wallet]) {
emit AbleQualification(block.timestamp, wallet, !previousStatus);
}
// Emit Event
emit Points(wallet, Cycle.cycle(), amount, false);
}
function CloseCycle() public {
require(
msg.sender == address(Cycle),
"Only the Clock can Set Qualified Points"
);
qualified_points_by_cycle[Cycle.cycle()] = qualified_points;
}
// Able Reward
function ClaimAble() public {
require(
Qualification.is_updated(msg.sender, Cycle.cycle()),
"You have to update first."
);
require(
CanClaimAble(msg.sender),
"You are not qualified to claim Able."
);
require(
cycle_to_able_reward[msg.sender] < Cycle.cycle(),
"You have to wait more cycles to claim your Able."
);
// Emit events
emit ClaimAbleEvent(block.timestamp, points_of[msg.sender], msg.sender);
_mint(msg.sender, points_of[msg.sender] * POTENCIAL_ABLE);
is_listed_to_claim_able[msg.sender] = false;
if (!won_able_reward[msg.sender]) {
address[] storage winners = wallet_winners;
winners.push(msg.sender);
wallet_winners = winners;
}
won_able_reward[msg.sender] = true;
amount_of_wins_able_reward_of[msg.sender]++;
able_rewards_claimed++;
qualified_able_rewards_claimed++;
total_able_distributed += points_of[msg.sender];
total_able_earned_of[msg.sender] += points_of[msg.sender];
Qualification.ResetStablecoinEarnedOnAbleReward(msg.sender);
}
function CanClaimAble(address wallet) public view returns (bool) {
return (Qualification.IsQualified(wallet) &&
is_listed_to_claim_able[wallet]);
}
// Update
function UpdateQualifiedPoints(address wallet) public {
bool previousStatus = is_qualified[wallet];
if (is_qualified[wallet]) {
qualified_points -= points_of[wallet];
is_qualified[wallet] = false;
total_qualified_wallets--;
qualified_holders--;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed -= amount_of_wins_able_reward_of[
wallet
];
}
}
if (Qualification.IsQualified(wallet)) {
qualified_points += points_of[wallet];
is_qualified[wallet] = true;
total_qualified_wallets++;
qualified_holders++;
if (amount_of_wins_able_reward_of[wallet] > 0) {
qualified_able_rewards_claimed += amount_of_wins_able_reward_of[
wallet
];
}
}
if (previousStatus != is_qualified[wallet]) {
emit AbleQualification(block.timestamp, wallet, !previousStatus);
}
}
function CheckAbleReward(address wallet) public {
if (
!Qualification.IsQualified(wallet) &&
is_listed_to_claim_able[wallet]
) {
is_listed_to_claim_able[wallet] = false;
emit AbleRewardQualification(block.timestamp, wallet, false);
return;
}
if (
Qualification.IsQualified(wallet) &&
!is_listed_to_claim_able[wallet]
) {
is_listed_to_claim_able[wallet] = true;
cycle_to_able_reward[wallet] =
Cycle.cycle() +
CYCLES_FOR_ABLE_REWARD;
emit AbleRewardQualification(block.timestamp, wallet, true);
return;
}
}
// Get Functions
function GetWalletWinnersLength() public view returns (uint256) {
return wallet_winners.length;
}
// Helpers
function IsOwner(address wallet) public view returns (bool) {
return Wallets.IsOwner(wallet);
}
// Set Functions
function SetPersonalPurpose(string memory _str) public {
personal_purpose[msg.sender] = _str;
}
function SetCommunityPurpose(string memory _str) public {
community_purpose[msg.sender] = _str;
}
function SetPotencialAble(uint256 potencial) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the able reward potencial."
);
POTENCIAL_ABLE = potencial;
}
function SetCyclesForAbleReward(uint256 cycles) public {
require(
IsOwner(msg.sender),
"You are not qualified to change the cycles for able reward."
);
CYCLES_FOR_ABLE_REWARD = cycles;
}
// Private Functions
function _MigrateAble(
address wallet,
ERC20Migration _Able,
bool triple
) private {
uint256 last_points_of = points_of[wallet];
// Recover Donation Balance
points_of[wallet] += _Able.donationBalance(wallet);
total_points += points_of[wallet];
// Recover Purposes
personal_purpose[wallet] = _Able.personalPurpose(wallet);
community_purpose[wallet] = _Able.communityPurpose(wallet);
// Recover SAVF (Last Saver Fast)
_mint(wallet, GetAbleToRecover(wallet, _Able, triple));
if (_Able.balanceOf(wallet) > 0 && !is_holder[wallet]) {
total_holders++;
is_holder[wallet] = true;
}
bool qualification_is_qualified = Qualification.IsQualified(wallet);
// Recover Qualified Donation Balance
if (qualification_is_qualified && !is_qualified[wallet]) {
qualified_points += points_of[wallet];
is_qualified[wallet] = true;
total_qualified_wallets++;
qualified_holders++;
} else if (qualification_is_qualified && is_qualified[wallet]) {
qualified_points += points_of[wallet] - last_points_of;
}
if (points_of[wallet] > 0 && last_points_of == 0) {
amount_of_wallets_with_points++;
}
isRecover[wallet] = true;
}
function _CanDecreasePoints(
address wallet,
address owner
) private view returns (bool) {
if (
wallet == address(this) ||
wallet == address(Qualification) ||
wallet == address(StablecoinBaseReward) ||
wallet == owner
) return true;
return false;
}
// 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 (!is_holder[to] && amount > 0) {
total_holders++;
is_holder[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) {
total_holders--;
is_holder[from] = false;
}
if (to != address(AbleSale)) {
has_transfer[from][Cycle.cycle()] = true;
}
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 AbleSaver is ERC20 {
constructor() ERC20("ABLE SAVER", "ABLE") {}
}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_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CloseCycle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"CreateGenesisNfts","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"wallet","type":"address"}],"name":"GetAbleBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetAbleToConfidenceReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetAbleToConstancyReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetAbleToValueReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetAmountOfNftMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetCycle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetStablecoinToConfidenceReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetStablecoinToConstancyReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetStablecoinToPassiveReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GetStablecoinToReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"migration_contract","type":"address"},{"internalType":"uint256","name":"month_contract","type":"uint256"}],"name":"HandleRecover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverEightLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverFirstLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverFiveLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverFourLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverNineLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverSecondLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverSevenLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverSixLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"contract_migration","type":"address"}],"name":"HandlerRecoverThirdLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"IsOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"IsQualified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"IsUpdated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_AMOUNT_FIRST_LEVEL_CONNECTIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MigrationSinergy","outputs":[{"internalType":"contract Migration","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":"uint256","name":"_tokenID","type":"uint256"}],"name":"ModifyNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"NftWasQualified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_ABLE_CONFIDENCE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_ABLE_CONSTANCY_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_ABLE_VALUE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_ABLE_CONFIDENCE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_ABLE_CONSTANCY_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_ABLE_VALUE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_STABLECOIN_CONFIDENCE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_STABLECOIN_CONSTANCY_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVIDE_STABLECOIN_VALUE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_STABLECOIN_CONFIDENCE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_STABLECOIN_CONSTANCY_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_STABLECOIN_VALUE_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RefreshContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleConfidenceRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleConfidenceRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleConstancyRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleConstancyRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAblePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleValueRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetAbleValueRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"SetAddresses","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":"uint256","name":"amount","type":"uint256"}],"name":"SetMinAmountFirstLevelConnections","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinConfidenceRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinConfidenceRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinConstancyRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinConstancyRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinPercentReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinPercentRewardDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinValueRewardPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetStablecoinValueRewardPercentDivide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"SinergyBronze","outputs":[{"internalType":"contract Sinergy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Stablecoin","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDT","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"UpdateQualifiedNfts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"token_id","type":"uint256"},{"internalType":"uint256","name":"reward_amount","type":"uint256"}],"name":"_TrnasferStablecoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","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":[],"name":"contracts_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":[],"name":"initial_tokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"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":"","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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nfts_qualified_by_cycle","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":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","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":[{"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_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":[],"name":"updateFromAble","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405273f7ca5aeb3d2dbc0012f153224e22a1757c8f83f5600b60006101000a8154816001600160a01b0302191690836001600160a01b031602179055506001600c556801f399b1438a10000060285567a688906bd8b000006029556001602a55600c602b556001602c55600c602d556001602e55600c602f556001603055600c6031556001603255600360335560016034556003603555600160365560036037556003603855610515603b55348015620000bb57600080fd5b50604080518082018252600d81526c4f666665722053696e6572677960981b60208083019182528351808501909452600784526653696e6572677960c81b908401528151919291620001109160009162000700565b5080516200012690600190602084019062000700565b505050620001436200013d6200042560201b60201c565b62000429565b603b546200015d60396200047b60201b620038dc1760201c565b101562000181576200017b60396200047f60201b620038e01760201c565b62000143565b600b546040805163ddf0604560e01b815290516000926001600160a01b03169163ddf06045916004808301926020929190829003018186803b158015620001c757600080fd5b505afa158015620001dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002029190620007a6565b905060006200021d60396200047b60201b620038dc1760201c565b90506200023660396200047f60201b620038e01760201c565b62000242828262000488565b604080518082018252600781526647454e4553495360c81b60208083019182526000858152603f9091529290922090516200027e929062000700565b50604080518082018252601381527f47454e4553495320494e534352495054494f4e000000000000000000000000006020808301918252600085815290849052929092209051620002d0929062000700565b50604080518082018252601681527f47454e455349532056414c55452050524f504f53414c0000000000000000000060208083019182526000858152604190915292909220905162000323929062000700565b506040518060800160405280605c8152602001620066b5605c91396000828152604360209081526040909120825162000363939192919091019062000700565b5060008181526042602090815260408083204290556001600160a01b03851683526007825291829020839055815160608101909252603e808352620003b59284929091906200671190830139620004ae565b6001600160a01b03821660009081526006602090815260408220805460018101825590835290822001829055603b54603a556008805491620003f783620008bc565b9091555050506001600160a01b03166000908152605e60205260409020805460ff19166001179055620008e6565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b80546001019055565b620004aa828260405180602001604052806000815250620004e960201b60201c565b5050565b620004b9826200050e565b620004c357600080fd5b60008281526009602090815260409091208251620004e49284019062000700565b505050565b620004f583836200052b565b620005046000848484620005d6565b620004e457600080fd5b6000908152600260205260409020546001600160a01b0316151590565b6001600160a01b0382166200053f57600080fd5b6200054a816200050e565b156200055557600080fd5b62000560816200050e565b156200056b57600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000620005f7846001600160a01b0316620006f160201b620038e91760201c565b15620006e557604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906200063190339089908890889060040162000804565b602060405180830381600087803b1580156200064c57600080fd5b505af19250505080156200067f575060408051601f3d908101601f191682019092526200067c91810190620007d8565b60015b620006ca573d808015620006b0576040519150601f19603f3d011682016040523d82523d6000602084013e620006b5565b606091505b508051620006c257600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050620006e9565b5060015b949350505050565b6001600160a01b03163b151590565b8280546200070e906200087f565b90600052602060002090601f0160209004810192826200073257600085556200077d565b82601f106200074d57805160ff19168380011785556200077d565b828001600101855582156200077d579182015b828111156200077d57825182559160200191906001019062000760565b506200078b9291506200078f565b5090565b5b808211156200078b576000815560010162000790565b600060208284031215620007b957600080fd5b81516001600160a01b0381168114620007d157600080fd5b9392505050565b600060208284031215620007eb57600080fd5b81516001600160e01b031981168114620007d157600080fd5b600060018060a01b038087168352602081871681850152856040850152608060608501528451915081608085015260005b82811015620008535785810182015185820160a00152810162000835565b828111156200086657600060a084870101525b5050601f01601f19169190910160a00195945050505050565b600181811c908216806200089457607f821691505b60208210811415620008b657634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415620008df57634e487b7160e01b600052601160045260246000fd5b5060010190565b615dbf80620008f66000396000f3fe608060405234801561001057600080fd5b50600436106105c15760003560e01c806301b9f212146105c657806301ffc9a7146105db578063034e63f41461060357806306fdde031461061a578063078f3bd21461062f578063081812fc1461064257806308a1f67f14610662578063095ea7b3146106755780630a5fdca8146106885780630dfc4ef91461069b578063172a327e146106a4578063193767cd146106ad5780631c5c4759146106c05780631dabeeff146106c85780631eb60deb146106d157806323b872dd146106e4578063297e0762146106f75780632e4564661461070a578063328b18a5146107125780633c1bd0831461071b5780633eab2b481461072e57806341a4051b14610741578063425ea88e1461074957806342842e0e146107515780634347ec0514610764578063443c0aa41461076d57806346ada0ec1461078d57806346bce096146107a05780634886d946146107c0578063489693cd146107d35780634a1be8c8146107dc5780634d1ea9c5146107ef57806351efae0d14610802578063529a7e381461081557806353294b70146108285780635616f325146108485780635805de06146108685780635c5699371461087b5780635d215e6f1461088e5780635d27d821146108975780635d3f7f0a146108aa5780636136c156146108bd578063620481a5146108dd578063634ddfd8146108f05780636352211e1461090357806364b43775146109165780636841b0a91461092957806369040b54146106ad578063706e2dfd1461094957806370a082311461096957806370c703831461097c578063715018a61461098f57806372638346146109975780637578a5901461099f578063782300d5146109a85780637ac5e5af146109cb5780637b970727146109de5780637e53bfc0146109f15780637f51e803146109fa578063813e551c14610a0d57806381c9db7714610a2d57806382210e5f14610a4d578063824dcd2514610a6057806382d706ad14610a7357806384370b7a14610a865780638506907814610a8f578063895694bf14610a9757806389a3027114610aaa5780638a9e8b7014610abd5780638acb5bd414610ac65780638b61b56e14610ad95780638d5791dc14610ae15780638d859f3e14610b015780638da5cb5b14610b0a5780639106e0be14610b1257806391dbff7a14610b325780639556fb8914610b4557806395c50b9314610b5857806395d89b4114610b61578063973138fa14610b69578063995672bb14610b7c578063995b145314610b845780639b13263014610b8d578063a104808014610ba0578063a22cb46514610ba9578063a283323814610bbc578063a45179a114610bc5578063a653bfdc14610be5578063a867326c14610c05578063ab3d63a814610c18578063af95166514610c2b578063b0deaa7014610c34578063b3e2067014610c47578063b3ea900114610c4f578063b484ba3614610c57578063b88d4fde14610c6a578063bb68c17014610c7d578063bd8cd14e14610c90578063c27ce47914610cb0578063c2b04ef414610cc3578063c4a1eefc14610cd6578063c54e44eb14610cdf578063c7a0e1dc14610cf2578063c87b56dd14610d15578063c8aaf64b146105d9578063ca14b06d14610d28578063cafb7bec14610d3b578063cb9f22c614610d4e578063cf814b5014610d6e578063d1ce9af314610d81578063d4d792fb14610d8a578063d6003e4e14610d92578063d819abc714610db2578063d8e409d814610dc5578063d94a776214610dd8578063da74d74214610deb578063dad964f414610dfe578063dd0860a814610e1e578063e1aaa2fa14610e31578063e1cdc6f714610e44578063e681204114610e64578063e774620f14610e84578063e985e9c514610e97578063eb20feab14610eaa578063ec78f9cc14610ebd578063ecd8966414610ec6578063f187806b14610ee6578063f2fde38b14610ef9578063f3c304fd14610f0c578063fcd9d7ff14610f15578063feecf85014610f1d575b600080fd5b6105d96105d43660046159a0565b610f26565b005b6105ee6105e936600461577d565b610f3b565b60405190151581526020015b60405180910390f35b61060c60335481565b6040519081526020016105fa565b610622610f8d565b6040516105fa9190615b32565b6105ee61063d3660046159a0565b61101f565b6106556106503660046159a0565b6110ce565b6040516105fa9190615aa4565b61060c6106703660046159d2565b6110f5565b6105d96106833660046156b7565b611126565b6105d96106963660046159a0565b611186565b61060c60085481565b61060c60595481565b6105d96106bb3660046159a0565b61119b565b61060c6111b0565b61060c602e5481565b61060c6106df36600461572b565b6111d4565b6105d96106f23660046155c9565b611365565b61060c6107053660046159d2565b611383565b6105d961139f565b61060c603a5481565b6106226107293660046159a0565b6113d5565b61060c61073c3660046159d2565b61146f565b6105d961148b565b61060c611635565b6105d961075f3660046155c9565b61164a565b61060c60325481565b61060c61077b3660046159a0565b60476020526000908152604090205481565b6105d961079b36600461582d565b611665565b61060c6107ae3660046159a0565b60466020526000908152604090205481565b6105d96107ce3660046159a0565b611af9565b61060c60365481565b6105d96107ea3660046159a0565b611b0e565b6105ee6107fd366004615556565b611b23565b6105d96108103660046159f4565b611b40565b6105d96108233660046159a0565b611c03565b61060c6108363660046159a0565b604c6020526000908152604090205481565b61060c6108563660046159a0565b60486020526000908152604090205481565b6105ee610876366004615556565b611c2b565b6105d96108893660046159f4565b611c5c565b61060c603b5481565b601054610655906001600160a01b031681565b61060c6108b8366004615556565b611cb3565b61060c6108cb366004615556565b605b6020526000908152604090205481565b6105d96108eb3660046159a0565b611d34565b61060c6108fe3660046159d2565b611d49565b6106556109113660046159a0565b611d65565b6105d96109243660046159f4565b611d86565b61060c6109373660046159a0565b605d6020526000908152604090205481565b61060c6109573660046159a0565b60496020526000908152604090205481565b61060c610977366004615556565b611ddd565b61060c61098a3660046159d2565b611e0e565b6105d9611e2a565b61060c611e3e565b61060c600c5481565b6105ee6109b6366004615556565b605e6020526000908152604090205460ff1681565b6105d96109d9366004615556565b611e53565b6105d96109ec366004615556565b611f45565b61060c602d5481565b6105d9610a083660046159a0565b61202f565b61060c610a1b366004615556565b605c6020526000908152604090205481565b61060c610a3b3660046159a0565b604a6020526000908152604090205481565b61060c610a5b3660046156b7565b612057565b6105d9610a6e3660046159a0565b612073565b610622610a813660046159a0565b612088565b61060c603d5481565b61060c6120a1565b61060c610aa53660046159d2565b6120b6565b602654610655906001600160a01b031681565b61060c60385481565b6105d9610ad43660046159f4565b6120d2565b61060c612129565b61060c610aef3660046159a0565b60576020526000908152604090205481565b61060c60285481565b61065561213e565b61060c610b203660046159a0565b60456020526000908152604090205481565b61060c610b403660046159d2565b61214d565b6105d9610b533660046159a0565b612169565b61060c60355481565b61062261217e565b6105d9610b773660046156e3565b61218d565b61060c61226a565b61060c60375481565b6105d9610b9b3660046159f4565b612275565b61060c602b5481565b6105d9610bb7366004615689565b6122cc565b61060c602a5481565b61060c610bd33660046159a0565b603c6020526000908152604090205481565b61060c610bf33660046159a0565b60426020526000908152604090205481565b6105d9610c133660046159a0565b6122d7565b601554610655906001600160a01b031681565b61060c602c5481565b6105d9610c423660046159f4565b6122ec565b61060c612343565b61060c6123c0565b6105d9610c65366004615911565b6123d5565b6105d9610c7836600461560a565b6125ae565b6105d9610c8b3660046159f4565b6125cd565b61060c610c9e366004615556565b60076020526000908152604090205481565b602554610655906001600160a01b031681565b6105d9610cd13660046159a0565b612624565b61060c60295481565b602754610655906001600160a01b031681565b6105ee610d00366004615556565b603e6020526000908152604090205460ff1681565b610622610d233660046159a0565b612639565b6105d9610d363660046159f4565b612644565b61060c610d493660046159d2565b61269b565b61060c610d5c3660046159a0565b604d6020526000908152604090205481565b6105d9610d7c3660046159a0565b6126b7565b61060c60305481565b61060c6126cc565b61060c610da0366004615556565b605f6020526000908152604090205481565b6105d9610dc03660046159a0565b6126e1565b6105d9610dd33660046156b7565b6126f6565b6105d9610de63660046159f4565b6127a2565b610622610df93660046159a0565b6127f9565b61060c610e0c3660046159a0565b60446020526000908152604090205481565b6105ee610e2c366004615556565b612812565b610622610e3f3660046159a0565b612843565b61060c610e523660046159a0565b604b6020526000908152604090205481565b61060c610e72366004615556565b605a6020526000908152604090205481565b6105d9610e923660046159a0565b61285c565b6105ee610ea5366004615590565b612871565b61060c610eb83660046159d2565b61289f565b61060c602f5481565b61060c610ed43660046159a0565b60586020526000908152604090205481565b6105d9610ef43660046159a0565b6128bb565b6105d9610f07366004615556565b6128d0565b61060c60315481565b6105d96128f4565b61060c60345481565b610f2f33612812565b610f365750565b602a55565b60006001600160e01b031982166380ac58cd60e01b1480610f6c57506001600160e01b03198216635b5e139f60e01b145b80610f8757506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060008054610f9c90615c46565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc890615c46565b80156110155780601f10610fea57610100808354040283529160200191611015565b820191906000526020600020905b815481529060010190602001808311610ff857829003601f168201915b5050505050905090565b600061102d61087683611d65565b80610f875750600e546001600160a01b03166346f4d72561104d84611d65565b6001611057612343565b6110619190615c03565b6040518363ffffffff1660e01b815260040161107e929190615b19565b60206040518083038186803b15801561109657600080fd5b505afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f879190615760565b60006110d9826138f8565b506000908152600460205260409020546001600160a01b031690565b6053602052816000526040600020818154811061111157600080fd5b90600052602060002001600091509150505481565b600061113182611d65565b9050806001600160a01b0316836001600160a01b0316141561115257600080fd5b336001600160a01b038216148061116e575061116e8133612871565b61117757600080fd5b611181838361390a565b505050565b61118f33612812565b6111965750565b603555565b6111a433612812565b6111ab5750565b603455565b60006031546030546028546111c59190615be4565b6111cf9190615bc2565b905090565b60005b6038546000848152604460205260409020541080156111f557508215155b1561121b57600092835260576020526040909220549161121483611d65565b93506111d7565b60255460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061124d9087908690600401615b19565b602060405180830381600087803b15801561126757600080fd5b505af115801561127b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129f9190615760565b506001600160a01b0384166000908152605a6020526040812080548492906112c8908490615baa565b9091555050600083815260586020526040812080548492906112eb908490615baa565b9250508190555081605960008282546113049190615baa565b9250508190555042846001600160a01b03167fa421b4aced6f4fcb40d755e461bb29417a90636ae4f2769ff2cb29db7eab79948585604051611347929190615b45565b60405180910390a35050600090815260576020526040902054919050565b61136f3382613978565b61137857600080fd5b6111818383836139d7565b6050602052816000526040600020818154811061111157600080fd5b600d546001600160a01b031633146113b357565b603d54603c60006113c2612343565b8152602081019190915260400160002055565b604360205260009081526040902080546113ee90615c46565b80601f016020809104026020016040519081016040528092919081815260200182805461141a90615c46565b80156114675780601f1061143c57610100808354040283529160200191611467565b820191906000526020600020905b81548152906001019060200180831161144a57829003601f168201915b505050505081565b604e602052816000526040600020818154811061111157600080fd5b6015546001600160a01b0316331461149f57565b600b546040805163adbf1fb960e01b815290516000926001600160a01b03169163adbf1fb9916004808301926020929190829003018186803b1580156114e457600080fd5b505afa1580156114f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151c9190615573565b905060005b6009811015611631576115348282613b28565b611556816040518060600160405280603c8152602001615d2e603c9139613b42565b601f5461156f9082906001600160a01b03166004613b73565b6001600160a01b03828116600090815260066020908152604080832080546001810182559084529190922001839055601f549051633b36259960e21b81526004810184905291169063ecd896649060240160206040518083038186803b1580156115d857600080fd5b505afa1580156115ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161091906159b9565b6000828152605860205260409020558061162981615c81565b915050611521565b5050565b6000602b54602a546028546111c59190615be4565b611181838383604051806020016040528060008152506125ae565b61166e33611b23565b61167757611af0565b600060076000601460009054906101000a90046001600160a01b03166001600160a01b03166374d6abcb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116cb57600080fd5b505afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117039190615573565b6001600160a01b03168152602081019190915260400160002054905082156117285750815b80611731575060085b603954811061173f57600080fd5b6025546028546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916117749133913091600401615ab8565b602060405180830381600087803b15801561178e57600080fd5b505af11580156117a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c69190615760565b50600f546029546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916117fc9133913091600401615ab8565b602060405180830381600087803b15801561181657600080fd5b505af115801561182a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184e9190615760565b5061185833611f45565b600061186333611ddd565b11156118df576014543360009081526007602052604090819020549051635354b0f160e11b81526001600160a01b039092169163a6a961e2916118ac9160040190815260200190565b600060405180830381600087803b1580156118c657600080fd5b505af11580156118da573d6000803e3d6000fd5b505050505b60006118ea60395490565b90506118fa603980546001019055565b6119043382613b28565b61190e8187613b42565b6000818152603f602090815260409091208a5161192d928c019061545f565b506000818152604060208181529120895161194a928b019061545f565b506000818152604160209081526040909120885161196a928a019061545f565b5060008181526057602090815260408083208590556043825290912086516119949288019061545f565b50600081815260426020908152604080832086905533835260079091529020546119cb573360009081526007602052604090208190555b336000908152600660209081526040822080546001810182559083529120018190556119f56145bf565b6119fd6146e0565b611a05614792565b611a1181836001614844565b605d6000611a1d612343565b81526020019081526020016000206000815480929190611a3c90615c81565b9091555050336000908152605e602052604090205460ff16611a8657336000908152605e60205260408120805460ff191660011790556008805491611a8083615c81565b91905055505b6040513390611a96908990615a59565b60405180910390208a604051611aac9190615a59565b60405180910390207f348a2af61c3e551d263eaa8735e61cbaaa4dbbcde2de30c684dd75431e5088d78442604051611ae5929190615b45565b60405180910390a450505b50505050505050565b611b0233612812565b611b095750565b603855565b611b1733612812565b611b1e5750565b602f55565b600e546000906001600160a01b0316633c992a9183611061612343565b6015546001600160a01b03163314611b5757505050565b6000838152605460205260409081902090516332bedefb60e21b81528291906001600160a01b0383169063cafb7bec90611b979088908890600401615b45565b60206040518083038186803b158015611baf57600080fd5b505afa158015611bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be791906159b9565b8154600181018355600092835260209092209091015550505050565b611c0c33612812565b611c135750565b611c2581670de0b6b3a7640000615be4565b60285550565b600e54604051632c02ef0360e11b81526000916001600160a01b031690635805de069061107e908590600401615aa4565b6015546001600160a01b03163314611c7357505050565b6000838152604e60205260409081902090516307d5656960e31b81528291906001600160a01b03831690633eab2b4890611b979088908890600401615b45565b600f546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611ce4908590600401615aa4565b60206040518083038186803b158015611cfc57600080fd5b505afa158015611d10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8791906159b9565b611d3d33612812565b611d445750565b603355565b6055602052816000526040600020818154811061111157600080fd5b600080611d71836148a9565b90506001600160a01b038116610f8757600080fd5b6015546001600160a01b03163314611d9d57505050565b6000838152605360205260409081902090516308a1f67f60e01b81528291906001600160a01b038316906308a1f67f90611b979088908890600401615b45565b60006001600160a01b038216611df257600080fd5b506001600160a01b031660009081526003602052604090205490565b6052602052816000526040600020818154811061111157600080fd5b611e326148c4565b611e3c60006148e0565b565b60006037546036546029546111c59190615be4565b600b54604051631ba10c1560e31b81526001600160a01b039091169063dd0860a890611e83903390600401615aa4565b60206040518083038186803b158015611e9b57600080fd5b505afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615760565b611f235760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e65722063616e20736574204164647265737365732e000000604482015260640160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152603e602052604090205460ff1615611fc5576001600160a01b0381166000908152605f6020526040812054603d805491929091611f92908490615c03565b90915550506001600160a01b0381166000908152605f60209081526040808320839055603e9091529020805460ff191690555b611fce81611c2b565b1561202c57611fdc81611ddd565b603d6000828254611fed9190615baa565b90915550611ffc905081611ddd565b6001600160a01b0382166000908152605f6020908152604080832093909355603e905220805460ff191660011790555b50565b61203833612812565b61203f5750565b61205181670de0b6b3a7640000615be4565b60295550565b6006602052816000526040600020818154811061111157600080fd5b61207c33612812565b6120835750565b603155565b604160205260009081526040902080546113ee90615c46565b60006035546034546029546111c59190615be4565b6051602052816000526040600020818154811061111157600080fd5b6015546001600160a01b031633146120e957505050565b60008381526051602052604090819020905163895694bf60e01b81528291906001600160a01b0383169063895694bf90611b979088908890600401615b45565b6000602f54602e546028546111c59190615be4565b600a546001600160a01b031690565b604f602052816000526040600020818154811061111157600080fd5b61217233612812565b6121795750565b602c55565b606060018054610f9c90615c46565b6015546001600160a01b031633146121a457612264565b6121af838383613b73565b6001600160a01b0384166000908152600660209081526040822080546001810182559083529120018390556121e384611ddd565b6121fd57600880549060006121f783615c81565b91905055505b6122078484613b28565b6001600160a01b038416600090815260076020526040902054612240576001600160a01b03841660009081526007602052604090208390555b61224984611c2b565b1561226457603d805490600061225e83615c81565b91905055505b50505050565b60006111cf60395490565b6015546001600160a01b0316331461228c57505050565b6000838152604f60205260409081902090516348edffbd60e11b81528291906001600160a01b038316906391dbff7a90611b979088908890600401615b45565b611631338383614932565b6122e033612812565b6122e75750565b603755565b6015546001600160a01b0316331461230357505050565b6000838152605260205260409081902090516370c7038360e01b81528291906001600160a01b038316906370c7038390611b979088908890600401615b45565b600d5460408051636190c9d560e01b815290516000926001600160a01b031691636190c9d5916004808301926020929190829003018186803b15801561238857600080fd5b505afa15801561239c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cf91906159b9565b60006033546032546029546111c59190615be4565b6123de33611b23565b158061240457506123ee81611d65565b6001600160a01b0316336001600160a01b031614155b1561240e57612264565b6025546028546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916124439133913091600401615ab8565b602060405180830381600087803b15801561245d57600080fd5b505af1158015612471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124959190615760565b50600f546029546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916124cb9133913091600401615ab8565b602060405180830381600087803b1580156124e557600080fd5b505af11580156124f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251d9190615760565b506000818152603f60209081526040909120855161253d9287019061545f565b506000818152604060208181529120845161255a9286019061545f565b506000818152604160209081526040909120835161257a9285019061545f565b506125836145bf565b61258b6146e0565b612593614792565b60008181526057602052604081205461226491839190614844565b6125b83383613978565b6125c157600080fd5b612264848484846149be565b6015546001600160a01b031633146125e457505050565b600083815260556020526040908190209051630c69bbfb60e31b81528291906001600160a01b0383169063634ddfd890611b979088908890600401615b45565b61262d33612812565b6126345750565b602b55565b6060610f87826149de565b6015546001600160a01b0316331461265b57505050565b60008381526056602052604090819020905163eb20feab60e01b81528291906001600160a01b0383169063eb20feab90611b979088908890600401615b45565b6054602052816000526040600020818154811061111157600080fd5b6126c033612812565b6126c75750565b602e55565b6000602d54602c546028546111c59190615be4565b6126ea33612812565b6126f15750565b602d55565b603954811115612704575050565b61270d81611d65565b6001600160a01b0316336001600160a01b03161415801561273957506015546001600160a01b03163314155b15612742575050565b6001600160a01b03821660009081526007602052604090819020805490839055905133907ff1920cbfe18dff4155b1e46e979d6d82313c39f04760c14fbb8f37a21b36e912906127959084908690615b45565b60405180910390a2505050565b6015546001600160a01b031633146127b957505050565b6000838152605060205260409081902090516314bf03b160e11b81528291906001600160a01b0383169063297e076290611b979088908890600401615b45565b603f60205260009081526040902080546113ee90615c46565b600b54604051631ba10c1560e31b81526000916001600160a01b03169063dd0860a89061107e908590600401615aa4565b604060208190526000918252902080546113ee90615c46565b61286533612812565b61286c5750565b603055565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6056602052816000526040600020818154811061111157600080fd5b6128c433612812565b6128cb5750565b603255565b6128d86148c4565b6001600160a01b0381166128eb57600080fd5b61202c816148e0565b600b54604080516307578a5960e41b815290516000926001600160a01b031691637578a590916004808301926020929190829003018186803b15801561293957600080fd5b505afa15801561294d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297191906159b9565b905080600c5414156129805750565b600c819055600b5460408051635f9ca54b60e11b815290516001600160a01b039092169163bf394a9691600480820192602092909190829003018186803b1580156129ca57600080fd5b505afa1580156129de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a029190615573565b600d80546001600160a01b0319166001600160a01b03928316179055600b5460408051632d311b9f60e11b815290519190921691635a62373e916004808301926020929190829003018186803b158015612a5b57600080fd5b505afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190615573565b600e80546001600160a01b0319166001600160a01b03928316179055600b5460408051632fc69b7560e21b81529051919092169163bf1a6dd4916004808301926020929190829003018186803b158015612aec57600080fd5b505afa158015612b00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b249190615573565b600f80546001600160a01b0319166001600160a01b03928316179055600b5460408051635d27d82160e01b815290519190921691635d27d821916004808301926020929190829003018186803b158015612b7d57600080fd5b505afa158015612b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb59190615573565b601080546001600160a01b0319166001600160a01b03928316179055600b5460408051633739851960e21b81529051919092169163dce61464916004808301926020929190829003018186803b158015612c0e57600080fd5b505afa158015612c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c469190615573565b601180546001600160a01b0319166001600160a01b03928316179055600b546040805163fdf6c44360e01b81529051919092169163fdf6c443916004808301926020929190829003018186803b158015612c9f57600080fd5b505afa158015612cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd79190615573565b601280546001600160a01b0319166001600160a01b03928316179055600b54604080516353962e4560e11b81529051919092169163a72c5c8a916004808301926020929190829003018186803b158015612d3057600080fd5b505afa158015612d44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d689190615573565b601380546001600160a01b0319166001600160a01b03928316179055600b546040805163e93b941b60e01b81529051919092169163e93b941b916004808301926020929190829003018186803b158015612dc157600080fd5b505afa158015612dd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df99190615573565b601480546001600160a01b0319166001600160a01b03928316179055600b5460408051631567ac7560e31b81529051919092169163ab3d63a8916004808301926020929190829003018186803b158015612e5257600080fd5b505afa158015612e66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8a9190615573565b601580546001600160a01b0319166001600160a01b03928316179055600b5460408051635ffb42d960e11b81529051919092169163bff685b2916004808301926020929190829003018186803b158015612ee357600080fd5b505afa158015612ef7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1b9190615573565b601680546001600160a01b0319166001600160a01b03928316179055600b5460408051630bbc5d7d60e31b815290519190921691635de2ebe8916004808301926020929190829003018186803b158015612f7457600080fd5b505afa158015612f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fac9190615573565b601780546001600160a01b0319166001600160a01b03928316179055600b546040805163c586261f60e01b81529051919092169163c586261f916004808301926020929190829003018186803b15801561300557600080fd5b505afa158015613019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303d9190615573565b601880546001600160a01b0319166001600160a01b03928316179055600b5460408051637abb1b7360e01b815290519190921691637abb1b73916004808301926020929190829003018186803b15801561309657600080fd5b505afa1580156130aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ce9190615573565b601980546001600160a01b0319166001600160a01b03928316179055600b5460408051633dd5259d60e01b815290519190921691633dd5259d916004808301926020929190829003018186803b15801561312757600080fd5b505afa15801561313b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315f9190615573565b601a80546001600160a01b0319166001600160a01b03928316179055600b546040805163967db45360e01b81529051919092169163967db453916004808301926020929190829003018186803b1580156131b857600080fd5b505afa1580156131cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f09190615573565b601b80546001600160a01b0319166001600160a01b03928316179055600b54604080516310fced2960e01b8152905191909216916310fced29916004808301926020929190829003018186803b15801561324957600080fd5b505afa15801561325d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132819190615573565b601c80546001600160a01b0319166001600160a01b03928316179055600b5460408051634cfd0abf60e11b8152905191909216916399fa157e916004808301926020929190829003018186803b1580156132da57600080fd5b505afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190615573565b601d80546001600160a01b0319166001600160a01b03928316179055600b5460408051636164467360e01b8152905191909216916361644673916004808301926020929190829003018186803b15801561336b57600080fd5b505afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a39190615573565b601e80546001600160a01b0319166001600160a01b03928316179055600b5460408051631b7410a160e31b81529051919092169163dba08508916004808301926020929190829003018186803b1580156133fc57600080fd5b505afa158015613410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134349190615573565b601f80546001600160a01b0319166001600160a01b03928316179055600b546040805163484de36360e11b81529051919092169163909bc6c6916004808301926020929190829003018186803b15801561348d57600080fd5b505afa1580156134a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c59190615573565b602080546001600160a01b0319166001600160a01b03928316178155600b5460408051633310a27960e01b815290519190931692633310a279926004808301939192829003018186803b15801561351b57600080fd5b505afa15801561352f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135539190615573565b602180546001600160a01b0319166001600160a01b03928316179055600b5460408051633c9d0ac360e11b81529051919092169163793a1586916004808301926020929190829003018186803b1580156135ac57600080fd5b505afa1580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190615573565b602280546001600160a01b0319166001600160a01b03928316179055600b546040805163063606b760e51b81529051919092169163c6c0d6e0916004808301926020929190829003018186803b15801561363d57600080fd5b505afa158015613651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136759190615573565b602380546001600160a01b0319166001600160a01b03928316179055600b5460408051630ffbb3e960e21b815290519190921691633feecfa4916004808301926020929190829003018186803b1580156136ce57600080fd5b505afa1580156136e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137069190615573565b602480546001600160a01b0319166001600160a01b03928316179055600b546040805163c27ce47960e01b81529051919092169163c27ce479916004808301926020929190829003018186803b15801561375f57600080fd5b505afa158015613773573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137979190615573565b602580546001600160a01b0319166001600160a01b03928316179055600b54604080516389a3027160e01b8152905191909216916389a30271916004808301926020929190829003018186803b1580156137f057600080fd5b505afa158015613804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138289190615573565b602680546001600160a01b0319166001600160a01b03928316179055600b546040805163c54e44eb60e01b81529051919092169163c54e44eb916004808301926020929190829003018186803b15801561388157600080fd5b505afa158015613895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b99190615573565b602780546001600160a01b0319166001600160a01b039290921691909117905550565b5490565b80546001019055565b6001600160a01b03163b151590565b61390181614ae7565b61202c57600080fd5b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061393f82611d65565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061398483611d65565b9050806001600160a01b0316846001600160a01b031614806139ab57506139ab8185612871565b806139cf5750836001600160a01b03166139c4846110ce565b6001600160a01b0316145b949350505050565b826001600160a01b03166139ea82611d65565b6001600160a01b0316146139fd57600080fd5b6001600160a01b038216613a1057600080fd5b826001600160a01b0316613a2382611d65565b6001600160a01b031614613a3657600080fd5b600081815260046020526040902080546001600160a01b0319169055613a5c8184614b04565b6001600160a01b038316600090815260036020526040902080546000190190819055158015613a8d57506000600854115b15613a9d57600880546000190190555b613aa78183614cc5565b6001600160a01b038216600090815260036020526040902054613ace576008805460010190555b6001600160a01b03808316600081815260036020908152604080832080546001019055858352600290915280822080546001600160a01b03191684179055518493871691600080516020615d6a83398151915291a4505050565b611631828260405180602001604052806000815250614d19565b613b4b82614ae7565b613b5457600080fd5b600082815260096020908152604090912082516111819284019061545f565b604051636d3a6ba160e11b815260048101849052829081906001600160a01b0382169063da74d7429060240160006040518083038186803b158015613bb757600080fd5b505afa158015613bcb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613bf391908101906157b7565b6000868152603f602090815260409091208251613c16939192919091019061545f565b506040516370d5517d60e11b8152600481018690526001600160a01b0383169063e1aaa2fa9060240160006040518083038186803b158015613c5757600080fd5b505afa158015613c6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c9391908101906157b7565b60008681526040602081815291208251613cb3939192919091019061545f565b506040516382d706ad60e01b8152600481018690526001600160a01b038316906382d706ad9060240160006040518083038186803b158015613cf457600080fd5b505afa158015613d08573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d3091908101906157b7565b60008681526041602090815260409091208251613d53939192919091019061545f565b50604051632994eff760e21b8152600481018690526001600160a01b0383169063a653bfdc9060240160206040518083038186803b158015613d9457600080fd5b505afa158015613da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dcc91906159b9565b600086815260426020526040908190209190915551633c1bd08360e01b8152600481018690526001600160a01b03831690633c1bd0839060240160006040518083038186803b158015613e1e57600080fd5b505afa158015613e32573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613e5a91908101906157b7565b60008681526043602090815260409091208251613e7d939192919091019061545f565b50604051632355e47760e21b8152600481018690526001600160a01b03831690638d5791dc9060240160206040518083038186803b158015613ebe57600080fd5b505afa158015613ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef691906159b9565b6000868152605760205260409081902091909155516336b6593d60e21b8152600481018690526001600160a01b0383169063dad964f49060240160206040518083038186803b158015613f4857600080fd5b505afa158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f8091906159b9565b600086815260446020526040908190209190915551634883705f60e11b8152600481018690526001600160a01b03831690639106e0be9060240160206040518083038186803b158015613fd257600080fd5b505afa158015613fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400a91906159b9565b60008681526045602052604090819020919091555163235e704b60e11b8152600481018690526001600160a01b038316906346bce0969060240160206040518083038186803b15801561405c57600080fd5b505afa158015614070573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061409491906159b9565b60008681526046602052604090819020919091555163110f02a960e21b8152600481018690526001600160a01b0383169063443c0aa49060240160206040518083038186803b1580156140e657600080fd5b505afa1580156140fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061411e91906159b9565b600086815260476020526040908190209190915551635616f32560e01b8152600481018690526001600160a01b03831690635616f3259060240160206040518083038186803b15801561417057600080fd5b505afa158015614184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a891906159b9565b60008681526048602052604090819020919091555163706e2dfd60e01b8152600481018690526001600160a01b0383169063706e2dfd9060240160206040518083038186803b1580156141fa57600080fd5b505afa15801561420e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061423291906159b9565b6000868152604960205260409081902091909155516381c9db7760e01b8152600481018690526001600160a01b038316906381c9db779060240160206040518083038186803b15801561428457600080fd5b505afa158015614298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142bc91906159b9565b6000868152604a602052604090819020919091555163e1cdc6f760e01b8152600481018690526001600160a01b0383169063e1cdc6f79060240160206040518083038186803b15801561430e57600080fd5b505afa158015614322573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061434691906159b9565b6000868152604b602052604090819020919091555163053294b760e41b8152600481018690526001600160a01b038316906353294b709060240160206040518083038186803b15801561439857600080fd5b505afa1580156143ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d091906159b9565b6000868152604c60205260409081902091909155516365cf916360e11b8152600481018690526001600160a01b0383169063cb9f22c69060240160206040518083038186803b15801561442257600080fd5b505afa158015614436573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061445a91906159b9565b6000868152604d6020526040902055600483141561451357604051633b36259960e21b8152600481018690526001600160a01b0383169063ecd896649060240160206040518083038186803b1580156144b257600080fd5b505afa1580156144c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144ea91906159b9565b60008681526058602052604081208054909190614508908490615baa565b909155506145b89050565b82600b14156145b857604051633549d94b60e11b8152600481018690526001600160a01b03821690636a93b2969060240160206040518083038186803b15801561455c57600080fd5b505afa158015614570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061459491906159b9565b600086815260586020526040812080549091906145b2908490615baa565b90915550505b5050505050565b600f546019546001600160a01b039182169163a9059cbb91166145e06123c0565b6040518363ffffffff1660e01b81526004016145fd929190615b19565b602060405180830381600087803b15801561461757600080fd5b505af115801561462b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061464f9190615760565b506025546018546001600160a01b039182169163a9059cbb91166146716126cc565b6040518363ffffffff1660e01b815260040161468e929190615b19565b602060405180830381600087803b1580156146a857600080fd5b505af11580156146bc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202c9190615760565b600f54601b546001600160a01b039182169163a9059cbb91166147016120a1565b6040518363ffffffff1660e01b815260040161471e929190615b19565b602060405180830381600087803b15801561473857600080fd5b505af115801561474c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147709190615760565b50602554601a546001600160a01b039182169163a9059cbb9116614671612129565b600f54601d546001600160a01b039182169163a9059cbb91166147b3611e3e565b6040518363ffffffff1660e01b81526004016147d0929190615b19565b602060405180830381600087803b1580156147ea57600080fd5b505af11580156147fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148229190615760565b50602554601c546001600160a01b039182169163a9059cbb91166146716111b0565b60008080614850611635565b9050845b6009831015611af057841561486e5761486e838888614d39565b61487781611d65565b93506148848482846111d4565b60009687526057602052604090962054959050826148a181615c81565b935050614854565b6000908152600260205260409020546001600160a01b031690565b336148cd61213e565b6001600160a01b031614611e3c57600080fd5b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561495157600080fd5b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6149c98484846139d7565b6149d5848484846150e6565b61226457600080fd5b60606149e9826138f8565b60008281526009602052604081208054614a0290615c46565b80601f0160208091040260200160405190810160405280929190818152602001828054614a2e90615c46565b8015614a7b5780601f10614a5057610100808354040283529160200191614a7b565b820191906000526020600020905b815481529060010190602001808311614a5e57829003601f168201915b505050505090506000614a9960408051602081019091526000815290565b9050805160001415614aac575092915050565b815115614ade578082604051602001614ac6929190615a75565b60405160208183030381529060405292505050919050565b6139cf846151e7565b600080614af3836148a9565b6001600160a01b0316141592915050565b60005b6001600160a01b0382166000908152600660205260409020805484919083908110614b3457614b34615cc8565b906000526020600020015414614b565780614b4e81615c81565b915050614b07565b6001600160a01b038216600090815260036020526040902054614b7b90600190615c03565b811015614c14576001600160a01b0382166000908152600660205260409020614ba5826001615baa565b81548110614bb557614bb5615cc8565b906000526020600020015460066000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110614bf657614bf6615cc8565b60009182526020909120015580614c0c81615c81565b915050614b56565b6001600160a01b0382166000908152600660205260409020805480614c3b57614c3b615cb2565b6000828152602080822083016000199081018390559092019092556001600160a01b0384168252600790526040902054831415611181576001600160a01b03821660009081526006602052604081208054909190614c9b57614c9b615cc8565b60009182526020808320909101546001600160a01b03851683526007909152604090912055505050565b6001600160a01b0381166000818152600660209081526040808320805460018101825590845282842001869055928252600790522054611631576001600160a01b0316600090815260076020526040902055565b614d23838361525b565b614d3060008484846150e6565b61118157600080fd5b82614d9e576000818152604460205260408120805491614d5883615c81565b90915550506000818152604d60205260408120805491614d7783615c81565b90915550506000908152604e60209081526040822080546001810182559083529120015550565b8260011415614e07576000818152604560205260408120805491614dc183615c81565b90915550506000818152604d60205260408120805491614de083615c81565b90915550506000908152604f60209081526040822080546001810182559083529120015550565b8260021415614e70576000818152604660205260408120805491614e2a83615c81565b90915550506000818152604d60205260408120805491614e4983615c81565b90915550506000908152605060209081526040822080546001810182559083529120015550565b8260031415614ed9576000818152604760205260408120805491614e9383615c81565b90915550506000818152604d60205260408120805491614eb283615c81565b90915550506000908152605160209081526040822080546001810182559083529120015550565b8260041415614f42576000818152604860205260408120805491614efc83615c81565b90915550506000818152604d60205260408120805491614f1b83615c81565b90915550506000908152605260209081526040822080546001810182559083529120015550565b8260051415614fab576000818152604960205260408120805491614f6583615c81565b90915550506000818152604d60205260408120805491614f8483615c81565b90915550506000908152605360209081526040822080546001810182559083529120015550565b8260061415615014576000818152604a60205260408120805491614fce83615c81565b90915550506000818152604d60205260408120805491614fed83615c81565b90915550506000908152605460209081526040822080546001810182559083529120015550565b826007141561507d576000818152604b6020526040812080549161503783615c81565b90915550506000818152604d6020526040812080549161505683615c81565b90915550506000908152605560209081526040822080546001810182559083529120015550565b8260081415611181576000818152604c602052604081208054916150a083615c81565b90915550506000818152604d602052604081208054916150bf83615c81565b90915550506000908152605660209081526040822080546001810182559083529120015550565b60006150fa846001600160a01b03166138e9565b156151dc57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290615131903390899088908890600401615adc565b602060405180830381600087803b15801561514b57600080fd5b505af192505050801561517b575060408051601f3d908101601f191682019092526151789181019061579a565b60015b6151c2573d8080156151a9576040519150601f19603f3d011682016040523d82523d6000602084013e6151ae565b606091505b5080516151ba57600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506139cf565b506001949350505050565b60606151f2826138f8565b600061520960408051602081019091526000815290565b905060008151116152295760405180602001604052806000815250615254565b80615233846152ed565b604051602001615244929190615a75565b6040516020818303038152906040525b9392505050565b6001600160a01b03821661526e57600080fd5b61527781614ae7565b1561528157600080fd5b61528a81614ae7565b1561529457600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020615d6a833981519152908290a45050565b606060006152fa83615389565b60010190506000816001600160401b0381111561531957615319615cde565b6040519080825280601f01601f191660200182016040528015615343576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461537c57615381565b61534d565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106153c85772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106153f2576904ee2d6d415b85acef8160201b830492506020015b662386f26fc10000831061541057662386f26fc10000830492506010015b6305f5e1008310615428576305f5e100830492506008015b612710831061543c57612710830492506004015b6064831061544e576064830492506002015b600a8310610f875760010192915050565b82805461546b90615c46565b90600052602060002090601f01602090048101928261548d57600085556154d3565b82601f106154a657805160ff19168380011785556154d3565b828001600101855582156154d3579182015b828111156154d35782518255916020019190600101906154b8565b506154df9291506154e3565b5090565b5b808211156154df57600081556001016154e4565b600061550b61550684615b83565b615b53565b905082815283838301111561551f57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261554757600080fd5b615254838335602085016154f8565b60006020828403121561556857600080fd5b813561525481615cf4565b60006020828403121561558557600080fd5b815161525481615cf4565b600080604083850312156155a357600080fd5b82356155ae81615cf4565b915060208301356155be81615cf4565b809150509250929050565b6000806000606084860312156155de57600080fd5b83356155e981615cf4565b925060208401356155f981615cf4565b929592945050506040919091013590565b6000806000806080858703121561562057600080fd5b843561562b81615cf4565b9350602085013561563b81615cf4565b92506040850135915060608501356001600160401b0381111561565d57600080fd5b8501601f8101871361566e57600080fd5b61567d878235602084016154f8565b91505092959194509250565b6000806040838503121561569c57600080fd5b82356156a781615cf4565b915060208301356155be81615d09565b600080604083850312156156ca57600080fd5b82356156d581615cf4565b946020939093013593505050565b600080600080608085870312156156f957600080fd5b843561570481615cf4565b935060208501359250604085013561571b81615cf4565b9396929550929360600135925050565b60008060006060848603121561574057600080fd5b833561574b81615cf4565b95602085013595506040909401359392505050565b60006020828403121561577257600080fd5b815161525481615d09565b60006020828403121561578f57600080fd5b813561525481615d17565b6000602082840312156157ac57600080fd5b815161525481615d17565b6000602082840312156157c957600080fd5b81516001600160401b038111156157df57600080fd5b8201601f810184136157f057600080fd5b80516157fe61550682615b83565b81815285602083850101111561581357600080fd5b615824826020830160208601615c1a565b95945050505050565b600080600080600080600060e0888a03121561584857600080fd5b87356001600160401b038082111561585f57600080fd5b61586b8b838c01615536565b985060208a013591508082111561588157600080fd5b61588d8b838c01615536565b975060408a01359150808211156158a357600080fd5b6158af8b838c01615536565b965060608a01359150808211156158c557600080fd5b6158d18b838c01615536565b955060808a01359150808211156158e757600080fd5b506158f48a828b01615536565b93505060a0880135915060c0880135905092959891949750929550565b6000806000806080858703121561592757600080fd5b84356001600160401b038082111561593e57600080fd5b61594a88838901615536565b9550602087013591508082111561596057600080fd5b61596c88838901615536565b9450604087013591508082111561598257600080fd5b5061598f87828801615536565b949793965093946060013593505050565b6000602082840312156159b257600080fd5b5035919050565b6000602082840312156159cb57600080fd5b5051919050565b600080604083850312156159e557600080fd5b50508035926020909101359150565b600080600060608486031215615a0957600080fd5b83359250602084013591506040840135615a2281615cf4565b809150509250925092565b60008151808452615a45816020860160208601615c1a565b601f01601f19169290920160200192915050565b60008251615a6b818460208701615c1a565b9190910192915050565b60008351615a87818460208801615c1a565b835190830190615a9b818360208801615c1a565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b0f90830184615a2d565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b6020815260006152546020830184615a2d565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715615b7b57615b7b615cde565b604052919050565b60006001600160401b03821115615b9c57615b9c615cde565b50601f01601f191660200190565b60008219821115615bbd57615bbd615c9c565b500190565b600082615bdf57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615615bfe57615bfe615c9c565b500290565b600082821015615c1557615c15615c9c565b500390565b60005b83811015615c35578181015183820152602001615c1d565b838111156122645750506000910152565b600181811c90821680615c5a57607f821691505b60208210811415615c7b57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615c9557615c95615c9c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461202c57600080fd5b801515811461202c57600080fd5b6001600160e01b03198116811461202c57600080fdfe697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f302e6a736f6eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220868a46f6c1de263806a361876d5eb1974f5af51d22d0d93939ad068c17c9105e64736f6c6343000807003368747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f73617665722d636f6d6d756e6974792f696d6167652f75706c6f61642f76313636363338303530312f6a766a626c73346c67356d74787378686c686e662e706e67697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f3237332e6a736f6e
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106105c15760003560e01c806301b9f212146105c657806301ffc9a7146105db578063034e63f41461060357806306fdde031461061a578063078f3bd21461062f578063081812fc1461064257806308a1f67f14610662578063095ea7b3146106755780630a5fdca8146106885780630dfc4ef91461069b578063172a327e146106a4578063193767cd146106ad5780631c5c4759146106c05780631dabeeff146106c85780631eb60deb146106d157806323b872dd146106e4578063297e0762146106f75780632e4564661461070a578063328b18a5146107125780633c1bd0831461071b5780633eab2b481461072e57806341a4051b14610741578063425ea88e1461074957806342842e0e146107515780634347ec0514610764578063443c0aa41461076d57806346ada0ec1461078d57806346bce096146107a05780634886d946146107c0578063489693cd146107d35780634a1be8c8146107dc5780634d1ea9c5146107ef57806351efae0d14610802578063529a7e381461081557806353294b70146108285780635616f325146108485780635805de06146108685780635c5699371461087b5780635d215e6f1461088e5780635d27d821146108975780635d3f7f0a146108aa5780636136c156146108bd578063620481a5146108dd578063634ddfd8146108f05780636352211e1461090357806364b43775146109165780636841b0a91461092957806369040b54146106ad578063706e2dfd1461094957806370a082311461096957806370c703831461097c578063715018a61461098f57806372638346146109975780637578a5901461099f578063782300d5146109a85780637ac5e5af146109cb5780637b970727146109de5780637e53bfc0146109f15780637f51e803146109fa578063813e551c14610a0d57806381c9db7714610a2d57806382210e5f14610a4d578063824dcd2514610a6057806382d706ad14610a7357806384370b7a14610a865780638506907814610a8f578063895694bf14610a9757806389a3027114610aaa5780638a9e8b7014610abd5780638acb5bd414610ac65780638b61b56e14610ad95780638d5791dc14610ae15780638d859f3e14610b015780638da5cb5b14610b0a5780639106e0be14610b1257806391dbff7a14610b325780639556fb8914610b4557806395c50b9314610b5857806395d89b4114610b61578063973138fa14610b69578063995672bb14610b7c578063995b145314610b845780639b13263014610b8d578063a104808014610ba0578063a22cb46514610ba9578063a283323814610bbc578063a45179a114610bc5578063a653bfdc14610be5578063a867326c14610c05578063ab3d63a814610c18578063af95166514610c2b578063b0deaa7014610c34578063b3e2067014610c47578063b3ea900114610c4f578063b484ba3614610c57578063b88d4fde14610c6a578063bb68c17014610c7d578063bd8cd14e14610c90578063c27ce47914610cb0578063c2b04ef414610cc3578063c4a1eefc14610cd6578063c54e44eb14610cdf578063c7a0e1dc14610cf2578063c87b56dd14610d15578063c8aaf64b146105d9578063ca14b06d14610d28578063cafb7bec14610d3b578063cb9f22c614610d4e578063cf814b5014610d6e578063d1ce9af314610d81578063d4d792fb14610d8a578063d6003e4e14610d92578063d819abc714610db2578063d8e409d814610dc5578063d94a776214610dd8578063da74d74214610deb578063dad964f414610dfe578063dd0860a814610e1e578063e1aaa2fa14610e31578063e1cdc6f714610e44578063e681204114610e64578063e774620f14610e84578063e985e9c514610e97578063eb20feab14610eaa578063ec78f9cc14610ebd578063ecd8966414610ec6578063f187806b14610ee6578063f2fde38b14610ef9578063f3c304fd14610f0c578063fcd9d7ff14610f15578063feecf85014610f1d575b600080fd5b6105d96105d43660046159a0565b610f26565b005b6105ee6105e936600461577d565b610f3b565b60405190151581526020015b60405180910390f35b61060c60335481565b6040519081526020016105fa565b610622610f8d565b6040516105fa9190615b32565b6105ee61063d3660046159a0565b61101f565b6106556106503660046159a0565b6110ce565b6040516105fa9190615aa4565b61060c6106703660046159d2565b6110f5565b6105d96106833660046156b7565b611126565b6105d96106963660046159a0565b611186565b61060c60085481565b61060c60595481565b6105d96106bb3660046159a0565b61119b565b61060c6111b0565b61060c602e5481565b61060c6106df36600461572b565b6111d4565b6105d96106f23660046155c9565b611365565b61060c6107053660046159d2565b611383565b6105d961139f565b61060c603a5481565b6106226107293660046159a0565b6113d5565b61060c61073c3660046159d2565b61146f565b6105d961148b565b61060c611635565b6105d961075f3660046155c9565b61164a565b61060c60325481565b61060c61077b3660046159a0565b60476020526000908152604090205481565b6105d961079b36600461582d565b611665565b61060c6107ae3660046159a0565b60466020526000908152604090205481565b6105d96107ce3660046159a0565b611af9565b61060c60365481565b6105d96107ea3660046159a0565b611b0e565b6105ee6107fd366004615556565b611b23565b6105d96108103660046159f4565b611b40565b6105d96108233660046159a0565b611c03565b61060c6108363660046159a0565b604c6020526000908152604090205481565b61060c6108563660046159a0565b60486020526000908152604090205481565b6105ee610876366004615556565b611c2b565b6105d96108893660046159f4565b611c5c565b61060c603b5481565b601054610655906001600160a01b031681565b61060c6108b8366004615556565b611cb3565b61060c6108cb366004615556565b605b6020526000908152604090205481565b6105d96108eb3660046159a0565b611d34565b61060c6108fe3660046159d2565b611d49565b6106556109113660046159a0565b611d65565b6105d96109243660046159f4565b611d86565b61060c6109373660046159a0565b605d6020526000908152604090205481565b61060c6109573660046159a0565b60496020526000908152604090205481565b61060c610977366004615556565b611ddd565b61060c61098a3660046159d2565b611e0e565b6105d9611e2a565b61060c611e3e565b61060c600c5481565b6105ee6109b6366004615556565b605e6020526000908152604090205460ff1681565b6105d96109d9366004615556565b611e53565b6105d96109ec366004615556565b611f45565b61060c602d5481565b6105d9610a083660046159a0565b61202f565b61060c610a1b366004615556565b605c6020526000908152604090205481565b61060c610a3b3660046159a0565b604a6020526000908152604090205481565b61060c610a5b3660046156b7565b612057565b6105d9610a6e3660046159a0565b612073565b610622610a813660046159a0565b612088565b61060c603d5481565b61060c6120a1565b61060c610aa53660046159d2565b6120b6565b602654610655906001600160a01b031681565b61060c60385481565b6105d9610ad43660046159f4565b6120d2565b61060c612129565b61060c610aef3660046159a0565b60576020526000908152604090205481565b61060c60285481565b61065561213e565b61060c610b203660046159a0565b60456020526000908152604090205481565b61060c610b403660046159d2565b61214d565b6105d9610b533660046159a0565b612169565b61060c60355481565b61062261217e565b6105d9610b773660046156e3565b61218d565b61060c61226a565b61060c60375481565b6105d9610b9b3660046159f4565b612275565b61060c602b5481565b6105d9610bb7366004615689565b6122cc565b61060c602a5481565b61060c610bd33660046159a0565b603c6020526000908152604090205481565b61060c610bf33660046159a0565b60426020526000908152604090205481565b6105d9610c133660046159a0565b6122d7565b601554610655906001600160a01b031681565b61060c602c5481565b6105d9610c423660046159f4565b6122ec565b61060c612343565b61060c6123c0565b6105d9610c65366004615911565b6123d5565b6105d9610c7836600461560a565b6125ae565b6105d9610c8b3660046159f4565b6125cd565b61060c610c9e366004615556565b60076020526000908152604090205481565b602554610655906001600160a01b031681565b6105d9610cd13660046159a0565b612624565b61060c60295481565b602754610655906001600160a01b031681565b6105ee610d00366004615556565b603e6020526000908152604090205460ff1681565b610622610d233660046159a0565b612639565b6105d9610d363660046159f4565b612644565b61060c610d493660046159d2565b61269b565b61060c610d5c3660046159a0565b604d6020526000908152604090205481565b6105d9610d7c3660046159a0565b6126b7565b61060c60305481565b61060c6126cc565b61060c610da0366004615556565b605f6020526000908152604090205481565b6105d9610dc03660046159a0565b6126e1565b6105d9610dd33660046156b7565b6126f6565b6105d9610de63660046159f4565b6127a2565b610622610df93660046159a0565b6127f9565b61060c610e0c3660046159a0565b60446020526000908152604090205481565b6105ee610e2c366004615556565b612812565b610622610e3f3660046159a0565b612843565b61060c610e523660046159a0565b604b6020526000908152604090205481565b61060c610e72366004615556565b605a6020526000908152604090205481565b6105d9610e923660046159a0565b61285c565b6105ee610ea5366004615590565b612871565b61060c610eb83660046159d2565b61289f565b61060c602f5481565b61060c610ed43660046159a0565b60586020526000908152604090205481565b6105d9610ef43660046159a0565b6128bb565b6105d9610f07366004615556565b6128d0565b61060c60315481565b6105d96128f4565b61060c60345481565b610f2f33612812565b610f365750565b602a55565b60006001600160e01b031982166380ac58cd60e01b1480610f6c57506001600160e01b03198216635b5e139f60e01b145b80610f8757506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060008054610f9c90615c46565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc890615c46565b80156110155780601f10610fea57610100808354040283529160200191611015565b820191906000526020600020905b815481529060010190602001808311610ff857829003601f168201915b5050505050905090565b600061102d61087683611d65565b80610f875750600e546001600160a01b03166346f4d72561104d84611d65565b6001611057612343565b6110619190615c03565b6040518363ffffffff1660e01b815260040161107e929190615b19565b60206040518083038186803b15801561109657600080fd5b505afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f879190615760565b60006110d9826138f8565b506000908152600460205260409020546001600160a01b031690565b6053602052816000526040600020818154811061111157600080fd5b90600052602060002001600091509150505481565b600061113182611d65565b9050806001600160a01b0316836001600160a01b0316141561115257600080fd5b336001600160a01b038216148061116e575061116e8133612871565b61117757600080fd5b611181838361390a565b505050565b61118f33612812565b6111965750565b603555565b6111a433612812565b6111ab5750565b603455565b60006031546030546028546111c59190615be4565b6111cf9190615bc2565b905090565b60005b6038546000848152604460205260409020541080156111f557508215155b1561121b57600092835260576020526040909220549161121483611d65565b93506111d7565b60255460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061124d9087908690600401615b19565b602060405180830381600087803b15801561126757600080fd5b505af115801561127b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129f9190615760565b506001600160a01b0384166000908152605a6020526040812080548492906112c8908490615baa565b9091555050600083815260586020526040812080548492906112eb908490615baa565b9250508190555081605960008282546113049190615baa565b9250508190555042846001600160a01b03167fa421b4aced6f4fcb40d755e461bb29417a90636ae4f2769ff2cb29db7eab79948585604051611347929190615b45565b60405180910390a35050600090815260576020526040902054919050565b61136f3382613978565b61137857600080fd5b6111818383836139d7565b6050602052816000526040600020818154811061111157600080fd5b600d546001600160a01b031633146113b357565b603d54603c60006113c2612343565b8152602081019190915260400160002055565b604360205260009081526040902080546113ee90615c46565b80601f016020809104026020016040519081016040528092919081815260200182805461141a90615c46565b80156114675780601f1061143c57610100808354040283529160200191611467565b820191906000526020600020905b81548152906001019060200180831161144a57829003601f168201915b505050505081565b604e602052816000526040600020818154811061111157600080fd5b6015546001600160a01b0316331461149f57565b600b546040805163adbf1fb960e01b815290516000926001600160a01b03169163adbf1fb9916004808301926020929190829003018186803b1580156114e457600080fd5b505afa1580156114f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151c9190615573565b905060005b6009811015611631576115348282613b28565b611556816040518060600160405280603c8152602001615d2e603c9139613b42565b601f5461156f9082906001600160a01b03166004613b73565b6001600160a01b03828116600090815260066020908152604080832080546001810182559084529190922001839055601f549051633b36259960e21b81526004810184905291169063ecd896649060240160206040518083038186803b1580156115d857600080fd5b505afa1580156115ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161091906159b9565b6000828152605860205260409020558061162981615c81565b915050611521565b5050565b6000602b54602a546028546111c59190615be4565b611181838383604051806020016040528060008152506125ae565b61166e33611b23565b61167757611af0565b600060076000601460009054906101000a90046001600160a01b03166001600160a01b03166374d6abcb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116cb57600080fd5b505afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117039190615573565b6001600160a01b03168152602081019190915260400160002054905082156117285750815b80611731575060085b603954811061173f57600080fd5b6025546028546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916117749133913091600401615ab8565b602060405180830381600087803b15801561178e57600080fd5b505af11580156117a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c69190615760565b50600f546029546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916117fc9133913091600401615ab8565b602060405180830381600087803b15801561181657600080fd5b505af115801561182a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184e9190615760565b5061185833611f45565b600061186333611ddd565b11156118df576014543360009081526007602052604090819020549051635354b0f160e11b81526001600160a01b039092169163a6a961e2916118ac9160040190815260200190565b600060405180830381600087803b1580156118c657600080fd5b505af11580156118da573d6000803e3d6000fd5b505050505b60006118ea60395490565b90506118fa603980546001019055565b6119043382613b28565b61190e8187613b42565b6000818152603f602090815260409091208a5161192d928c019061545f565b506000818152604060208181529120895161194a928b019061545f565b506000818152604160209081526040909120885161196a928a019061545f565b5060008181526057602090815260408083208590556043825290912086516119949288019061545f565b50600081815260426020908152604080832086905533835260079091529020546119cb573360009081526007602052604090208190555b336000908152600660209081526040822080546001810182559083529120018190556119f56145bf565b6119fd6146e0565b611a05614792565b611a1181836001614844565b605d6000611a1d612343565b81526020019081526020016000206000815480929190611a3c90615c81565b9091555050336000908152605e602052604090205460ff16611a8657336000908152605e60205260408120805460ff191660011790556008805491611a8083615c81565b91905055505b6040513390611a96908990615a59565b60405180910390208a604051611aac9190615a59565b60405180910390207f348a2af61c3e551d263eaa8735e61cbaaa4dbbcde2de30c684dd75431e5088d78442604051611ae5929190615b45565b60405180910390a450505b50505050505050565b611b0233612812565b611b095750565b603855565b611b1733612812565b611b1e5750565b602f55565b600e546000906001600160a01b0316633c992a9183611061612343565b6015546001600160a01b03163314611b5757505050565b6000838152605460205260409081902090516332bedefb60e21b81528291906001600160a01b0383169063cafb7bec90611b979088908890600401615b45565b60206040518083038186803b158015611baf57600080fd5b505afa158015611bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be791906159b9565b8154600181018355600092835260209092209091015550505050565b611c0c33612812565b611c135750565b611c2581670de0b6b3a7640000615be4565b60285550565b600e54604051632c02ef0360e11b81526000916001600160a01b031690635805de069061107e908590600401615aa4565b6015546001600160a01b03163314611c7357505050565b6000838152604e60205260409081902090516307d5656960e31b81528291906001600160a01b03831690633eab2b4890611b979088908890600401615b45565b600f546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611ce4908590600401615aa4565b60206040518083038186803b158015611cfc57600080fd5b505afa158015611d10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8791906159b9565b611d3d33612812565b611d445750565b603355565b6055602052816000526040600020818154811061111157600080fd5b600080611d71836148a9565b90506001600160a01b038116610f8757600080fd5b6015546001600160a01b03163314611d9d57505050565b6000838152605360205260409081902090516308a1f67f60e01b81528291906001600160a01b038316906308a1f67f90611b979088908890600401615b45565b60006001600160a01b038216611df257600080fd5b506001600160a01b031660009081526003602052604090205490565b6052602052816000526040600020818154811061111157600080fd5b611e326148c4565b611e3c60006148e0565b565b60006037546036546029546111c59190615be4565b600b54604051631ba10c1560e31b81526001600160a01b039091169063dd0860a890611e83903390600401615aa4565b60206040518083038186803b158015611e9b57600080fd5b505afa158015611eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed39190615760565b611f235760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e65722063616e20736574204164647265737365732e000000604482015260640160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152603e602052604090205460ff1615611fc5576001600160a01b0381166000908152605f6020526040812054603d805491929091611f92908490615c03565b90915550506001600160a01b0381166000908152605f60209081526040808320839055603e9091529020805460ff191690555b611fce81611c2b565b1561202c57611fdc81611ddd565b603d6000828254611fed9190615baa565b90915550611ffc905081611ddd565b6001600160a01b0382166000908152605f6020908152604080832093909355603e905220805460ff191660011790555b50565b61203833612812565b61203f5750565b61205181670de0b6b3a7640000615be4565b60295550565b6006602052816000526040600020818154811061111157600080fd5b61207c33612812565b6120835750565b603155565b604160205260009081526040902080546113ee90615c46565b60006035546034546029546111c59190615be4565b6051602052816000526040600020818154811061111157600080fd5b6015546001600160a01b031633146120e957505050565b60008381526051602052604090819020905163895694bf60e01b81528291906001600160a01b0383169063895694bf90611b979088908890600401615b45565b6000602f54602e546028546111c59190615be4565b600a546001600160a01b031690565b604f602052816000526040600020818154811061111157600080fd5b61217233612812565b6121795750565b602c55565b606060018054610f9c90615c46565b6015546001600160a01b031633146121a457612264565b6121af838383613b73565b6001600160a01b0384166000908152600660209081526040822080546001810182559083529120018390556121e384611ddd565b6121fd57600880549060006121f783615c81565b91905055505b6122078484613b28565b6001600160a01b038416600090815260076020526040902054612240576001600160a01b03841660009081526007602052604090208390555b61224984611c2b565b1561226457603d805490600061225e83615c81565b91905055505b50505050565b60006111cf60395490565b6015546001600160a01b0316331461228c57505050565b6000838152604f60205260409081902090516348edffbd60e11b81528291906001600160a01b038316906391dbff7a90611b979088908890600401615b45565b611631338383614932565b6122e033612812565b6122e75750565b603755565b6015546001600160a01b0316331461230357505050565b6000838152605260205260409081902090516370c7038360e01b81528291906001600160a01b038316906370c7038390611b979088908890600401615b45565b600d5460408051636190c9d560e01b815290516000926001600160a01b031691636190c9d5916004808301926020929190829003018186803b15801561238857600080fd5b505afa15801561239c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cf91906159b9565b60006033546032546029546111c59190615be4565b6123de33611b23565b158061240457506123ee81611d65565b6001600160a01b0316336001600160a01b031614155b1561240e57612264565b6025546028546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916124439133913091600401615ab8565b602060405180830381600087803b15801561245d57600080fd5b505af1158015612471573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124959190615760565b50600f546029546040516323b872dd60e01b81526001600160a01b03909216916323b872dd916124cb9133913091600401615ab8565b602060405180830381600087803b1580156124e557600080fd5b505af11580156124f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251d9190615760565b506000818152603f60209081526040909120855161253d9287019061545f565b506000818152604060208181529120845161255a9286019061545f565b506000818152604160209081526040909120835161257a9285019061545f565b506125836145bf565b61258b6146e0565b612593614792565b60008181526057602052604081205461226491839190614844565b6125b83383613978565b6125c157600080fd5b612264848484846149be565b6015546001600160a01b031633146125e457505050565b600083815260556020526040908190209051630c69bbfb60e31b81528291906001600160a01b0383169063634ddfd890611b979088908890600401615b45565b61262d33612812565b6126345750565b602b55565b6060610f87826149de565b6015546001600160a01b0316331461265b57505050565b60008381526056602052604090819020905163eb20feab60e01b81528291906001600160a01b0383169063eb20feab90611b979088908890600401615b45565b6054602052816000526040600020818154811061111157600080fd5b6126c033612812565b6126c75750565b602e55565b6000602d54602c546028546111c59190615be4565b6126ea33612812565b6126f15750565b602d55565b603954811115612704575050565b61270d81611d65565b6001600160a01b0316336001600160a01b03161415801561273957506015546001600160a01b03163314155b15612742575050565b6001600160a01b03821660009081526007602052604090819020805490839055905133907ff1920cbfe18dff4155b1e46e979d6d82313c39f04760c14fbb8f37a21b36e912906127959084908690615b45565b60405180910390a2505050565b6015546001600160a01b031633146127b957505050565b6000838152605060205260409081902090516314bf03b160e11b81528291906001600160a01b0383169063297e076290611b979088908890600401615b45565b603f60205260009081526040902080546113ee90615c46565b600b54604051631ba10c1560e31b81526000916001600160a01b03169063dd0860a89061107e908590600401615aa4565b604060208190526000918252902080546113ee90615c46565b61286533612812565b61286c5750565b603055565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6056602052816000526040600020818154811061111157600080fd5b6128c433612812565b6128cb5750565b603255565b6128d86148c4565b6001600160a01b0381166128eb57600080fd5b61202c816148e0565b600b54604080516307578a5960e41b815290516000926001600160a01b031691637578a590916004808301926020929190829003018186803b15801561293957600080fd5b505afa15801561294d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297191906159b9565b905080600c5414156129805750565b600c819055600b5460408051635f9ca54b60e11b815290516001600160a01b039092169163bf394a9691600480820192602092909190829003018186803b1580156129ca57600080fd5b505afa1580156129de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a029190615573565b600d80546001600160a01b0319166001600160a01b03928316179055600b5460408051632d311b9f60e11b815290519190921691635a62373e916004808301926020929190829003018186803b158015612a5b57600080fd5b505afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190615573565b600e80546001600160a01b0319166001600160a01b03928316179055600b5460408051632fc69b7560e21b81529051919092169163bf1a6dd4916004808301926020929190829003018186803b158015612aec57600080fd5b505afa158015612b00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b249190615573565b600f80546001600160a01b0319166001600160a01b03928316179055600b5460408051635d27d82160e01b815290519190921691635d27d821916004808301926020929190829003018186803b158015612b7d57600080fd5b505afa158015612b91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb59190615573565b601080546001600160a01b0319166001600160a01b03928316179055600b5460408051633739851960e21b81529051919092169163dce61464916004808301926020929190829003018186803b158015612c0e57600080fd5b505afa158015612c22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c469190615573565b601180546001600160a01b0319166001600160a01b03928316179055600b546040805163fdf6c44360e01b81529051919092169163fdf6c443916004808301926020929190829003018186803b158015612c9f57600080fd5b505afa158015612cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd79190615573565b601280546001600160a01b0319166001600160a01b03928316179055600b54604080516353962e4560e11b81529051919092169163a72c5c8a916004808301926020929190829003018186803b158015612d3057600080fd5b505afa158015612d44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d689190615573565b601380546001600160a01b0319166001600160a01b03928316179055600b546040805163e93b941b60e01b81529051919092169163e93b941b916004808301926020929190829003018186803b158015612dc157600080fd5b505afa158015612dd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df99190615573565b601480546001600160a01b0319166001600160a01b03928316179055600b5460408051631567ac7560e31b81529051919092169163ab3d63a8916004808301926020929190829003018186803b158015612e5257600080fd5b505afa158015612e66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8a9190615573565b601580546001600160a01b0319166001600160a01b03928316179055600b5460408051635ffb42d960e11b81529051919092169163bff685b2916004808301926020929190829003018186803b158015612ee357600080fd5b505afa158015612ef7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1b9190615573565b601680546001600160a01b0319166001600160a01b03928316179055600b5460408051630bbc5d7d60e31b815290519190921691635de2ebe8916004808301926020929190829003018186803b158015612f7457600080fd5b505afa158015612f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fac9190615573565b601780546001600160a01b0319166001600160a01b03928316179055600b546040805163c586261f60e01b81529051919092169163c586261f916004808301926020929190829003018186803b15801561300557600080fd5b505afa158015613019573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303d9190615573565b601880546001600160a01b0319166001600160a01b03928316179055600b5460408051637abb1b7360e01b815290519190921691637abb1b73916004808301926020929190829003018186803b15801561309657600080fd5b505afa1580156130aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130ce9190615573565b601980546001600160a01b0319166001600160a01b03928316179055600b5460408051633dd5259d60e01b815290519190921691633dd5259d916004808301926020929190829003018186803b15801561312757600080fd5b505afa15801561313b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315f9190615573565b601a80546001600160a01b0319166001600160a01b03928316179055600b546040805163967db45360e01b81529051919092169163967db453916004808301926020929190829003018186803b1580156131b857600080fd5b505afa1580156131cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f09190615573565b601b80546001600160a01b0319166001600160a01b03928316179055600b54604080516310fced2960e01b8152905191909216916310fced29916004808301926020929190829003018186803b15801561324957600080fd5b505afa15801561325d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132819190615573565b601c80546001600160a01b0319166001600160a01b03928316179055600b5460408051634cfd0abf60e11b8152905191909216916399fa157e916004808301926020929190829003018186803b1580156132da57600080fd5b505afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190615573565b601d80546001600160a01b0319166001600160a01b03928316179055600b5460408051636164467360e01b8152905191909216916361644673916004808301926020929190829003018186803b15801561336b57600080fd5b505afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a39190615573565b601e80546001600160a01b0319166001600160a01b03928316179055600b5460408051631b7410a160e31b81529051919092169163dba08508916004808301926020929190829003018186803b1580156133fc57600080fd5b505afa158015613410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134349190615573565b601f80546001600160a01b0319166001600160a01b03928316179055600b546040805163484de36360e11b81529051919092169163909bc6c6916004808301926020929190829003018186803b15801561348d57600080fd5b505afa1580156134a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c59190615573565b602080546001600160a01b0319166001600160a01b03928316178155600b5460408051633310a27960e01b815290519190931692633310a279926004808301939192829003018186803b15801561351b57600080fd5b505afa15801561352f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135539190615573565b602180546001600160a01b0319166001600160a01b03928316179055600b5460408051633c9d0ac360e11b81529051919092169163793a1586916004808301926020929190829003018186803b1580156135ac57600080fd5b505afa1580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190615573565b602280546001600160a01b0319166001600160a01b03928316179055600b546040805163063606b760e51b81529051919092169163c6c0d6e0916004808301926020929190829003018186803b15801561363d57600080fd5b505afa158015613651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136759190615573565b602380546001600160a01b0319166001600160a01b03928316179055600b5460408051630ffbb3e960e21b815290519190921691633feecfa4916004808301926020929190829003018186803b1580156136ce57600080fd5b505afa1580156136e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137069190615573565b602480546001600160a01b0319166001600160a01b03928316179055600b546040805163c27ce47960e01b81529051919092169163c27ce479916004808301926020929190829003018186803b15801561375f57600080fd5b505afa158015613773573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137979190615573565b602580546001600160a01b0319166001600160a01b03928316179055600b54604080516389a3027160e01b8152905191909216916389a30271916004808301926020929190829003018186803b1580156137f057600080fd5b505afa158015613804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138289190615573565b602680546001600160a01b0319166001600160a01b03928316179055600b546040805163c54e44eb60e01b81529051919092169163c54e44eb916004808301926020929190829003018186803b15801561388157600080fd5b505afa158015613895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b99190615573565b602780546001600160a01b0319166001600160a01b039290921691909117905550565b5490565b80546001019055565b6001600160a01b03163b151590565b61390181614ae7565b61202c57600080fd5b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061393f82611d65565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061398483611d65565b9050806001600160a01b0316846001600160a01b031614806139ab57506139ab8185612871565b806139cf5750836001600160a01b03166139c4846110ce565b6001600160a01b0316145b949350505050565b826001600160a01b03166139ea82611d65565b6001600160a01b0316146139fd57600080fd5b6001600160a01b038216613a1057600080fd5b826001600160a01b0316613a2382611d65565b6001600160a01b031614613a3657600080fd5b600081815260046020526040902080546001600160a01b0319169055613a5c8184614b04565b6001600160a01b038316600090815260036020526040902080546000190190819055158015613a8d57506000600854115b15613a9d57600880546000190190555b613aa78183614cc5565b6001600160a01b038216600090815260036020526040902054613ace576008805460010190555b6001600160a01b03808316600081815260036020908152604080832080546001019055858352600290915280822080546001600160a01b03191684179055518493871691600080516020615d6a83398151915291a4505050565b611631828260405180602001604052806000815250614d19565b613b4b82614ae7565b613b5457600080fd5b600082815260096020908152604090912082516111819284019061545f565b604051636d3a6ba160e11b815260048101849052829081906001600160a01b0382169063da74d7429060240160006040518083038186803b158015613bb757600080fd5b505afa158015613bcb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613bf391908101906157b7565b6000868152603f602090815260409091208251613c16939192919091019061545f565b506040516370d5517d60e11b8152600481018690526001600160a01b0383169063e1aaa2fa9060240160006040518083038186803b158015613c5757600080fd5b505afa158015613c6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c9391908101906157b7565b60008681526040602081815291208251613cb3939192919091019061545f565b506040516382d706ad60e01b8152600481018690526001600160a01b038316906382d706ad9060240160006040518083038186803b158015613cf457600080fd5b505afa158015613d08573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d3091908101906157b7565b60008681526041602090815260409091208251613d53939192919091019061545f565b50604051632994eff760e21b8152600481018690526001600160a01b0383169063a653bfdc9060240160206040518083038186803b158015613d9457600080fd5b505afa158015613da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dcc91906159b9565b600086815260426020526040908190209190915551633c1bd08360e01b8152600481018690526001600160a01b03831690633c1bd0839060240160006040518083038186803b158015613e1e57600080fd5b505afa158015613e32573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613e5a91908101906157b7565b60008681526043602090815260409091208251613e7d939192919091019061545f565b50604051632355e47760e21b8152600481018690526001600160a01b03831690638d5791dc9060240160206040518083038186803b158015613ebe57600080fd5b505afa158015613ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef691906159b9565b6000868152605760205260409081902091909155516336b6593d60e21b8152600481018690526001600160a01b0383169063dad964f49060240160206040518083038186803b158015613f4857600080fd5b505afa158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f8091906159b9565b600086815260446020526040908190209190915551634883705f60e11b8152600481018690526001600160a01b03831690639106e0be9060240160206040518083038186803b158015613fd257600080fd5b505afa158015613fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061400a91906159b9565b60008681526045602052604090819020919091555163235e704b60e11b8152600481018690526001600160a01b038316906346bce0969060240160206040518083038186803b15801561405c57600080fd5b505afa158015614070573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061409491906159b9565b60008681526046602052604090819020919091555163110f02a960e21b8152600481018690526001600160a01b0383169063443c0aa49060240160206040518083038186803b1580156140e657600080fd5b505afa1580156140fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061411e91906159b9565b600086815260476020526040908190209190915551635616f32560e01b8152600481018690526001600160a01b03831690635616f3259060240160206040518083038186803b15801561417057600080fd5b505afa158015614184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a891906159b9565b60008681526048602052604090819020919091555163706e2dfd60e01b8152600481018690526001600160a01b0383169063706e2dfd9060240160206040518083038186803b1580156141fa57600080fd5b505afa15801561420e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061423291906159b9565b6000868152604960205260409081902091909155516381c9db7760e01b8152600481018690526001600160a01b038316906381c9db779060240160206040518083038186803b15801561428457600080fd5b505afa158015614298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142bc91906159b9565b6000868152604a602052604090819020919091555163e1cdc6f760e01b8152600481018690526001600160a01b0383169063e1cdc6f79060240160206040518083038186803b15801561430e57600080fd5b505afa158015614322573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061434691906159b9565b6000868152604b602052604090819020919091555163053294b760e41b8152600481018690526001600160a01b038316906353294b709060240160206040518083038186803b15801561439857600080fd5b505afa1580156143ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d091906159b9565b6000868152604c60205260409081902091909155516365cf916360e11b8152600481018690526001600160a01b0383169063cb9f22c69060240160206040518083038186803b15801561442257600080fd5b505afa158015614436573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061445a91906159b9565b6000868152604d6020526040902055600483141561451357604051633b36259960e21b8152600481018690526001600160a01b0383169063ecd896649060240160206040518083038186803b1580156144b257600080fd5b505afa1580156144c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144ea91906159b9565b60008681526058602052604081208054909190614508908490615baa565b909155506145b89050565b82600b14156145b857604051633549d94b60e11b8152600481018690526001600160a01b03821690636a93b2969060240160206040518083038186803b15801561455c57600080fd5b505afa158015614570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061459491906159b9565b600086815260586020526040812080549091906145b2908490615baa565b90915550505b5050505050565b600f546019546001600160a01b039182169163a9059cbb91166145e06123c0565b6040518363ffffffff1660e01b81526004016145fd929190615b19565b602060405180830381600087803b15801561461757600080fd5b505af115801561462b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061464f9190615760565b506025546018546001600160a01b039182169163a9059cbb91166146716126cc565b6040518363ffffffff1660e01b815260040161468e929190615b19565b602060405180830381600087803b1580156146a857600080fd5b505af11580156146bc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202c9190615760565b600f54601b546001600160a01b039182169163a9059cbb91166147016120a1565b6040518363ffffffff1660e01b815260040161471e929190615b19565b602060405180830381600087803b15801561473857600080fd5b505af115801561474c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147709190615760565b50602554601a546001600160a01b039182169163a9059cbb9116614671612129565b600f54601d546001600160a01b039182169163a9059cbb91166147b3611e3e565b6040518363ffffffff1660e01b81526004016147d0929190615b19565b602060405180830381600087803b1580156147ea57600080fd5b505af11580156147fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148229190615760565b50602554601c546001600160a01b039182169163a9059cbb91166146716111b0565b60008080614850611635565b9050845b6009831015611af057841561486e5761486e838888614d39565b61487781611d65565b93506148848482846111d4565b60009687526057602052604090962054959050826148a181615c81565b935050614854565b6000908152600260205260409020546001600160a01b031690565b336148cd61213e565b6001600160a01b031614611e3c57600080fd5b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561495157600080fd5b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6149c98484846139d7565b6149d5848484846150e6565b61226457600080fd5b60606149e9826138f8565b60008281526009602052604081208054614a0290615c46565b80601f0160208091040260200160405190810160405280929190818152602001828054614a2e90615c46565b8015614a7b5780601f10614a5057610100808354040283529160200191614a7b565b820191906000526020600020905b815481529060010190602001808311614a5e57829003601f168201915b505050505090506000614a9960408051602081019091526000815290565b9050805160001415614aac575092915050565b815115614ade578082604051602001614ac6929190615a75565b60405160208183030381529060405292505050919050565b6139cf846151e7565b600080614af3836148a9565b6001600160a01b0316141592915050565b60005b6001600160a01b0382166000908152600660205260409020805484919083908110614b3457614b34615cc8565b906000526020600020015414614b565780614b4e81615c81565b915050614b07565b6001600160a01b038216600090815260036020526040902054614b7b90600190615c03565b811015614c14576001600160a01b0382166000908152600660205260409020614ba5826001615baa565b81548110614bb557614bb5615cc8565b906000526020600020015460066000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110614bf657614bf6615cc8565b60009182526020909120015580614c0c81615c81565b915050614b56565b6001600160a01b0382166000908152600660205260409020805480614c3b57614c3b615cb2565b6000828152602080822083016000199081018390559092019092556001600160a01b0384168252600790526040902054831415611181576001600160a01b03821660009081526006602052604081208054909190614c9b57614c9b615cc8565b60009182526020808320909101546001600160a01b03851683526007909152604090912055505050565b6001600160a01b0381166000818152600660209081526040808320805460018101825590845282842001869055928252600790522054611631576001600160a01b0316600090815260076020526040902055565b614d23838361525b565b614d3060008484846150e6565b61118157600080fd5b82614d9e576000818152604460205260408120805491614d5883615c81565b90915550506000818152604d60205260408120805491614d7783615c81565b90915550506000908152604e60209081526040822080546001810182559083529120015550565b8260011415614e07576000818152604560205260408120805491614dc183615c81565b90915550506000818152604d60205260408120805491614de083615c81565b90915550506000908152604f60209081526040822080546001810182559083529120015550565b8260021415614e70576000818152604660205260408120805491614e2a83615c81565b90915550506000818152604d60205260408120805491614e4983615c81565b90915550506000908152605060209081526040822080546001810182559083529120015550565b8260031415614ed9576000818152604760205260408120805491614e9383615c81565b90915550506000818152604d60205260408120805491614eb283615c81565b90915550506000908152605160209081526040822080546001810182559083529120015550565b8260041415614f42576000818152604860205260408120805491614efc83615c81565b90915550506000818152604d60205260408120805491614f1b83615c81565b90915550506000908152605260209081526040822080546001810182559083529120015550565b8260051415614fab576000818152604960205260408120805491614f6583615c81565b90915550506000818152604d60205260408120805491614f8483615c81565b90915550506000908152605360209081526040822080546001810182559083529120015550565b8260061415615014576000818152604a60205260408120805491614fce83615c81565b90915550506000818152604d60205260408120805491614fed83615c81565b90915550506000908152605460209081526040822080546001810182559083529120015550565b826007141561507d576000818152604b6020526040812080549161503783615c81565b90915550506000818152604d6020526040812080549161505683615c81565b90915550506000908152605560209081526040822080546001810182559083529120015550565b8260081415611181576000818152604c602052604081208054916150a083615c81565b90915550506000818152604d602052604081208054916150bf83615c81565b90915550506000908152605660209081526040822080546001810182559083529120015550565b60006150fa846001600160a01b03166138e9565b156151dc57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290615131903390899088908890600401615adc565b602060405180830381600087803b15801561514b57600080fd5b505af192505050801561517b575060408051601f3d908101601f191682019092526151789181019061579a565b60015b6151c2573d8080156151a9576040519150601f19603f3d011682016040523d82523d6000602084013e6151ae565b606091505b5080516151ba57600080fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506139cf565b506001949350505050565b60606151f2826138f8565b600061520960408051602081019091526000815290565b905060008151116152295760405180602001604052806000815250615254565b80615233846152ed565b604051602001615244929190615a75565b6040516020818303038152906040525b9392505050565b6001600160a01b03821661526e57600080fd5b61527781614ae7565b1561528157600080fd5b61528a81614ae7565b1561529457600080fd5b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020615d6a833981519152908290a45050565b606060006152fa83615389565b60010190506000816001600160401b0381111561531957615319615cde565b6040519080825280601f01601f191660200182016040528015615343576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461537c57615381565b61534d565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106153c85772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106153f2576904ee2d6d415b85acef8160201b830492506020015b662386f26fc10000831061541057662386f26fc10000830492506010015b6305f5e1008310615428576305f5e100830492506008015b612710831061543c57612710830492506004015b6064831061544e576064830492506002015b600a8310610f875760010192915050565b82805461546b90615c46565b90600052602060002090601f01602090048101928261548d57600085556154d3565b82601f106154a657805160ff19168380011785556154d3565b828001600101855582156154d3579182015b828111156154d35782518255916020019190600101906154b8565b506154df9291506154e3565b5090565b5b808211156154df57600081556001016154e4565b600061550b61550684615b83565b615b53565b905082815283838301111561551f57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261554757600080fd5b615254838335602085016154f8565b60006020828403121561556857600080fd5b813561525481615cf4565b60006020828403121561558557600080fd5b815161525481615cf4565b600080604083850312156155a357600080fd5b82356155ae81615cf4565b915060208301356155be81615cf4565b809150509250929050565b6000806000606084860312156155de57600080fd5b83356155e981615cf4565b925060208401356155f981615cf4565b929592945050506040919091013590565b6000806000806080858703121561562057600080fd5b843561562b81615cf4565b9350602085013561563b81615cf4565b92506040850135915060608501356001600160401b0381111561565d57600080fd5b8501601f8101871361566e57600080fd5b61567d878235602084016154f8565b91505092959194509250565b6000806040838503121561569c57600080fd5b82356156a781615cf4565b915060208301356155be81615d09565b600080604083850312156156ca57600080fd5b82356156d581615cf4565b946020939093013593505050565b600080600080608085870312156156f957600080fd5b843561570481615cf4565b935060208501359250604085013561571b81615cf4565b9396929550929360600135925050565b60008060006060848603121561574057600080fd5b833561574b81615cf4565b95602085013595506040909401359392505050565b60006020828403121561577257600080fd5b815161525481615d09565b60006020828403121561578f57600080fd5b813561525481615d17565b6000602082840312156157ac57600080fd5b815161525481615d17565b6000602082840312156157c957600080fd5b81516001600160401b038111156157df57600080fd5b8201601f810184136157f057600080fd5b80516157fe61550682615b83565b81815285602083850101111561581357600080fd5b615824826020830160208601615c1a565b95945050505050565b600080600080600080600060e0888a03121561584857600080fd5b87356001600160401b038082111561585f57600080fd5b61586b8b838c01615536565b985060208a013591508082111561588157600080fd5b61588d8b838c01615536565b975060408a01359150808211156158a357600080fd5b6158af8b838c01615536565b965060608a01359150808211156158c557600080fd5b6158d18b838c01615536565b955060808a01359150808211156158e757600080fd5b506158f48a828b01615536565b93505060a0880135915060c0880135905092959891949750929550565b6000806000806080858703121561592757600080fd5b84356001600160401b038082111561593e57600080fd5b61594a88838901615536565b9550602087013591508082111561596057600080fd5b61596c88838901615536565b9450604087013591508082111561598257600080fd5b5061598f87828801615536565b949793965093946060013593505050565b6000602082840312156159b257600080fd5b5035919050565b6000602082840312156159cb57600080fd5b5051919050565b600080604083850312156159e557600080fd5b50508035926020909101359150565b600080600060608486031215615a0957600080fd5b83359250602084013591506040840135615a2281615cf4565b809150509250925092565b60008151808452615a45816020860160208601615c1a565b601f01601f19169290920160200192915050565b60008251615a6b818460208701615c1a565b9190910192915050565b60008351615a87818460208801615c1a565b835190830190615a9b818360208801615c1a565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b0f90830184615a2d565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b6020815260006152546020830184615a2d565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715615b7b57615b7b615cde565b604052919050565b60006001600160401b03821115615b9c57615b9c615cde565b50601f01601f191660200190565b60008219821115615bbd57615bbd615c9c565b500190565b600082615bdf57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615615bfe57615bfe615c9c565b500290565b600082821015615c1557615c15615c9c565b500390565b60005b83811015615c35578181015183820152602001615c1d565b838111156122645750506000910152565b600181811c90821680615c5a57607f821691505b60208210811415615c7b57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615c9557615c95615c9c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461202c57600080fd5b801515811461202c57600080fd5b6001600160e01b03198116811461202c57600080fdfe697066733a2f2f516d5269314476674475367a414a7770625552474e424251544d38325a434e5a4179546b454172624b5a4b6d31552f302e6a736f6eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220868a46f6c1de263806a361876d5eb1974f5af51d22d0d93939ad068c17c9105e64736f6c63430008070033
Deployed Bytecode Sourcemap
178059:29235:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;198842:144;;;;;;:::i;:::-;;:::i;:::-;;31079:321;;;;;;:::i;:::-;;:::i;:::-;;;15849:14:1;;15842:22;15824:41;;15812:2;15797:18;31079:321:0;;;;;;;;178785:51;;;;;;;;;17279:25:1;;;17267:2;17252:18;178785:51:0;17133:177:1;31982:100:0;;;:::i;:::-;;;;;;;:::i;192142:219::-;;;;;;:::i;:::-;;:::i;33418:187::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;182656:61::-;;;;;;:::i;:::-;;:::i;33075:277::-;;;;;;:::i;:::-;;:::i;197014:177::-;;;;;;:::i;:::-;;:::i;30695:28::-;;;;;;183133:43;;;;;;196842:164;;;;;;:::i;:::-;;:::i;195630:217::-;;;:::i;178468:54::-;;;;;;201462:879;;;;;;:::i;:::-;;:::i;34184:286::-;;;;;;:::i;:::-;;:::i;182448:63::-;;;;;;:::i;:::-;;:::i;193178:151::-;;;:::i;179665:30::-;;;;;;181251:51;;;;;;:::i;:::-;;:::i;182307:63::-;;;;;;:::i;:::-;;:::i;192369:801::-;;;:::i;195855:137::-;;;:::i;34541:185::-;;;;;;:::i;:::-;;:::i;178734:44::-;;;;;;181643:66;;;;;;:::i;:::-;;;;;;;;;;;;;;188914:2322;;;;;;:::i;:::-;;:::i;181569:67::-;;;;;;:::i;:::-;;;;;;;;;;;;;;199467:171;;;;;;:::i;:::-;;:::i;178964:49::-;;;;;;198201:187;;;;;;:::i;:::-;;:::i;193947:132::-;;;;;;:::i;:::-;;:::i;187519:454::-;;;;;;:::i;:::-;;:::i;199174:139::-;;;;;;:::i;:::-;;:::i;182009:66::-;;;;;;:::i;:::-;;;;;;;;;;;;;;181716;;;;;;:::i;:::-;;;;;;;;;;;;;;194087:123;;;;;;:::i;:::-;;:::i;184756:454::-;;;;;;:::i;:::-;;:::i;179702:37::-;;;;;;65027:28;;;;;-1:-1:-1;;;;;65027:28:0;;;194240:118;;;;;;:::i;:::-;;:::i;183248:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;196635:169;;;;;;:::i;:::-;;:::i;182794:63::-;;;;;;:::i;:::-;;:::i;31704:211::-;;;;;;:::i;:::-;;:::i;187063:448::-;;;;;;:::i;:::-;;:::i;183367:56::-;;;;;;:::i;:::-;;;;;;;;;;;;;;181789:65;;;;;;:::i;:::-;;;;;;;;;;;;;;31464:178;;;;;;:::i;:::-;;:::i;182587:62::-;;;;;;:::i;:::-;;:::i;50585:103::-;;;:::i;194984:204::-;;;:::i;64929:31::-;;;;;;183448:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;68215:171;;;;;;:::i;:::-;;:::i;193337:469::-;;;;;;:::i;:::-;;:::i;178401:58::-;;;;;;199321:138;;;;;;:::i;:::-;;:::i;183307:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;181861:67;;;;;;:::i;:::-;;;;;;;;;;;;;;30585:48;;;;;;:::i;:::-;;:::i;198617:189::-;;;;;;:::i;:::-;;:::i;181121:56::-;;;;;;:::i;:::-;;:::i;180921:29::-;;;;;;194775:201;;;:::i;182518:62::-;;;;;;:::i;:::-;;:::i;66002:17::-;;;;;-1:-1:-1;;;;;66002:17:0;;;179501:53;;;;;;186145:451;;;;;;:::i;:::-;;:::i;195408:214::-;;;:::i;182965:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;178143:31;;;;;;50000:87;;;:::i;181494:68::-;;;;;;:::i;:::-;;;;;;;;;;;;;;182377:64;;;;;;:::i;:::-;;:::i;197622:166::-;;;;;;:::i;:::-;;:::i;178900:55::-;;;;;;32151:104;;;:::i;184106:642::-;;;;;;:::i;:::-;;:::i;194463:107::-;;;:::i;179020:56::-;;;;;;185218:457;;;;;;:::i;:::-;;:::i;178294:41::-;;;;;;33677:180;;;;;;:::i;:::-;;:::i;178254:33::-;;;;;;180856:58;;;;;;:::i;:::-;;;;;;;;;;;;;;181184:60;;;;;;:::i;:::-;;;;;;;;;;;;;;197403:179;;;;;;:::i;:::-;;:::i;65164:33::-;;;;;-1:-1:-1;;;;;65164:33:0;;;178344:50;;;;;;186604:451;;;;;;:::i;:::-;;:::i;194366:89::-;;;:::i;194578:189::-;;;:::i;191244:890::-;;;;;;:::i;:::-;;:::i;34797:273::-;;;;;;:::i;:::-;;:::i;187981:454::-;;;;;;:::i;:::-;;:::i;30640:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;65972:23;;;;;-1:-1:-1;;;;;65972:23:0;;;198994:157;;;;;;:::i;:::-;;:::i;178181:36::-;;;;;;66026:17;;;;;-1:-1:-1;;;;;66026:17:0;;;180957:44;;;;;;:::i;:::-;;;;;;;;;;;;;;;;207120:171;;;;;;:::i;:::-;;:::i;188443:451::-;;;;;;:::i;:::-;;:::i;182724:63::-;;;;;;:::i;:::-;;:::i;182084:62::-;;;;;;:::i;:::-;;;;;;;;;;;;;;198019:174;;;;;;:::i;:::-;;:::i;178600:55::-;;;;;;195196:204;;;:::i;183511:57::-;;;;;;:::i;:::-;;;;;;;;;;;;;;197796:179;;;;;;:::i;:::-;;:::i;196022:397::-;;;;;;:::i;:::-;;:::i;185683:454::-;;;;;;:::i;:::-;;:::i;181008:46::-;;;;;;:::i;:::-;;:::i;181420:67::-;;;;;;:::i;:::-;;;;;;;;;;;;;;193830:109;;;;;;:::i;:::-;;:::i;181061:53::-;;;;;;:::i;:::-;;:::i;181935:67::-;;;;;;:::i;:::-;;;;;;;;;;;;;;183183:58;;;;;;:::i;:::-;;;;;;;;;;;;;;198433:176;;;;;;:::i;:::-;;:::i;33928:189::-;;;;;;:::i;:::-;;:::i;182864:62::-;;;;;;:::i;:::-;;:::i;178529:::-;;;;;;183042:63;;;;;;:::i;:::-;;;;;;;;;;;;;;196473:154;;;;;;:::i;:::-;;:::i;50836:159::-;;;;;;:::i;:::-;;:::i;178662:63::-;;;;;;66052:2155;;;:::i;178845:48::-;;;;;;198842:144;198917:19;198925:10;198917:7;:19::i;:::-;198912:33;;198842:144;:::o;198912:33::-;198955:14;:23;198842:144::o;31079:321::-;31197:4;-1:-1:-1;;;;;;31234:40:0;;-1:-1:-1;;;31234:40:0;;:105;;-1:-1:-1;;;;;;;31291:48:0;;-1:-1:-1;;;31291:48:0;31234:105;:158;;;-1:-1:-1;;;;;;;;;;29839:40:0;;;31356:36;31214:178;31079:321;-1:-1:-1;;31079:321:0:o;31982:100::-;32036:13;32069:5;32062:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31982:100;:::o;192142:219::-;192205:4;192242:29;192254:16;192262:7;192254;:16::i;192242:29::-;:111;;;-1:-1:-1;192288:13:0;;-1:-1:-1;;;;;192288:13:0;:31;192320:16;192328:7;192320;:16::i;:::-;192351:1;192338:10;:8;:10::i;:::-;:14;;;;:::i;:::-;192288:65;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;33418:187::-;33510:7;33530:23;33545:7;33530:14;:23::i;:::-;-1:-1:-1;33573:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;33573:24:0;;33418:187::o;182656:61::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;33075:277::-;33156:13;33172:23;33187:7;33172:14;:23::i;:::-;33156:39;;33220:5;-1:-1:-1;;;;;33214:11:0;:2;-1:-1:-1;;;;;33214:11:0;;;33206:20;;;;;;26114:10;-1:-1:-1;;;;;33247:21:0;;;;:62;;-1:-1:-1;33272:37:0;33289:5;26114:10;33928:189;:::i;33272:37::-;33239:71;;;;;;33323:21;33332:2;33336:7;33323:8;:21::i;:::-;33145:207;33075:277;;:::o;197014:177::-;197098:19;197106:10;197098:7;:19::i;:::-;197093:33;;197014:177;:::o;197093:33::-;197138:36;:45;197014:177::o;196842:164::-;196920:19;196928:10;196920:7;:19::i;:::-;196915:33;;196842:164;:::o;196915:33::-;196960:29;:38;196842:164::o;195630:217::-;195694:7;195796:43;;195743:36;;195735:5;;:44;;;;:::i;:::-;195734:105;;;;:::i;:::-;195714:125;;195630:217;:::o;201462:879::-;201597:7;201617:260;201696:34;;201638:42;;;;:32;:42;;;;;;:92;:122;;;;-1:-1:-1;201747:13:0;;;201638:122;201617:260;;;201798:27;;;;:17;:27;;;;;;;;201848:17;201798:27;201848:7;:17::i;:::-;201840:25;;201617:260;;;201889:10;;:41;;-1:-1:-1;;;201889:41:0;;-1:-1:-1;;;;;201889:10:0;;;;:19;;:41;;201909:5;;201916:13;;201889:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;201943:30:0;;;;;;:23;:30;;;;;:47;;201977:13;;201943:30;:47;;201977:13;;201943:47;:::i;:::-;;;;-1:-1:-1;;202001:38:0;;;;:28;:38;;;;;:55;;202043:13;;202001:38;:55;;202043:13;;202001:55;:::i;:::-;;;;;;;;202099:13;202067:28;;:45;;;;;;;:::i;:::-;;;;;;;;202260:15;202240:5;-1:-1:-1;;;;;202154:132:0;;202189:8;202212:13;202154:132;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;202306:27:0;;;;:17;:27;;;;;;;201462:879;-1:-1:-1;201462:879:0:o;34184:286::-;34379:41;26114:10;34412:7;34379:18;:41::i;:::-;34371:50;;;;;;34434:28;34444:4;34450:2;34454:7;34434:9;:28::i;182448:63::-;;;;;;;;;;;;;;;;;;;;193178:151;193244:5;;-1:-1:-1;;;;;193244:5:0;193222:10;:28;193218:41;;193178:151::o;193218:41::-;193307:14;;193269:23;:35;193293:10;:8;:10::i;:::-;193269:35;;;;;;;;;;;-1:-1:-1;193269:35:0;:52;193178:151::o;181251:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;182307:63::-;;;;;;;;;;;;;;;;;;;;192369:801;192442:16;;-1:-1:-1;;;;;192442:16:0;192420:10;:39;192416:52;;192369:801::o;192416:52::-;192644:7;;:26;;;-1:-1:-1;;;192644:26:0;;;;192617:24;;-1:-1:-1;;;;;192644:7:0;;:24;;:26;;;;;;;;;;;;;;:7;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;192617:53;;192686:9;192681:482;192705:1;192701;:5;192681:482;;;192728:30;192738:16;192756:1;192728:9;:30::i;:::-;192773:128;192804:1;192773:128;;;;;;;;;;;;;;;;;:12;:128::i;:::-;192941:26;;192918:54;;192930:1;;-1:-1:-1;;;;;192941:26:0;192970:1;192918:11;:54::i;:::-;-1:-1:-1;;;;;192989:29:0;;;;;;;:11;:29;;;;;;;;:37;;;;;;;;;;;;;;;;;;193075:26;;:76;;-1:-1:-1;;;193075:76:0;;;;;17279:25:1;;;193075:26:0;;;:73;;17252:18:1;;193075:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;193041:31;;;;:28;:31;;;;;:110;193070:1;192708:3;193070:1;192708:3;:::i;:::-;;;;192681:482;;;;192405:765;192369:801::o;195855:137::-;195909:7;195963:21;;195945:14;;195937:5;;:22;;;;:::i;34541:185::-;34679:39;34696:4;34702:2;34706:7;34679:39;;;;;;;;;;;;:16;:39::i;188914:2322::-;189184:21;189194:10;189184:9;:21::i;:::-;189179:35;;189207:7;;189179:35;189252:18;189273:13;:82;189301:8;;;;;;;;;-1:-1:-1;;;;;189301:8:0;-1:-1:-1;;;;;189301:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;189273:82:0;;;;;;;;;;;;-1:-1:-1;189273:82:0;;;-1:-1:-1;189372:9:0;;189368:59;;-1:-1:-1;189411:4:0;189368:59;189443:15;189439:62;;-1:-1:-1;189488:1:0;189439:62;189534:9;25531:14;189521:10;:32;189513:41;;;;;;189567:10;;189618:5;;189567:57;;-1:-1:-1;;;189567:57:0;;-1:-1:-1;;;;;189567:10:0;;;;:23;;:57;;189591:10;;189611:4;;189567:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;189635:4:0;;189680:10;;189635:56;;-1:-1:-1;;;189635:56:0;;-1:-1:-1;;;;;189635:4:0;;;;:17;;:56;;189653:10;;189673:4;;189635:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;189704:31;189724:10;189704:19;:31::i;:::-;189776:1;189752:21;189762:10;189752:9;:21::i;:::-;:25;189748:103;;;189794:8;;189827:10;189794:8;189813:25;;;:13;:25;;;;;;;;189794:45;;-1:-1:-1;;;189794:45:0;;-1:-1:-1;;;;;189794:8:0;;;;:18;;:45;;;;17279:25:1;;;17267:2;17252:18;;17133:177;189794:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;189748:103;189884:15;189902:19;:9;25531:14;;25439:114;189902:19;189884:37;;189932:21;:9;25650:19;;25668:1;25650:19;;;25561:127;189932:21;189964:30;189974:10;189986:7;189964:9;:30::i;:::-;190027:27;190040:7;190049:4;190027:12;:27::i;:::-;190106:21;;;;:12;:21;;;;;;;;:29;;;;;;;;:::i;:::-;-1:-1:-1;190146:28:0;;;;:19;:28;;;;;;:43;;;;;;;;:::i;:::-;-1:-1:-1;190200:31:0;;;;:22;:31;;;;;;;;:48;;;;;;;;:::i;:::-;-1:-1:-1;190259:26:0;;;;:17;:26;;;;;;;;:39;;;190311:17;:26;;;;;:38;;;;;;;;:::i;:::-;-1:-1:-1;190360:34:0;;;;:25;:34;;;;;;;;:47;;;190438:10;190424:25;;:13;:25;;;;;;190420:98;;190485:10;190471:25;;;;:13;:25;;;;;:35;;;190420:98;190542:10;190530:23;;;;:11;:23;;;;;;;:37;;;;;;;;;;;;;;;;190612:23;:21;:23::i;:::-;190646:27;:25;:27::i;:::-;190684:28;:26;:28::i;:::-;190778:38;190790:7;190799:10;190811:4;190778:11;:38::i;:::-;190942:21;:33;190964:10;:8;:10::i;:::-;190942:33;;;;;;;;;;;;:35;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;191025:10:0;191015:21;;;;:9;:21;;;;;;;;191010:113;;191063:10;191053:21;;;;:9;:21;;;;;:28;;-1:-1:-1;;191053:28:0;191077:4;191053:28;;;191096:13;:15;;;;;;:::i;:::-;;;;;;191010:113;191163:65;;191217:10;;191163:65;;191201:14;;191163:65;:::i;:::-;;;;;;;;191194:5;191163:65;;;;;;:::i;:::-;;;;;;;;;191168:7;191177:15;191163:65;;;;;;;:::i;:::-;;;;;;;;189168:2068;;188914:2322;;;;;;;;:::o;199467:171::-;199549:19;199557:10;199549:7;:19::i;:::-;199544:33;;199467:171;:::o;199544:33::-;199587:34;:43;199467:171::o;198201:187::-;198291:19;198299:10;198291:7;:19::i;:::-;198286:33;;198201:187;:::o;198286:33::-;198329:42;:51;198201:187::o;193947:132::-;194027:13;;194003:4;;-1:-1:-1;;;;;194027:13:0;:24;194052:6;194060:10;:8;:10::i;187519:454::-;187691:16;;-1:-1:-1;;;;;187691:16:0;187669:10;:39;187665:52;;187519:454;;;:::o;187665:52::-;187729:34;187839:35;;;:26;:35;;;;;;;187894:60;;-1:-1:-1;;;187894:60:0;;187797:18;;187839:35;-1:-1:-1;;;;;187894:44:0;;;;;:60;;187866:7;;187948:5;;187894:60;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;187839:126;;;;;;;-1:-1:-1;187839:126:0;;;;;;;;;;;-1:-1:-1;;;;187519:454:0:o;199174:139::-;199241:19;199249:10;199241:7;:19::i;:::-;199236:33;;199174:139;:::o;199236:33::-;199287:18;:6;199297:7;199287:18;:::i;:::-;199279:5;:26;-1:-1:-1;199174:139:0:o;194087:123::-;194169:13;;:33;;-1:-1:-1;;;194169:33:0;;194145:4;;-1:-1:-1;;;;;194169:13:0;;:25;;:33;;194195:6;;194169:33;;;:::i;184756:454::-;184928:16;;-1:-1:-1;;;;;184928:16:0;184906:10;:39;184902:52;;184756:454;;;:::o;184902:52::-;184966:34;185076:35;;;:26;:35;;;;;;;185131:60;;-1:-1:-1;;;185131:60:0;;185034:18;;185076:35;-1:-1:-1;;;;;185131:44:0;;;;;:60;;185103:7;;185185:5;;185131:60;;;:::i;194240:118::-;194328:4;;:22;;-1:-1:-1;;;194328:22:0;;194301:7;;-1:-1:-1;;;;;194328:4:0;;:14;;:22;;194343:6;;194328:22;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;196635:169::-;196715:19;196723:10;196715:7;:19::i;:::-;196710:33;;196635:169;:::o;196710:33::-;196755:32;:41;196635:169::o;182794:63::-;;;;;;;;;;;;;;;;;;;;31704:211;31792:7;31812:13;31828:17;31837:7;31828:8;:17::i;:::-;31812:33;-1:-1:-1;;;;;;31864:19:0;;31856:28;;;;;187063:448;187233:16;;-1:-1:-1;;;;;187233:16:0;187211:10;:39;187207:52;;187063:448;;;:::o;187207:52::-;187271:34;187381:33;;;:24;:33;;;;;;;187434:58;;-1:-1:-1;;;187434:58:0;;187339:18;;187381:33;-1:-1:-1;;;;;187434:42:0;;;;;:58;;187406:7;;187486:5;;187434:58;;;:::i;31464:178::-;31552:7;-1:-1:-1;;;;;31580:19:0;;31572:28;;;;;;-1:-1:-1;;;;;;31618:16:0;;;;;:9;:16;;;;;;;31464:178::o;182587:62::-;;;;;;;;;;;;;;;;;;;;50585:103;49893:13;:11;:13::i;:::-;50650:30:::1;50677:1;50650:18;:30::i;:::-;50585:103::o:0;194984:204::-;195042:7;195143:37;;195096:30;;195083:10;;:43;;;;:::i;68215:171::-;68279:7;;:27;;-1:-1:-1;;;68279:27:0;;-1:-1:-1;;;;;68279:7:0;;;;:15;;:27;;68295:10;;68279:27;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68271:69;;;;-1:-1:-1;;;68271:69:0;;16977:2:1;68271:69:0;;;16959:21:1;17016:2;16996:18;;;16989:30;17055:31;17035:18;;;17028:59;17104:18;;68271:69:0;;;;;;;;68351:7;:27;;-1:-1:-1;;;;;;68351:27:0;-1:-1:-1;;;;;68351:27:0;;;;;;;;;;68215:171::o;193337:469::-;-1:-1:-1;;;;;193404:20:0;;;;;;:12;:20;;;;;;;;193400:193;;;-1:-1:-1;;;;;193459:30:0;;;;;;:22;:30;;;;;;193441:14;:48;;193459:30;;193441:14;;:48;;193459:30;;193441:48;:::i;:::-;;;;-1:-1:-1;;;;;;;193504:30:0;;193537:1;193504:30;;;:22;:30;;;;;;;;:34;;;193553:12;:20;;;;;:28;;-1:-1:-1;;193553:28:0;;;193400:193;193609:19;193621:6;193609:11;:19::i;:::-;193605:194;;;193663:17;193673:6;193663:9;:17::i;:::-;193645:14;;:35;;;;;;;:::i;:::-;;;;-1:-1:-1;193728:17:0;;-1:-1:-1;193738:6:0;193728:9;:17::i;:::-;-1:-1:-1;;;;;193695:30:0;;;;;;:22;:30;;;;;;;;:50;;;;193760:12;:20;;;:27;;-1:-1:-1;;193760:27:0;193783:4;193760:27;;;193605:194;193337:469;:::o;199321:138::-;199382:19;199390:10;199382:7;:19::i;:::-;199377:33;;199321:138;:::o;199377:33::-;199433:18;:6;199443:7;199433:18;:::i;:::-;199420:10;:31;-1:-1:-1;199321:138:0:o;30585:48::-;;;;;;;;;;;;;;;;;;;;198617:189;198708:19;198716:10;198708:7;:19::i;:::-;198703:33;;198617:189;:::o;198703:33::-;198746:43;:52;198617:189::o;181121:56::-;;;;;;;;;;;;;;;;:::i;194775:201::-;194832:7;194932:36;;194886:29;;194873:10;;:42;;;;:::i;182518:62::-;;;;;;;;;;;;;;;;;;;;186145:451;186316:16;;-1:-1:-1;;;;;186316:16:0;186294:10;:39;186290:52;;186145:451;;;:::o;186290:52::-;186354:34;186464;;;:25;:34;;;;;;;186518:59;;-1:-1:-1;;;186518:59:0;;186422:18;;186464:34;-1:-1:-1;;;;;186518:43:0;;;;;:59;;186490:7;;186571:5;;186518:59;;;:::i;195408:214::-;195471:7;195572:42;;195520:35;;195512:5;;:43;;;;:::i;50000:87::-;50073:6;;-1:-1:-1;;;;;50073:6:0;;50000:87::o;182377:64::-;;;;;;;;;;;;;;;;;;;;197622:166;197702:19;197710:10;197702:7;:19::i;:::-;197697:33;;197622:166;:::o;197697:33::-;197740:31;:40;197622:166::o;32151:104::-;32207:13;32240:7;32233:14;;;;;:::i;184106:642::-;184301:16;;-1:-1:-1;;;;;184301:16:0;184279:10;:39;184275:52;;184320:7;;184275:52;184339:56;184351:7;184360:18;184380:14;184339:11;:56::i;:::-;-1:-1:-1;;;;;184408:19:0;;;;;;:11;:19;;;;;;;:33;;;;;;;;;;;;;;;;184456:17;184420:6;184456:9;:17::i;:::-;184452:70;;184495:13;:15;;;:13;:15;;;:::i;:::-;;;;;;184452:70;184532:26;184542:6;184550:7;184532:9;:26::i;:::-;-1:-1:-1;;;;;184575:21:0;;;;;;:13;:21;;;;;;184571:90;;-1:-1:-1;;;;;184618:21:0;;;;;;:13;:21;;;;;:31;;;184571:90;184677:19;184689:6;184677:11;:19::i;:::-;184673:68;;;184713:14;:16;;;:14;:16;;;:::i;:::-;;;;;;184673:68;184106:642;;;;:::o;194463:107::-;194516:7;194543:19;:9;25531:14;;25439:114;185218:457;185391:16;;-1:-1:-1;;;;;185391:16:0;185369:10;:39;185365:52;;185218:457;;;:::o;185365:52::-;185429:34;185539:36;;;:27;:36;;;;;;;185595:61;;-1:-1:-1;;;185595:61:0;;185497:18;;185539:36;-1:-1:-1;;;;;185595:45:0;;;;;:61;;185567:7;;185650:5;;185595:61;;;:::i;33677:180::-;33797:52;26114:10;33830:8;33840;33797:18;:52::i;197403:179::-;197488:19;197496:10;197488:7;:19::i;:::-;197483:33;;197403:179;:::o;197483:33::-;197528:37;:46;197403:179::o;186604:451::-;186775:16;;-1:-1:-1;;;;;186775:16:0;186753:10;:39;186749:52;;186604:451;;;:::o;186749:52::-;186813:34;186923;;;:25;:34;;;;;;;186977:59;;-1:-1:-1;;;186977:59:0;;186881:18;;186923:34;-1:-1:-1;;;;;186977:43:0;;;;;:59;;186949:7;;187030:5;;186977:59;;;:::i;194366:89::-;194434:5;;:13;;;-1:-1:-1;;;194434:13:0;;;;194407:7;;-1:-1:-1;;;;;194434:5:0;;:11;;:13;;;;;;;;;;;;;;:5;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;194578:189::-;194631:7;194727:32;;194685:25;;194672:10;;:38;;;;:::i;191244:890::-;191426:21;191436:10;191426:9;:21::i;:::-;191425:22;:57;;;;191465:17;191473:8;191465:7;:17::i;:::-;-1:-1:-1;;;;;191451:31:0;:10;-1:-1:-1;;;;;191451:31:0;;;191425:57;191421:70;;;191484:7;;191421:70;191503:10;;191554:5;;191503:57;;-1:-1:-1;;;191503:57:0;;-1:-1:-1;;;;;191503:10:0;;;;:23;;:57;;191527:10;;191547:4;;191503:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;191571:4:0;;191616:10;;191571:56;;-1:-1:-1;;;191571:56:0;;-1:-1:-1;;;;;191571:4:0;;;;:17;;:56;;191589:10;;191609:4;;191571:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;191667:22:0;;;;:12;:22;;;;;;;;:30;;;;;;;;:::i;:::-;-1:-1:-1;191708:29:0;;;;:19;:29;;;;;;:44;;;;;;;;:::i;:::-;-1:-1:-1;191763:32:0;;;;:22;:32;;;;;;;;:49;;;;;;;;:::i;:::-;;191857:23;:21;:23::i;:::-;191891:27;:25;:27::i;:::-;191929:28;:26;:28::i;:::-;192043:27;;;;:17;:27;;;;;;192021:57;;192033:8;;192043:27;192021:11;:57::i;34797:273::-;34971:41;26114:10;35004:7;34971:18;:41::i;:::-;34963:50;;;;;;35024:38;35038:4;35044:2;35048:7;35057:4;35024:13;:38::i;187981:454::-;188153:16;;-1:-1:-1;;;;;188153:16:0;188131:10;:39;188127:52;;187981:454;;;:::o;188127:52::-;188191:34;188301:35;;;:26;:35;;;;;;;188356:60;;-1:-1:-1;;;188356:60:0;;188259:18;;188301:35;-1:-1:-1;;;;;188356:44:0;;;;;:60;;188328:7;;188410:5;;188356:60;;;:::i;198994:157::-;199075:19;199083:10;199075:7;:19::i;:::-;199070:33;;198994:157;:::o;199070:33::-;199113:21;:30;198994:157::o;207120:171::-;207227:13;207260:23;207275:7;207260:14;:23::i;188443:451::-;188614:16;;-1:-1:-1;;;;;188614:16:0;188592:10;:39;188588:52;;188443:451;;;:::o;188588:52::-;188652:34;188762;;;:25;:34;;;;;;;188816:59;;-1:-1:-1;;;188816:59:0;;188720:18;;188762:34;-1:-1:-1;;;;;188816:43:0;;;;;:59;;188788:7;;188869:5;;188816:59;;;:::i;182724:63::-;;;;;;;;;;;;;;;;;;;;198019:174;198103:19;198111:10;198103:7;:19::i;:::-;198098:33;;198019:174;:::o;198098:33::-;198141:35;:44;198019:174::o;195196:204::-;195257:7;195354:38;;195306:31;;195298:5;;:39;;;;:::i;197796:179::-;197882:19;197890:10;197882:7;:19::i;:::-;197877:33;;197796:179;:::o;197877:33::-;197920:38;:47;197796:179::o;196022:397::-;196102:9;25531:14;196097:2;:24;196093:37;;;196022:397;;:::o;196093:37::-;196172:11;196180:2;196172:7;:11::i;:::-;-1:-1:-1;;;;;196158:25:0;:10;-1:-1:-1;;;;;196158:25:0;;;:68;;;;-1:-1:-1;196209:16:0;;-1:-1:-1;;;;;196209:16:0;196187:10;:39;;196158:68;196140:105;;;196022:397;;:::o;196140:105::-;-1:-1:-1;;;;;196285:21:0;;196257:25;196285:21;;;:13;:21;;;;;;;;;196317:26;;;;196361:50;;196377:10;;196361:50;;;;196285:21;;196341:2;;196361:50;:::i;:::-;;;;;;;;196082:337;196022:397;;:::o;185683:454::-;185855:16;;-1:-1:-1;;;;;185855:16:0;185833:10;:39;185829:52;;185683:454;;;:::o;185829:52::-;185893:34;186003:35;;;:26;:35;;;;;;;186058:60;;-1:-1:-1;;;186058:60:0;;185961:18;;186003:35;-1:-1:-1;;;;;186058:44:0;;;;;:60;;186030:7;;186112:5;;186058:60;;;:::i;181008:46::-;;;;;;;;;;;;;;;;:::i;193830:109::-;193908:7;;:23;;-1:-1:-1;;;193908:23:0;;193884:4;;-1:-1:-1;;;;;193908:7:0;;:15;;:23;;193924:6;;193908:23;;;:::i;181061:53::-;;;;;;;;;;;;;;;;;:::i;198433:176::-;198518:19;198526:10;198518:7;:19::i;:::-;198513:33;;198433:176;:::o;198513:33::-;198556:36;:45;198433:176::o;33928:189::-;-1:-1:-1;;;;;34074:25:0;;;34050:4;34074:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;33928:189::o;182864:62::-;;;;;;;;;;;;;;;;;;;;196473:154;196547:19;196555:10;196547:7;:19::i;:::-;196542:33;;196473:154;:::o;196542:33::-;196585:25;:34;196473:154::o;50836:159::-;49893:13;:11;:13::i;:::-;-1:-1:-1;;;;;50925:22:0;::::1;50917:31;;;::::0;::::1;;50959:28;50978:8;50959:18;:28::i;66052:2155::-:0;66123:7;;:22;;;-1:-1:-1;;;66123:22:0;;;;66098;;-1:-1:-1;;;;;66123:7:0;;:20;;:22;;;;;;;;;;;;;;:7;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66098:47;;66176:14;66160:12;;:30;66156:43;;;66192:7;66052:2155::o;66156:43::-;66209:12;:29;;;66263:7;;:15;;;-1:-1:-1;;;66263:15:0;;;;-1:-1:-1;;;;;66263:7:0;;;;:13;;:15;;;;;;;;;;;;;;;:7;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66249:5;:30;;-1:-1:-1;;;;;;66249:30:0;-1:-1:-1;;;;;66249:30:0;;;;;;66311:7;;:23;;;-1:-1:-1;;;66311:23:0;;;;:7;;;;;:21;;:23;;;;;;;;;;;;;;:7;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66290:13;:45;;-1:-1:-1;;;;;;66290:45:0;-1:-1:-1;;;;;66290:45:0;;;;;;66359:7;;:14;;;-1:-1:-1;;;66359:14:0;;;;:7;;;;;:12;;:14;;;;;;;;;;;;;;:7;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66346:4;:28;;-1:-1:-1;;;;;;66346:28:0;-1:-1:-1;;;;;66346:28:0;;;;;;66409:7;;:23;;;-1:-1:-1;;;66409:23:0;;;;:7;;;;;:21;;:23;;;;;;;;;;;;;;:7;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66385:13;:48;;-1:-1:-1;;;;;;66385:48:0;-1:-1:-1;;;;;66385:48:0;;;;;;66468:7;;:23;;;-1:-1:-1;;;66468:23:0;;;;:7;;;;;:21;;:23;;;;;;;;;;;;;;:7;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66444:13;:48;;-1:-1:-1;;;;;;66444:48:0;-1:-1:-1;;;;;66444:48:0;;;;;;66525:7;;:21;;;-1:-1:-1;;;66525:21:0;;;;:7;;;;;:19;;:21;;;;;;;;;;;;;;:7;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66503:11;:44;;-1:-1:-1;;;;;;66503:44:0;-1:-1:-1;;;;;66503:44:0;;;;;;66575:7;;:19;;;-1:-1:-1;;;66575:19:0;;;;:7;;;;;:17;;:19;;;;;;;;;;;;;;:7;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66558:9;:37;;-1:-1:-1;;;;;;66558:37:0;-1:-1:-1;;;;;66558:37:0;;;;;;66629:7;;:18;;;-1:-1:-1;;;66629:18:0;;;;:7;;;;;:16;;:18;;;;;;;;;;;;;;:7;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66606:8;:42;;-1:-1:-1;;;;;;66606:42:0;-1:-1:-1;;;;;66606:42:0;;;;;;66688:7;;:26;;;-1:-1:-1;;;66688:26:0;;;;:7;;;;;:24;;:26;;;;;;;;;;;;;;:7;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66659:16;:56;;-1:-1:-1;;;;;;66659:56:0;-1:-1:-1;;;;;66659:56:0;;;;;;66763:7;;:30;;;-1:-1:-1;;;66763:30:0;;;;:7;;;;;:28;;:30;;;;;;;;;;;;;;:7;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66726:20;:68;;-1:-1:-1;;;;;;66726:68:0;-1:-1:-1;;;;;66726:68:0;;;;;;66839:7;;:30;;;-1:-1:-1;;;66839:30:0;;;;:7;;;;;:28;;:30;;;;;;;;;;;;;;:7;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66805:20;:65;;-1:-1:-1;;;;;;66805:65:0;-1:-1:-1;;;;;66805:65:0;;;;;;66917:7;;:31;;;-1:-1:-1;;;66917:31:0;;;;:7;;;;;:29;;:31;;;;;;;;;;;;;;:7;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66881:21;:68;;-1:-1:-1;;;;;;66881:68:0;-1:-1:-1;;;;;66881:68:0;;;;;;66990:7;;:25;;;-1:-1:-1;;;66990:25:0;;;;:7;;;;;:23;;:25;;;;;;;;;;;;;;:7;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66960:15;:56;;-1:-1:-1;;;;;;66960:56:0;-1:-1:-1;;;;;66960:56:0;;;;;;67085:7;;:35;;;-1:-1:-1;;;67085:35:0;;;;:7;;;;;:33;;:35;;;;;;;;;;;;;;:7;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67027:25;:104;;-1:-1:-1;;;;;;67027:104:0;-1:-1:-1;;;;;67027:104:0;;;;;;67180:7;;:29;;;-1:-1:-1;;;67180:29:0;;;;:7;;;;;:27;;:29;;;;;;;;;;;;;;:7;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67142:19;:68;;-1:-1:-1;;;;;;67142:68:0;-1:-1:-1;;;;;67142:68:0;;;;;;67281:7;;:36;;;-1:-1:-1;;;67281:36:0;;;;:7;;;;;:34;;:36;;;;;;;;;;;;;;:7;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67221:26;:107;;-1:-1:-1;;;;;;67221:107:0;-1:-1:-1;;;;;67221:107:0;;;;;;67379:7;;:30;;;-1:-1:-1;;;67379:30:0;;;;:7;;;;;:28;;:30;;;;;;;;;;;;;;:7;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67339:20;:71;;-1:-1:-1;;;;;;67339:71:0;-1:-1:-1;;;;;67339:71:0;;;;;;67483:7;;:39;;;-1:-1:-1;;;67483:39:0;;;;:7;;;;;:37;;:39;;;;;;;;;;;;;;:7;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67421:29;:112;;-1:-1:-1;;;;;;67421:112:0;-1:-1:-1;;;;;67421:112:0;;;;;;67600:7;;:36;;;-1:-1:-1;;;67600:36:0;;;;:7;;;;;:34;;:36;;;;;;;;;;;;;;:7;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67544:26;:103;;-1:-1:-1;;;;;;67544:103:0;-1:-1:-1;;;;;67544:103:0;;;;;;67720:7;;:34;;;-1:-1:-1;;;67720:34:0;;;;:7;;;;;:32;;:34;;;;;;;;;;;;;;:7;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67658:24;:107;;-1:-1:-1;;;;;;67658:107:0;-1:-1:-1;;;;;67658:107:0;;;;;;67812:7;;:31;;;-1:-1:-1;;;67812:31:0;;;;:7;;;;;:29;;:31;;;;;67658:24;;67812:31;;;;;:7;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67778:21;:66;;-1:-1:-1;;;;;;67778:66:0;-1:-1:-1;;;;;67778:66:0;;;;;;67890:7;;:27;;;-1:-1:-1;;;67890:27:0;;;;:7;;;;;:25;;:27;;;;;;;;;;;;;;:7;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67855:17;:63;;-1:-1:-1;;;;;;67855:63:0;-1:-1:-1;;;;;67855:63:0;;;;;;67967:7;;:30;;;-1:-1:-1;;;67967:30:0;;;;:7;;;;;:28;;:30;;;;;;;;;;;;;;:7;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67929:20;:69;;-1:-1:-1;;;;;;67929:69:0;-1:-1:-1;;;;;67929:69:0;;;;;;68042:7;;:25;;;-1:-1:-1;;;68042:25:0;;;;:7;;;;;:23;;:25;;;;;;;;;;;;;;:7;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68009:15;:59;;-1:-1:-1;;;;;;68009:59:0;-1:-1:-1;;;;;68009:59:0;;;;;;68100:7;;:20;;;-1:-1:-1;;;68100:20:0;;;;:7;;;;;:18;;:20;;;;;;;;;;;;;;:7;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68081:10;:40;;-1:-1:-1;;;;;;68081:40:0;-1:-1:-1;;;;;68081:40:0;;;;;;68145:7;;:14;;;-1:-1:-1;;;68145:14:0;;;;:7;;;;;:12;;:14;;;;;;;;;;;;;;:7;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68132:4;:28;;-1:-1:-1;;;;;;68132:28:0;-1:-1:-1;;;;;68132:28:0;;;;;;68184:7;;:14;;;-1:-1:-1;;;68184:14:0;;;;:7;;;;;:12;;:14;;;;;;;;;;;;;;:7;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68171:4;:28;;-1:-1:-1;;;;;;68171:28:0;-1:-1:-1;;;;;68171:28:0;;;;;;;;;;-1:-1:-1;66052:2155:0:o;25439:114::-;25531:14;;25439:114::o;25561:127::-;25650:19;;25668:1;25650:19;;;25561:127::o;1070:326::-;-1:-1:-1;;;;;1365:19:0;;:23;;;1070:326::o;43874:107::-;43956:16;43964:7;43956;:16::i;:::-;43948:25;;;;;43182:174;43257:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;43257:29:0;-1:-1:-1;;;;;43257:29:0;;;;;;;;:24;;43311:23;43257:24;43311:14;:23::i;:::-;-1:-1:-1;;;;;43302:46:0;;;;;;;;;;;43182:174;;:::o;37049:315::-;37167:4;37184:13;37200:23;37215:7;37200:14;:23::i;:::-;37184:39;;37253:5;-1:-1:-1;;;;;37242:16:0;:7;-1:-1:-1;;;;;37242:16:0;;:65;;;;37275:32;37292:5;37299:7;37275:16;:32::i;:::-;37242:113;;;;37348:7;-1:-1:-1;;;;;37324:31:0;:20;37336:7;37324:11;:20::i;:::-;-1:-1:-1;;;;;37324:31:0;;37242:113;37234:122;37049:315;-1:-1:-1;;;;37049:315:0:o;41616:1447::-;41775:4;-1:-1:-1;;;;;41748:31:0;:23;41763:7;41748:14;:23::i;:::-;-1:-1:-1;;;;;41748:31:0;;41740:40;;;;;;-1:-1:-1;;;;;41799:16:0;;41791:25;;;;;;41998:4;-1:-1:-1;;;;;41971:31:0;:23;41986:7;41971:14;:23::i;:::-;-1:-1:-1;;;;;41971:31:0;;41963:40;;;;;;42075:24;;;;:15;:24;;;;;42068:31;;-1:-1:-1;;;;;;42068:31:0;;;42553:41;42091:7;42589:4;42553:26;:41::i;:::-;-1:-1:-1;;;;;42609:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;42609:20:0;;;;;42650;:41;;;;;42690:1;42674:13;;:17;42650:41;42646:97;;;42712:13;:15;;-1:-1:-1;;42712:15:0;;;42646:97;42759:36;42783:7;42792:2;42759:23;:36::i;:::-;-1:-1:-1;;;;;42814:13:0;;;;;;:9;:13;;;;;;42810:74;;42853:13;:15;;;;;;42810:74;-1:-1:-1;;;;;42898:13:0;;;;;;;:9;:13;;;;;;;;:18;;42915:1;42898:18;;;42938:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;42938:21:0;;;;;42977:27;42946:7;;42977:27;;;-1:-1:-1;;;;;;;;;;;42977:27:0;;33145:207;33075:277;;:::o;37706:110::-;37782:26;37792:2;37796:7;37782:26;;;;;;;;;;;;:9;:26::i;48796:192::-;48921:16;48929:7;48921;:16::i;:::-;48913:25;;;;;;48949:19;;;;:10;:19;;;;;;;;:31;;;;;;;;:::i;204426:2477::-;204799:37;;-1:-1:-1;;;204799:37:0;;;;;17279:25:1;;;204604:18:0;;;;-1:-1:-1;;;;;204799:30:0;;;;;17252:18:1;;204799:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;204799:37:0;;;;;;;;;;;;:::i;:::-;204777:19;;;;:12;:19;;;;;;;;:59;;;;:19;;:59;;;;;;:::i;:::-;-1:-1:-1;204876:68:0;;-1:-1:-1;;;204876:68:0;;;;;17279:25:1;;;-1:-1:-1;;;;;204876:37:0;;;;;17252:18:1;;204876:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;204876:68:0;;;;;;;;;;;;:::i;:::-;204847:26;;;;:19;:26;;;;;;:97;;;;:26;;:97;;;;;;:::i;:::-;-1:-1:-1;204987:61:0;;-1:-1:-1;;;204987:61:0;;;;;17279:25:1;;;-1:-1:-1;;;;;204987:54:0;;;;;17252:18:1;;204987:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;204987:61:0;;;;;;;;;;;;:::i;:::-;204955:29;;;;:22;:29;;;;;;;;:93;;;;:29;;:93;;;;;;:::i;:::-;-1:-1:-1;205094:64:0;;-1:-1:-1;;;205094:64:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205094:57:0;;;;;17252:18:1;;205094:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205059:32;;;;:25;:32;;;;;;;:99;;;;205196:42;-1:-1:-1;;;205196:42:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205196:35:0;;;;;17252:18:1;;205196:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;205196:42:0;;;;;;;;;;;;:::i;:::-;205169:24;;;;:17;:24;;;;;;;;:69;;;;:24;;:69;;;;;;:::i;:::-;-1:-1:-1;205276:42:0;;-1:-1:-1;;;205276:42:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205276:35:0;;;;;17252:18:1;;205276:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205249:24;;;;:17;:24;;;;;;;:69;;;;205396:71;-1:-1:-1;;;205396:71:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205396:64:0;;;;;17252:18:1;;205396:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205354:39;;;;:32;:39;;;;;;;:113;;;;205521:72;-1:-1:-1;;;205521:72:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205521:65:0;;;;;17252:18:1;;205521:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205478:40;;;;:33;:40;;;;;;;:115;;;;205646:71;-1:-1:-1;;;205646:71:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205646:64:0;;;;;17252:18:1;;205646:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205604:39;;;;:32;:39;;;;;;;:113;;;;205769:70;-1:-1:-1;;;205769:70:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205769:63:0;;;;;17252:18:1;;205769:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205728:38;;;;:31;:38;;;;;;;:111;;;;205891:70;-1:-1:-1;;;205891:70:0;;;;;17279:25:1;;;-1:-1:-1;;;;;205891:63:0;;;;;17252:18:1;;205891:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205850:38;;;;:31;:38;;;;;;;:111;;;;206012:69;-1:-1:-1;;;206012:69:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206012:62:0;;;;;17252:18:1;;206012:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;205972:37;;;;:30;:37;;;;;;;:109;;;;206134:71;-1:-1:-1;;;206134:71:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206134:64:0;;;;;17252:18:1;;206134:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206092:39;;;;:32;:39;;;;;;;:113;;;;206258:71;-1:-1:-1;;;206258:71:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206258:64:0;;;;;17252:18:1;;206258:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206216:39;;;;:32;:39;;;;;;;:113;;;;206381:70;-1:-1:-1;;;206381:70:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206381:63:0;;;;;17252:18:1;;206381:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206340:38;;;;:31;:38;;;;;;;:111;;;;206501:66;-1:-1:-1;;;206501:66:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206501:59:0;;;;;17252:18:1;;206501:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206464:34;;;;:27;:34;;;;;:103;206593:1;206584:10;;206580:316;;;206650:71;;-1:-1:-1;;;206650:71:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206650:64:0;;;;;17252:18:1;;206650:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206611:35;;;;:28;:35;;;;;:110;;:35;;;:110;;;;;:::i;:::-;;;;-1:-1:-1;206580:316:0;;-1:-1:-1;206580:316:0;;206743:5;206752:2;206743:11;206739:157;;;206810:74;;-1:-1:-1;;;206810:74:0;;;;;17279:25:1;;;-1:-1:-1;;;;;206810:67:0;;;;;17252:18:1;;206810:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206771:35;;;;:28;:35;;;;;:113;;:35;;;:113;;;;;:::i;:::-;;;;-1:-1:-1;;206739:157:0;204547:2356;;204426:2477;;;:::o;199672:256::-;199724:4;;199746:15;;-1:-1:-1;;;;;199724:4:0;;;;:13;;199746:15;199764:22;:20;:22::i;:::-;199724:63;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;199800:10:0;;199842:21;;-1:-1:-1;;;;;199800:10:0;;;;:19;;199842:21;199879:30;:28;:30::i;:::-;199800:120;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;199936:274::-;199992:4;;200014:19;;-1:-1:-1;;;;;199992:4:0;;;;:13;;200014:19;200036:26;:24;:26::i;:::-;199992:71;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;200076:10:0;;200118:25;;-1:-1:-1;;;;;200076:10:0;;;;:19;;200118:25;200159:32;:30;:32::i;200218:316::-;200275:4;;200311:20;;-1:-1:-1;;;;;200275:4:0;;;;:13;;200311:20;200347:27;:25;:27::i;:::-;200275:110;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;200398:10:0;;200440:26;;-1:-1:-1;;;;;200398:10:0;;;;:19;;200440:26;200482:33;:31;:33::i;200575:684::-;200700:13;;;200772:23;:21;:23::i;:::-;200748:47;-1:-1:-1;200837:10:0;200858:394;200869:1;200865;:5;200858:394;;;200891:7;200887:51;;;200900:38;200915:1;200918:7;200927:10;200900:14;:38::i;:::-;200963:29;200971:20;200963:7;:29::i;:::-;200955:37;;201032:129;201070:5;201094:20;201133:13;201032:19;:129::i;:::-;201191:29;;;;:17;:29;;;;;;;;201009:152;-1:-1:-1;201237:3:0;;;;:::i;:::-;;;;200858:394;;36324:117;36390:7;36417:16;;;:7;:16;;;;;;-1:-1:-1;;;;;36417:16:0;;36324:117::o;50158:96::-;26114:10;50222:7;:5;:7::i;:::-;-1:-1:-1;;;;;50222:23:0;;50214:32;;;;;51155:191;51248:6;;;-1:-1:-1;;;;;51265:17:0;;;-1:-1:-1;;;;;;51265:17:0;;;;;;;51298:40;;51248:6;;;51265:17;51248:6;;51298:40;;51229:16;;51298:40;51218:128;51155:191;:::o;43499:286::-;43654:8;-1:-1:-1;;;;;43645:17:0;:5;-1:-1:-1;;;;;43645:17:0;;;43637:26;;;;;;-1:-1:-1;;;;;43674:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;43674:46:0;;;;;;;;;;43736:41;;15824::1;;;43736::0;;15797:18:1;43736:41:0;;;;;;;43499:286;;;:::o;35951:259::-;36107:28;36117:4;36123:2;36127:7;36107:9;:28::i;:::-;36154:47;36177:4;36183:2;36187:7;36196:4;36154:22;:47::i;:::-;36146:56;;;;;48000:640;48089:13;48115:23;48130:7;48115:14;:23::i;:::-;48151;48177:19;;;:10;:19;;;;;48151:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48207:18;48228:10;32996:9;;;;;;;;;-1:-1:-1;32996:9:0;;;32919:94;48228:10;48207:31;;48320:4;48314:18;48336:1;48314:23;48310:72;;;-1:-1:-1;48361:9:0;48000:640;-1:-1:-1;;48000:640:0:o;48310:72::-;48486:23;;:27;48482:108;;48561:4;48567:9;48544:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;48530:48;;;;48000:640;;;:::o;48482:108::-;48609:23;48624:7;48609:14;:23::i;36754:128::-;36819:4;;36843:17;36852:7;36843:8;:17::i;:::-;-1:-1:-1;;;;;36843:31:0;;;;36754:128;-1:-1:-1;;36754:128:0:o;40794:485::-;40907:9;40933:45;-1:-1:-1;;;;;40940:19:0;;;;;;:11;:19;;;;;:22;;40966:7;;40940:19;40960:1;;40940:22;;;;;;:::i;:::-;;;;;;;;;:33;40933:45;;40975:3;;;;:::i;:::-;;;;40933:45;;;-1:-1:-1;;;;;41004:17:0;;;;;;:9;:17;;;;;;:21;;41024:1;;41004:21;:::i;:::-;40999:1;:27;40991:120;;;-1:-1:-1;;;;;41073:19:0;;;;;;:11;:19;;;;;41093:5;:1;41097;41093:5;:::i;:::-;41073:26;;;;;;;;:::i;:::-;;;;;;;;;41048:11;:19;41060:6;-1:-1:-1;;;;;41048:19:0;-1:-1:-1;;;;;41048:19:0;;;;;;;;;;;;41068:1;41048:22;;;;;;;;:::i;:::-;;;;;;;;;;:51;41028:3;;;;:::i;:::-;;;;40991:120;;;-1:-1:-1;;;;;41123:19:0;;;;;;:11;:19;;;;;:25;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;41123:25:0;;;;;;;;;;;;-1:-1:-1;;;;;41165:21:0;;;;:13;:21;;;;;;:32;;41161:111;;;-1:-1:-1;;;;;41238:19:0;;;;;;:11;:19;;;;;:22;;:19;;;:22;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;41214:21:0;;;;:13;:21;;;;;;;:46;40896:383;40794:485;;:::o;40560:226::-;-1:-1:-1;;;;;40645:19:0;;;;;;:11;:19;;;;;;;;:33;;;;;;;;;;;;;;;;;40693:21;;;:13;:21;;;;40689:90;;-1:-1:-1;;;;;40736:21:0;;;;;:13;:21;;;;;:31;40560:226::o;38043:228::-;38172:18;38178:2;38182:7;38172:5;:18::i;:::-;38209:53;38240:1;38244:2;38248:7;38257:4;38209:22;:53::i;:::-;38201:62;;;;;202349:2069;202437:6;202433:210;;202460:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;202514:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;202563:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;202433:210::-;202659:1;202664;202659:6;202655:212;;;202682:38;;;;:33;:38;;;;;:40;;;;;;:::i;:::-;;;;-1:-1:-1;;202737:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;202786:32:0;;;;:27;:32;;;;;;;:46;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;202655:212::-;202883:1;202888;202883:6;202879:210;;;202906:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;202960:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;203009:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;202879:210::-;203105:1;203110;203105:6;203101:208;;;203128:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;203181:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;203230:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;203101:208::-;203325:1;203330;203325:6;203321:208;;;203348:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;203401:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;203450:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;203321:208::-;203545:1;203550;203545:6;203541:206;;;203568:35;;;;:30;:35;;;;;:37;;;;;;:::i;:::-;;;;-1:-1:-1;;203620:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;203669:29:0;;;;:24;:29;;;;;;;:43;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;203541:206::-;203763:1;203768;203763:6;203759:210;;;203786:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;203840:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;203889:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;203759:210::-;203985:1;203990;203985:6;203981:210;;;204008:37;;;;:32;:37;;;;;:39;;;;;;:::i;:::-;;;;-1:-1:-1;;204062:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;204111:31:0;;;;:26;:31;;;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;203981:210::-;204207:1;204212;204207:6;204203:208;;;204230:36;;;;:31;:36;;;;;:38;;;;;;:::i;:::-;;;;-1:-1:-1;;204283:32:0;;;;:27;:32;;;;;:34;;;;;;:::i;:::-;;;;-1:-1:-1;;204332:30:0;;;;:25;:30;;;;;;;:44;;;;;;;;;;;;;;-1:-1:-1;202349:2069:0:o;44545:934::-;44699:4;44720:15;:2;-1:-1:-1;;;;;44720:13:0;;:15::i;:::-;44716:756;;;44773:174;;-1:-1:-1;;;44773:174:0;;-1:-1:-1;;;;;44773:36:0;;;;;:174;;26114:10;;44867:4;;44894:7;;44924:4;;44773:174;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44773:174:0;;;;;;;;-1:-1:-1;;44773:174:0;;;;;;;;;;;;:::i;:::-;;;44752:665;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45130:13:0;;45126:276;;45173:8;;;45126:276;45352:6;45346:13;45337:6;45333:2;45329:15;45322:38;44752:665;-1:-1:-1;;;;;;45011:51:0;-1:-1:-1;;;45011:51:0;;-1:-1:-1;45004:58:0;;44716:756;-1:-1:-1;45456:4:0;44545:934;;;;;;:::o;32326:344::-;32415:13;32441:23;32456:7;32441:14;:23::i;:::-;32477:21;32501:10;32996:9;;;;;;;;;-1:-1:-1;32996:9:0;;;32919:94;32501:10;32477:34;;32566:1;32548:7;32542:21;:25;:120;;;;;;;;;;;;;;;;;32611:7;32620:18;:7;:16;:18::i;:::-;32594:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;32542:120;32522:140;32326:344;-1:-1:-1;;;32326:344:0:o;38607:829::-;-1:-1:-1;;;;;38687:16:0;;38679:25;;;;;;38724:16;38732:7;38724;:16::i;:::-;38723:17;38715:26;;;;;;38898:16;38906:7;38898;:16::i;:::-;38897:17;38889:26;;;;;;-1:-1:-1;;;;;39257:13:0;;;;;;:9;:13;;;;;;;;:18;;39274:1;39257:18;;;39299:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;39299:21:0;;;;;39338:33;39307:7;;39257:13;;-1:-1:-1;;;;;;;;;;;39338:33:0;39257:13;;39338:33;192681:482;192405:765;192369:801::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;22176:948::-;22229:7;;-1:-1:-1;;;22307:17:0;;22303:106;;-1:-1:-1;;;22345:17:0;;;-1:-1:-1;22391:2:0;22381:12;22303:106;-1:-1:-1;;;22427:5:0;:17;22423:106;;-1:-1:-1;;;22465:17:0;;;-1:-1:-1;22511:2:0;22501:12;22423:106;22556:8;22547:5;:17;22543:106;;22594:8;22585:17;;;-1:-1:-1;22631:2:0;22621:12;22543:106;22676:7;22667:5;:16;22663:103;;22713:7;22704:16;;;-1:-1:-1;22749:1:0;22739:11;22663:103;22793:7;22784:5;:16;22780:103;;22830:7;22821:16;;;-1:-1:-1;22866:1:0;22856:11;22780:103;22910:7;22901:5;:16;22897:103;;22947:7;22938:16;;;-1:-1:-1;22983:1:0;22973:11;22897:103;23027:7;23018:5;:16;23014:68;;23065:1;23055:11;23110:6;22176:948;-1:-1:-1;;22176: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:525::-;3535:6;3543;3551;3559;3612:3;3600:9;3591:7;3587:23;3583:33;3580:53;;;3629:1;3626;3619:12;3580:53;3668:9;3655:23;3687:31;3712:5;3687:31;:::i;:::-;3737:5;-1:-1:-1;3789:2:1;3774:18;;3761:32;;-1:-1:-1;3845:2:1;3830:18;;3817:32;3858:33;3817:32;3858:33;:::i;:::-;3449:525;;;;-1:-1:-1;3910:7:1;;3964:2;3949:18;3936:32;;-1:-1:-1;;3449:525:1:o;3979:383::-;4056:6;4064;4072;4125:2;4113:9;4104:7;4100:23;4096:32;4093:52;;;4141:1;4138;4131:12;4093:52;4180:9;4167:23;4199:31;4224:5;4199:31;:::i;:::-;4249:5;4301:2;4286:18;;4273:32;;-1:-1:-1;4352:2:1;4337:18;;;4324:32;;3979:383;-1:-1:-1;;;3979:383:1:o;4367:245::-;4434:6;4487:2;4475:9;4466:7;4462:23;4458:32;4455:52;;;4503:1;4500;4493:12;4455:52;4535:9;4529:16;4554:28;4576:5;4554:28;:::i;4617:245::-;4675:6;4728:2;4716:9;4707:7;4703:23;4699:32;4696:52;;;4744:1;4741;4734:12;4696:52;4783:9;4770:23;4802:30;4826:5;4802:30;:::i;4867:249::-;4936:6;4989:2;4977:9;4968:7;4964:23;4960:32;4957:52;;;5005:1;5002;4995:12;4957:52;5037:9;5031:16;5056:30;5080:5;5056:30;:::i;9546:635::-;9626:6;9679:2;9667:9;9658:7;9654:23;9650:32;9647:52;;;9695:1;9692;9685:12;9647:52;9722:16;;-1:-1:-1;;;;;9750:30:1;;9747:50;;;9793:1;9790;9783:12;9747:50;9816:22;;9869:4;9861:13;;9857:27;-1:-1:-1;9847:55:1;;9898:1;9895;9888:12;9847:55;9927:2;9921:9;9952:48;9968:31;9996:2;9968:31;:::i;9952:48::-;10023:2;10016:5;10009:17;10063:7;10058:2;10053;10049;10045:11;10041:20;10038:33;10035:53;;;10084:1;10081;10074:12;10035:53;10097:54;10148:2;10143;10136:5;10132:14;10127:2;10123;10119:11;10097:54;:::i;:::-;10170:5;9546:635;-1:-1:-1;;;;;9546:635:1:o;10186:1283::-;10349:6;10357;10365;10373;10381;10389;10397;10450:3;10438:9;10429:7;10425:23;10421:33;10418:53;;;10467:1;10464;10457:12;10418:53;10494:23;;-1:-1:-1;;;;;10566:14:1;;;10563:34;;;10593:1;10590;10583:12;10563:34;10616:50;10658:7;10649:6;10638:9;10634:22;10616:50;:::i;:::-;10606:60;;10719:2;10708:9;10704:18;10691:32;10675:48;;10748:2;10738:8;10735:16;10732:36;;;10764:1;10761;10754:12;10732:36;10787:52;10831:7;10820:8;10809:9;10805:24;10787:52;:::i;:::-;10777:62;;10892:2;10881:9;10877:18;10864:32;10848:48;;10921:2;10911:8;10908:16;10905:36;;;10937:1;10934;10927:12;10905:36;10960:52;11004:7;10993:8;10982:9;10978:24;10960:52;:::i;:::-;10950:62;;11065:2;11054:9;11050:18;11037:32;11021:48;;11094:2;11084:8;11081:16;11078:36;;;11110:1;11107;11100:12;11078:36;11133:52;11177:7;11166:8;11155:9;11151:24;11133:52;:::i;:::-;11123:62;;11238:3;11227:9;11223:19;11210:33;11194:49;;11268:2;11258:8;11255:16;11252:36;;;11284:1;11281;11274:12;11252:36;;11307:52;11351:7;11340:8;11329:9;11325:24;11307:52;:::i;:::-;11297:62;;;11406:3;11395:9;11391:19;11378:33;11368:43;;11458:3;11447:9;11443:19;11430:33;11420:43;;10186:1283;;;;;;;;;;:::o;11474:812::-;11590:6;11598;11606;11614;11667:3;11655:9;11646:7;11642:23;11638:33;11635:53;;;11684:1;11681;11674:12;11635:53;11711:23;;-1:-1:-1;;;;;11783:14:1;;;11780:34;;;11810:1;11807;11800:12;11780:34;11833:50;11875:7;11866:6;11855:9;11851:22;11833:50;:::i;:::-;11823:60;;11936:2;11925:9;11921:18;11908:32;11892:48;;11965:2;11955:8;11952:16;11949:36;;;11981:1;11978;11971:12;11949:36;12004:52;12048:7;12037:8;12026:9;12022:24;12004:52;:::i;:::-;11994:62;;12109:2;12098:9;12094:18;12081:32;12065:48;;12138:2;12128:8;12125:16;12122:36;;;12154:1;12151;12144:12;12122:36;;12177:52;12221:7;12210:8;12199:9;12195:24;12177:52;:::i;:::-;11474:812;;;;-1:-1:-1;12167:62:1;;12276:2;12261:18;12248:32;;-1:-1:-1;;;11474:812:1:o;12291:180::-;12350:6;12403:2;12391:9;12382:7;12378:23;12374:32;12371:52;;;12419:1;12416;12409:12;12371:52;-1:-1:-1;12442:23:1;;12291:180;-1:-1:-1;12291:180:1:o;12476:184::-;12546:6;12599:2;12587:9;12578:7;12574:23;12570:32;12567:52;;;12615:1;12612;12605:12;12567:52;-1:-1:-1;12638:16:1;;12476:184;-1:-1:-1;12476:184:1:o;12665:248::-;12733:6;12741;12794:2;12782:9;12773:7;12769:23;12765:32;12762:52;;;12810:1;12807;12800:12;12762:52;-1:-1:-1;;12833:23:1;;;12903:2;12888:18;;;12875:32;;-1:-1:-1;12665:248:1:o;12918:383::-;12995:6;13003;13011;13064:2;13052:9;13043:7;13039:23;13035:32;13032:52;;;13080:1;13077;13070:12;13032:52;13116:9;13103:23;13093:33;;13173:2;13162:9;13158:18;13145:32;13135:42;;13227:2;13216:9;13212:18;13199:32;13240:31;13265:5;13240:31;:::i;:::-;13290:5;13280:15;;;12918:383;;;;;:::o;13306:257::-;13347:3;13385:5;13379:12;13412:6;13407:3;13400:19;13428:63;13484:6;13477:4;13472:3;13468:14;13461:4;13454:5;13450:16;13428:63;:::i;:::-;13545:2;13524:15;-1:-1:-1;;13520:29:1;13511:39;;;;13552:4;13507:50;;13306:257;-1:-1:-1;;13306:257:1:o;13568:276::-;13699:3;13737:6;13731:13;13753:53;13799:6;13794:3;13787:4;13779:6;13775:17;13753:53;:::i;:::-;13822:16;;;;;13568:276;-1:-1:-1;;13568:276:1:o;13849:470::-;14028:3;14066:6;14060:13;14082:53;14128:6;14123:3;14116:4;14108:6;14104:17;14082:53;:::i;:::-;14198:13;;14157:16;;;;14220:57;14198:13;14157:16;14254:4;14242:17;;14220:57;:::i;:::-;14293:20;;13849:470;-1:-1:-1;;;;13849:470:1:o;14324:203::-;-1:-1:-1;;;;;14488:32:1;;;;14470:51;;14458:2;14443:18;;14324:203::o;14532:375::-;-1:-1:-1;;;;;14790:15:1;;;14772:34;;14842:15;;;;14837:2;14822:18;;14815:43;14889:2;14874:18;;14867:34;;;;14722:2;14707:18;;14532:375::o;14912:488::-;-1:-1:-1;;;;;15181:15:1;;;15163:34;;15233:15;;15228:2;15213:18;;15206:43;15280:2;15265:18;;15258:34;;;15328:3;15323:2;15308:18;;15301:31;;;15106:4;;15349:45;;15374:19;;15366:6;15349:45;:::i;:::-;15341:53;14912:488;-1:-1:-1;;;;;;14912:488:1:o;15405:274::-;-1:-1:-1;;;;;15597:32:1;;;;15579:51;;15661:2;15646:18;;15639:34;15567:2;15552:18;;15405:274::o;16551:219::-;16700:2;16689:9;16682:21;16663:4;16720:44;16760:2;16749:9;16745:18;16737:6;16720:44;:::i;17315:248::-;17489:25;;;17545:2;17530:18;;17523:34;17477:2;17462:18;;17315:248::o;17568:275::-;17639:2;17633:9;17704:2;17685:13;;-1:-1:-1;;17681:27:1;17669:40;;-1:-1:-1;;;;;17724:34:1;;17760:22;;;17721:62;17718:88;;;17786:18;;:::i;:::-;17822:2;17815:22;17568:275;;-1:-1:-1;17568:275:1:o;17848:186::-;17896:4;-1:-1:-1;;;;;17918:30:1;;17915:56;;;17951:18;;:::i;:::-;-1:-1:-1;18017:2:1;17996:15;-1:-1:-1;;17992:29:1;18023:4;17988:40;;17848:186::o;18039:128::-;18079:3;18110:1;18106:6;18103:1;18100:13;18097:39;;;18116:18;;:::i;:::-;-1:-1:-1;18152:9:1;;18039:128::o;18172:217::-;18212:1;18238;18228:132;;18282:10;18277:3;18273:20;18270:1;18263:31;18317:4;18314:1;18307:15;18345:4;18342:1;18335:15;18228:132;-1:-1:-1;18374:9:1;;18172:217::o;18394:168::-;18434:7;18500:1;18496;18492:6;18488:14;18485:1;18482:21;18477:1;18470:9;18463:17;18459:45;18456:71;;;18507:18;;:::i;:::-;-1:-1:-1;18547:9:1;;18394:168::o;18567:125::-;18607:4;18635:1;18632;18629:8;18626:34;;;18640:18;;:::i;:::-;-1:-1:-1;18677:9:1;;18567:125::o;18697:258::-;18769:1;18779:113;18793:6;18790:1;18787:13;18779:113;;;18869:11;;;18863:18;18850:11;;;18843:39;18815:2;18808:10;18779:113;;;18910:6;18907:1;18904:13;18901:48;;;-1:-1:-1;;18945:1:1;18927:16;;18920:27;18697:258::o;18960:380::-;19039:1;19035:12;;;;19082;;;19103:61;;19157:4;19149:6;19145:17;19135:27;;19103:61;19210:2;19202:6;19199:14;19179:18;19176:38;19173:161;;;19256:10;19251:3;19247:20;19244:1;19237:31;19291:4;19288:1;19281:15;19319:4;19316:1;19309:15;19173:161;;18960:380;;;:::o;19345:135::-;19384:3;-1:-1:-1;;19405:17:1;;19402:43;;;19425:18;;:::i;:::-;-1:-1:-1;19472:1:1;19461:13;;19345:135::o;19485:127::-;19546:10;19541:3;19537:20;19534:1;19527:31;19577:4;19574:1;19567:15;19601:4;19598:1;19591:15;19749:127;19810:10;19805:3;19801:20;19798:1;19791:31;19841:4;19838:1;19831:15;19865:4;19862:1;19855:15;19881:127;19942:10;19937:3;19933:20;19930:1;19923:31;19973:4;19970:1;19963:15;19997:4;19994:1;19987:15;20013:127;20074:10;20069:3;20065:20;20062:1;20055:31;20105:4;20102:1;20095:15;20129:4;20126:1;20119:15;20145:131;-1:-1:-1;;;;;20220:31:1;;20210:42;;20200:70;;20266:1;20263;20256:12;20281:118;20367:5;20360:13;20353:21;20346:5;20343:32;20333:60;;20389:1;20386;20379:12;20404:131;-1:-1:-1;;;;;;20478:32:1;;20468:43;;20458:71;;20525:1;20522;20515:12
Swarm Source
ipfs://868a46f6c1de263806a361876d5eb1974f5af51d22d0d93939ad068c17c9105e
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.