My Name Tag:
Not Available, login to update
[ Download CSV Export ]
OVERVIEW
This is the Single Staking Contract for the CroQueen Token.
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0x38cbb8b11ee56fc2ce1f36f46c3e0fe8565a08bbcb39fc94d8fcb425b48c6435 | 3200878 | 240 days 6 hrs ago | CroKing: CRQ Single Staking | Contract Creation | 0 CRO |
[ Download CSV Export ]
Contract Name:
CRQSoloStaking
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at cronoscan.com on 2022-06-12 */ // File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol // OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } } // File: CRQSingleStaking.sol //SPDX-License-Identifier: MIT pragma solidity 0.8.13; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor() {} function _msgSender() internal view returns (address payable) { return payable(msg.sender); } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @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. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; } /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), 'Ownable: caller is not the owner'); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), 'Ownable: new owner is the zero address'); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, 'SafeMath: addition overflow'); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, 'SafeMath: subtraction overflow'); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, 'SafeMath: multiplication overflow'); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, 'SafeMath: division by zero'); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, 'SafeMath: modulo by zero'); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } function min(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x < y ? x : y; } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } library SafeMathInt { int256 private constant MIN_INT256 = int256(1) << 255; int256 private constant MAX_INT256 = ~(int256(1) << 255); /** * @dev Multiplies two int256 variables and fails on overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { int256 c = a * b; // Detect overflow when multiplying MIN_INT256 with -1 require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); require((b == 0) || (c / b == a)); return c; } /** * @dev Division of two int256 variables and fails on overflow. */ function div(int256 a, int256 b) internal pure returns (int256) { // Prevent overflow when dividing MIN_INT256 by -1 require(b != -1 || a != MIN_INT256); // Solidity already throws when dividing by 0. return a / b; } /** * @dev Subtracts two int256 variables and fails on overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a)); return c; } /** * @dev Adds two int256 variables and fails on overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a)); return c; } /** * @dev Converts to absolute value, and fails on overflow. */ function abs(int256 a) internal pure returns (int256) { require(a != MIN_INT256); return a < 0 ? -a : a; } function toUint256Safe(int256 a) internal pure returns (uint256) { require(a >= 0); return uint256(a); } } library SafeMathUint { function toInt256Safe(uint256 a) internal pure returns (int256) { int256 b = int256(a); require(b >= 0); return b; } } interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @dev Collection of functions related to the address type */ 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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, 'Address: insufficient balance'); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(''); require(success, 'Address: unable to send value, recipient may have reverted'); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, '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'); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue( address target, bytes memory data, uint256 weiValue, string memory errorMessage ) private returns (bytes memory) { require(isContract(target), 'Address: call to non-contract'); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{value: weiValue}(data); if (success) { return returndata; } else { // 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } 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); } interface DividendPayingTokenOptionalInterface { /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` can withdraw. function withdrawableDividendOf(address _owner) external view returns(uint256); /// @notice View the amount of dividend in wei that an address has withdrawn. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` has withdrawn. function withdrawnDividendOf(address _owner) external view returns(uint256); /// @notice View the amount of dividend in wei that an address has earned in total. /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` has earned in total. function accumulativeDividendOf(address _owner) external view returns(uint256); } interface DividendPayingTokenInterface { /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` can withdraw. function dividendOf(address _owner) external view returns(uint256); /// @notice Distributes ether to token holders as dividends. /// @dev SHOULD distribute the paid ether to token holders as dividends. /// SHOULD NOT directly transfer ether to token holders in this function. /// MUST emit a `DividendsDistributed` event when the amount of distributed ether is greater than 0. function distributeDividends() external payable; /// @notice Withdraws the ether distributed to the sender. /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer. /// MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0. function withdrawDividend() external; /// @dev This event MUST emit when ether is distributed to token holders. /// @param from The address which sends ether to this contract. /// @param weiAmount The amount of distributed ether in wei. event DividendsDistributed( address indexed from, uint256 weiAmount ); /// @dev This event MUST emit when an address withdraws their dividend. /// @param to The address which withdraws ether from this contract. /// @param weiAmount The amount of withdrawn ether in wei. event DividendWithdrawn( address indexed to, uint256 weiAmount ); } contract DividendPayingToken is DividendPayingTokenInterface, DividendPayingTokenOptionalInterface, Ownable { using SafeMath for uint256; using SafeMathUint for uint256; using SafeMathInt for int256; // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small. // For more discussion about choosing the value of `magnitude`, // see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728 uint256 constant internal magnitude = 2**128; uint256 internal magnifiedDividendPerShare; address public immutable token = address(0x065DE42E28E42d90c2052a1B49e7f83806Af0e1F); // About dividendCorrection: // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with: // `dividendOf(_user) = dividendPerShare * balanceOf(_user)`. // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens), // `dividendOf(_user)` should not be changed, // but the computed value of `dividendPerShare * balanceOf(_user)` is changed. // To keep the `dividendOf(_user)` unchanged, we add a correction term: // `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`, // where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed: // `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`. // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed. mapping(address => int256) internal magnifiedDividendCorrections; mapping(address => uint256) internal withdrawnDividends; mapping (address => uint256) public holderBalance; uint256 public totalBalance; uint256 public totalDividendsDistributed; uint256 public totalDividendsWaitingToSend; /// @dev Distributes dividends whenever ether is paid to this contract. receive() external payable { distributeDividends(); } /// @notice Distributes ether to token holders as dividends. /// @dev It reverts if the total supply of tokens is 0. /// It emits the `DividendsDistributed` event if the amount of received ether is greater than 0. /// About undistributed ether: /// In each distribution, there is a small amount of ether not distributed, /// the magnified amount of which is /// `(msg.value * magnitude) % totalSupply()`. /// With a well-chosen `magnitude`, the amount of undistributed ether /// (de-magnified) in a distribution can be less than 1 wei. /// We can actually keep track of the undistributed ether in a distribution /// and try to distribute it in the next distribution, /// but keeping track of such data on-chain costs much more than /// the saved ether, so we don't do that. function distributeDividends() public override payable { require(false, "Cannot send BNB directly to tracker as it is unrecoverable"); // } function distributeTokenDividends() external onlyOwner { if(totalBalance > 0){ uint256 tokensToAdd; uint256 balance = IERC20(token).balanceOf(address(this)); if(totalDividendsWaitingToSend < balance){ tokensToAdd = balance - totalDividendsWaitingToSend; } else { tokensToAdd = 0; } if (tokensToAdd > 0) { magnifiedDividendPerShare = magnifiedDividendPerShare.add( (tokensToAdd).mul(magnitude) / totalBalance ); emit DividendsDistributed(msg.sender, tokensToAdd); totalDividendsDistributed = totalDividendsDistributed.add(tokensToAdd); totalDividendsWaitingToSend = totalDividendsWaitingToSend.add(tokensToAdd); } } } /// @notice Withdraws the ether distributed to the sender. /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0. function withdrawDividend() external virtual override { _withdrawDividendOfUser(payable(msg.sender)); } /// @notice Withdraws the ether distributed to the sender. /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0. function _withdrawDividendOfUser(address payable user) internal returns (uint256) { uint256 _withdrawableDividend = withdrawableDividendOf(user); if (_withdrawableDividend > 0) { withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend); if(totalDividendsWaitingToSend >= _withdrawableDividend){ totalDividendsWaitingToSend -= _withdrawableDividend; } else { totalDividendsWaitingToSend = 0; } emit DividendWithdrawn(user, _withdrawableDividend); bool success = IERC20(token).transfer(user, _withdrawableDividend); if(!success) { withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend); return 0; } return _withdrawableDividend; } return 0; } /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` can withdraw. function dividendOf(address _owner) external view override returns(uint256) { return withdrawableDividendOf(_owner); } /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` can withdraw. function withdrawableDividendOf(address _owner) public view override returns(uint256) { return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]); } /// @notice View the amount of dividend in wei that an address has withdrawn. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` has withdrawn. function withdrawnDividendOf(address _owner) external view override returns(uint256) { return withdrawnDividends[_owner]; } /// @notice View the amount of dividend in wei that an address has earned in total. /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that `_owner` has earned in total. function accumulativeDividendOf(address _owner) public view override returns(uint256) { return magnifiedDividendPerShare.mul(holderBalance[_owner]).toInt256Safe() .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude; } /// @dev Internal function that increases tokens to an account. /// Update magnifiedDividendCorrections to keep dividends unchanged. /// @param account The account that will receive the created tokens. /// @param value The amount that will be created. function _increase(address account, uint256 value) internal { magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() ); } /// @dev Internal function that reduces an amount of the token of a given account. /// Update magnifiedDividendCorrections to keep dividends unchanged. /// @param account The account whose tokens will be burnt. /// @param value The amount that will be burnt. function _reduce(address account, uint256 value) internal { magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() ); } function _setBalance(address account, uint256 newBalance) internal { uint256 currentBalance = holderBalance[account]; holderBalance[account] = newBalance; if(newBalance > currentBalance) { uint256 increaseAmount = newBalance.sub(currentBalance); _increase(account, increaseAmount); totalBalance += increaseAmount; } else if(newBalance < currentBalance) { uint256 reduceAmount = currentBalance.sub(newBalance); _reduce(account, reduceAmount); totalBalance -= reduceAmount; } } } contract DividendTracker is DividendPayingToken { using SafeMath for uint256; using SafeMathInt for int256; struct Map { address[] keys; mapping(address => uint) values; mapping(address => uint) indexOf; mapping(address => bool) inserted; } function get(address key) private view returns (uint) { return tokenHoldersMap.values[key]; } function getIndexOfKey(address key) private view returns (int) { if(!tokenHoldersMap.inserted[key]) { return -1; } return int(tokenHoldersMap.indexOf[key]); } function getKeyAtIndex(uint index) private view returns (address) { return tokenHoldersMap.keys[index]; } function size() private view returns (uint) { return tokenHoldersMap.keys.length; } function set(address key, uint val) private { if (tokenHoldersMap.inserted[key]) { tokenHoldersMap.values[key] = val; } else { tokenHoldersMap.inserted[key] = true; tokenHoldersMap.values[key] = val; tokenHoldersMap.indexOf[key] = tokenHoldersMap.keys.length; tokenHoldersMap.keys.push(key); } } function remove(address key) private { if (!tokenHoldersMap.inserted[key]) { return; } delete tokenHoldersMap.inserted[key]; delete tokenHoldersMap.values[key]; uint index = tokenHoldersMap.indexOf[key]; uint lastIndex = tokenHoldersMap.keys.length - 1; address lastKey = tokenHoldersMap.keys[lastIndex]; tokenHoldersMap.indexOf[lastKey] = index; delete tokenHoldersMap.indexOf[key]; tokenHoldersMap.keys[index] = lastKey; tokenHoldersMap.keys.pop(); } Map private tokenHoldersMap; uint256 public lastProcessedIndex; mapping (address => bool) public excludedFromDividends; mapping (address => uint256) public lastClaimTimes; uint256 public claimWait; uint256 public immutable minimumTokenBalanceForDividends; event ExcludeFromDividends(address indexed account); event IncludeInDividends(address indexed account); event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue); event Claim(address indexed account, uint256 amount, bool indexed automatic); constructor() { claimWait = 1; minimumTokenBalanceForDividends = 1 * (10**18); //must hold 10,000+ tokens } function excludeFromDividends(address account) external onlyOwner { excludedFromDividends[account] = true; _setBalance(account, 0); remove(account); emit ExcludeFromDividends(account); } function includeInDividends(address account) external onlyOwner { require(excludedFromDividends[account]); excludedFromDividends[account] = false; emit IncludeInDividends(account); } function updateClaimWait(uint256 newClaimWait) external onlyOwner { require(newClaimWait >= 1200 && newClaimWait <= 86400, "Dividend_Tracker: claimWait must be updated to between 1 and 24 hours"); require(newClaimWait != claimWait, "Dividend_Tracker: Cannot update claimWait to same value"); emit ClaimWaitUpdated(newClaimWait, claimWait); claimWait = newClaimWait; } function getLastProcessedIndex() external view returns(uint256) { return lastProcessedIndex; } function getNumberOfTokenHolders() external view returns(uint256) { return tokenHoldersMap.keys.length; } // Check to see if I really made this contract or if it is a clone! // @Sir_Tris on TG, @SirTrisCrypto on Twitter function getAccount(address _account) public view returns ( address account, int256 index, int256 iterationsUntilProcessed, uint256 withdrawableDividends, uint256 totalDividends, uint256 lastClaimTime, uint256 nextClaimTime, uint256 secondsUntilAutoClaimAvailable) { account = _account; index = getIndexOfKey(account); iterationsUntilProcessed = -1; if(index >= 0) { if(uint256(index) > lastProcessedIndex) { iterationsUntilProcessed = index.sub(int256(lastProcessedIndex)); } else { uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ? tokenHoldersMap.keys.length.sub(lastProcessedIndex) : 0; iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray)); } } withdrawableDividends = withdrawableDividendOf(account); totalDividends = accumulativeDividendOf(account); lastClaimTime = lastClaimTimes[account]; nextClaimTime = lastClaimTime > 0 ? lastClaimTime.add(claimWait) : 0; secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ? nextClaimTime.sub(block.timestamp) : 0; } function getAccountAtIndex(uint256 index) external view returns ( address, int256, int256, uint256, uint256, uint256, uint256, uint256) { if(index >= size()) { return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0); } address account = getKeyAtIndex(index); return getAccount(account); } function canAutoClaim(uint256 lastClaimTime) private view returns (bool) { if(lastClaimTime > block.timestamp) { return false; } return block.timestamp.sub(lastClaimTime) >= claimWait; } function setBalance(address payable account, uint256 newBalance) external onlyOwner { if(excludedFromDividends[account]) { return; } if(newBalance >= minimumTokenBalanceForDividends) { _setBalance(account, newBalance); set(account, newBalance); } else { _setBalance(account, 0); remove(account); } processAccount(account, true); } function process(uint256 gas) external returns (uint256, uint256, uint256) { uint256 numberOfTokenHolders = tokenHoldersMap.keys.length; if(numberOfTokenHolders == 0) { return (0, 0, lastProcessedIndex); } uint256 _lastProcessedIndex = lastProcessedIndex; uint256 gasUsed = 0; uint256 gasLeft = gasleft(); uint256 iterations = 0; uint256 claims = 0; while(gasUsed < gas && iterations < numberOfTokenHolders) { _lastProcessedIndex++; if(_lastProcessedIndex >= tokenHoldersMap.keys.length) { _lastProcessedIndex = 0; } address account = tokenHoldersMap.keys[_lastProcessedIndex]; if(canAutoClaim(lastClaimTimes[account])) { if(processAccount(payable(account), true)) { claims++; } } iterations++; uint256 newGasLeft = gasleft(); if(gasLeft > newGasLeft) { gasUsed = gasUsed.add(gasLeft.sub(newGasLeft)); } gasLeft = newGasLeft; } lastProcessedIndex = _lastProcessedIndex; return (iterations, claims, lastProcessedIndex); } function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) { uint256 amount = _withdrawDividendOfUser(account); if(amount > 0) { lastClaimTimes[account] = block.timestamp; emit Claim(account, amount, automatic); return true; } return false; } } abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } contract CRQSoloStaking is Ownable, ReentrancyGuard { using SafeMath for uint256; using EnumerableSet for EnumerableSet.UintSet; DividendTracker public dividendTracker; IERC20 public immutable CRK = IERC20(0x065DE42E28E42d90c2052a1B49e7f83806Af0e1F); // Info of each user. struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 multipliedAmount; uint256 rewardDebt; // Reward debt. See explanation below. } // Info of each pool. struct PoolInfo { IERC20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. Tokens to distribute per block. uint256 lastRewardTimestamp; // Last block number that Tokens distribution occurs. uint256 accTokensPerShare; // Accumulated Tokens per share, times 1e12. See below. } IERC20 public immutable stakingToken; IERC20 public immutable rewardToken; mapping (address => uint256) public holderUnlockTime; mapping (address => uint256) public holderNftsStakedAmount; mapping (address => mapping (address => EnumerableSet.UintSet)) private holderNftsStaked; mapping (address => bool) public isValidNftToStake; uint256 public totalStaked; uint256 public totalStakedMultiplied; uint256 public rewardsPerSecond; uint256 public lockDuration; uint256 public exitPenaltyPerc; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping (address => UserInfo) public userInfo; // Total allocation poitns. Must be the sum of all allocation points in all pools. uint256 private totalAllocPoint = 0; event Deposit(address indexed user, uint256 amount); event Withdraw(address indexed user, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 amount); event StakedNFT(address indexed nftAddress, uint256 indexed tokenId, address indexed sender); event UnstakedNFT(address indexed nftAddress, uint256 indexed tokenId, address indexed sender); constructor( ) { stakingToken = IERC20(0xC5dfe8884aEc69716B3621Af2000A305e7e16E2B); rewardToken = IERC20(0xC5dfe8884aEc69716B3621Af2000A305e7e16E2B); dividendTracker = new DividendTracker(); rewardsPerSecond = 3 * 1e6 * 1e18; lockDuration = 0; exitPenaltyPerc = 0; isValidNftToStake[0xAD4bDA67bB8b6A502496EEF4dFba2ffdBAc38dB6] = true; isValidNftToStake[0x51D25FB5FBfe57FF67B20c499d4dd1d3c64844B7] = true; // staking pool poolInfo.push(PoolInfo({ lpToken: stakingToken, allocPoint: 1000, lastRewardTimestamp: 99999999999, accTokensPerShare: 0 })); totalAllocPoint = 1000; } function getHolderNfts(address nftAddress, address wallet) external view returns (uint256[] memory){ return holderNftsStaked[wallet][nftAddress].values(); } function stopReward() external onlyOwner { updatePool(0); rewardsPerSecond = 0; } function updateNftToStake(address nftAddress, bool enabledToStake) external onlyOwner { isValidNftToStake[nftAddress] = enabledToStake; } function startReward() external onlyOwner { require(poolInfo[0].lastRewardTimestamp == 99999999999, "Can only start rewards once"); poolInfo[0].lastRewardTimestamp = block.timestamp; } function stakeNft(address nftAddress, uint256 tokenId) external nonReentrant { require(isValidNftToStake[nftAddress], "NFT address not valid to stake"); require(holderNftsStaked[msg.sender][nftAddress].length() < 3, "Cannot stake more than 3 of the same NFT"); IERC721 nft = IERC721(nftAddress); UserInfo storage user = userInfo[msg.sender]; PoolInfo storage pool = poolInfo[0]; require(nft.getApproved(tokenId) == address(this), "Must approve token to be sent"); updatePool(0); if (user.amount > 0) { uint256 pending = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt); if(pending >= rewardsRemaining()){ pending = rewardsRemaining(); } if(pending > 0) { rewardToken.transfer(address(msg.sender), pending); } } nft.transferFrom(msg.sender, address(this), tokenId); holderNftsStakedAmount[msg.sender] += 1; holderNftsStaked[msg.sender][nftAddress].add(tokenId); totalStakedMultiplied -= user.multipliedAmount; user.multipliedAmount = user.amount * getStakingMultiplier(msg.sender) / 100; totalStakedMultiplied += user.multipliedAmount; user.rewardDebt = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12); emit StakedNFT(nftAddress, tokenId, msg.sender); } function unstakeNft(address nftAddress, uint256 tokenId) external nonReentrant { require(holderNftsStaked[msg.sender][nftAddress].contains(tokenId), "Can only unstake a tokenID allocated from this NFT address for the sender"); IERC721 nft = IERC721(nftAddress); UserInfo storage user = userInfo[msg.sender]; PoolInfo storage pool = poolInfo[0]; updatePool(0); if (user.amount > 0) { uint256 pending = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt); if(pending >= rewardsRemaining()){ pending = rewardsRemaining(); } if(pending > 0) { rewardToken.transfer(address(msg.sender), pending); } } nft.transferFrom(address(this), msg.sender, tokenId); holderNftsStakedAmount[msg.sender] -= 1; holderNftsStaked[msg.sender][nftAddress].remove(tokenId); totalStakedMultiplied -= user.multipliedAmount; user.multipliedAmount = user.amount * getStakingMultiplier(msg.sender) / 100; totalStakedMultiplied += user.multipliedAmount; user.rewardDebt = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12); emit UnstakedNFT(nftAddress, tokenId, msg.sender); } // @dev note that you must divide this by 100 after multiplying against tokens. function getStakingMultiplier(address holder) public view returns (uint256) { if(holderNftsStakedAmount[holder] == 0){ return 100; } // 15% additive boost per NFT staked return 100 + (holderNftsStakedAmount[holder]*15); } // View function to see pending Reward on frontend. function pendingReward(address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[_user]; if(pool.lastRewardTimestamp == 99999999999){ return 0; } uint256 accTokensPerShare = pool.accTokensPerShare; uint256 lpSupply = totalStakedMultiplied; if (block.timestamp > pool.lastRewardTimestamp && lpSupply != 0) { uint256 tokenReward = calculateNewRewards().mul(pool.allocPoint).div(totalAllocPoint); accTokensPerShare = accTokensPerShare.add(tokenReward.mul(1e12).div(lpSupply)); } return user.multipliedAmount.mul(accTokensPerShare).div(1e12).sub(user.rewardDebt); } // Update reward variables of the given pool to be up-to-date. function updatePool(uint256 _pid) internal { // transfer any accumulated tokens. if(CRK.balanceOf(address(this)) > 0){ CRK.transfer(address(dividendTracker), CRK.balanceOf(address(this))); } dividendTracker.distributeTokenDividends(); PoolInfo storage pool = poolInfo[_pid]; if (block.timestamp <= pool.lastRewardTimestamp) { return; } uint256 lpSupply = totalStakedMultiplied; if (lpSupply == 0) { pool.lastRewardTimestamp = block.timestamp; return; } uint256 tokenReward = calculateNewRewards().mul(pool.allocPoint).div(totalAllocPoint); pool.accTokensPerShare = pool.accTokensPerShare.add(tokenReward.mul(1e12).div(lpSupply)); pool.lastRewardTimestamp = block.timestamp; } // Update reward variables for all pools. Be careful of gas spending! function massUpdatePools() public onlyOwner { uint256 length = poolInfo.length; for (uint256 pid = 0; pid < length; ++pid) { updatePool(pid); } } // Stake primary tokens function deposit(uint256 _amount) public nonReentrant { if(holderUnlockTime[msg.sender] == 0){ holderUnlockTime[msg.sender] = block.timestamp + lockDuration; } PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; updatePool(0); if (user.amount > 0) { uint256 pending = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt); if(pending >= rewardsRemaining()){ pending = rewardsRemaining(); } if(pending > 0) { rewardToken.transfer(address(msg.sender), pending); } } uint256 amountTransferred = 0; if(_amount > 0) { uint256 initialBalance = pool.lpToken.balanceOf(address(this)); pool.lpToken.transferFrom(address(msg.sender), address(this), _amount); amountTransferred = pool.lpToken.balanceOf(address(this)) - initialBalance; totalStakedMultiplied -= user.multipliedAmount; user.amount = user.amount.add(amountTransferred); user.multipliedAmount = user.amount * getStakingMultiplier(msg.sender) / 100; totalStaked += amountTransferred; totalStakedMultiplied += user.multipliedAmount; } dividendTracker.setBalance(payable(msg.sender), user.amount); user.rewardDebt = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12); emit Deposit(msg.sender, _amount); } // Withdraw primary tokens from STAKING. function withdraw(uint256 _amount) public nonReentrant { require(holderUnlockTime[msg.sender] <= block.timestamp, "May not do normal withdraw early"); PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; updatePool(0); uint256 pending = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12).sub(user.rewardDebt); if(pending >= rewardsRemaining()){ pending = rewardsRemaining(); } if(pending > 0) { rewardToken.transfer(payable(address(msg.sender)), pending); } if(_amount > 0) { user.amount -= _amount; user.multipliedAmount = user.amount * getStakingMultiplier(msg.sender) / 100; totalStaked -= _amount; totalStakedMultiplied -= _amount * getStakingMultiplier(msg.sender) / 100; pool.lpToken.transfer(address(msg.sender), _amount); } dividendTracker.setBalance(payable(msg.sender), user.amount); user.rewardDebt = user.multipliedAmount.mul(pool.accTokensPerShare).div(1e12); if(user.amount > 0){ holderUnlockTime[msg.sender] = block.timestamp + lockDuration; } else { holderUnlockTime[msg.sender] = 0; } emit Withdraw(msg.sender, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function emergencyWithdraw() external nonReentrant { PoolInfo storage pool = poolInfo[0]; UserInfo storage user = userInfo[msg.sender]; uint256 _amount = user.amount; totalStaked -= _amount; totalStakedMultiplied -= user.multipliedAmount; // exit penalty for early unstakers, penalty held on contract as rewards. if(holderUnlockTime[msg.sender] >= block.timestamp){ _amount -= _amount * exitPenaltyPerc / 100; } holderUnlockTime[msg.sender] = 0; pool.lpToken.transfer(address(msg.sender), _amount); user.amount = 0; user.multipliedAmount = 0; user.rewardDebt = 0; dividendTracker.setBalance(payable(msg.sender), 0); emit EmergencyWithdraw(msg.sender, _amount); } // Withdraw reward. EMERGENCY ONLY. This allows the owner to migrate rewards to a new staking pool since we are not minting new tokens. function emergencyRewardWithdraw(uint256 _amount) external onlyOwner { require(_amount <= rewardsRemaining(), 'not enough tokens to take out'); rewardToken.transfer(address(msg.sender), _amount); } function calculateNewRewards() public view returns (uint256) { PoolInfo storage pool = poolInfo[0]; if(pool.lastRewardTimestamp > block.timestamp){ return 0; } return ((block.timestamp - pool.lastRewardTimestamp) * rewardsPerSecond); } function rewardsRemaining() public view returns (uint256){ return rewardToken.balanceOf(address(this)) - totalStaked; } function updateRewardsPerSecond(uint256 newRewardsPerSecond) external onlyOwner { require(rewardsPerSecond <= 10000000, "Rewards per second must be below 10,000,000"); updatePool(0); rewardsPerSecond = newRewardsPerSecond * 1e18; } function updateExitPenalty(uint256 newPenaltyPerc) external onlyOwner { require(newPenaltyPerc <= 20, "May not set higher than 20%"); exitPenaltyPerc = newPenaltyPerc; } function claim() external nonReentrant { dividendTracker.processAccount(payable(msg.sender), false); } }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","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":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"StakedNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"UnstakedNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"CRK","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateNewRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dividendTracker","outputs":[{"internalType":"contract DividendTracker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"emergencyRewardWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exitPenaltyPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"address","name":"wallet","type":"address"}],"name":"getHolderNfts","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"getStakingMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"holderNftsStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"holderUnlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isValidNftToStake","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardTimestamp","type":"uint256"},{"internalType":"uint256","name":"accTokensPerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stakeNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedMultiplied","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstakeNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPenaltyPerc","type":"uint256"}],"name":"updateExitPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"bool","name":"enabledToStake","type":"bool"}],"name":"updateNftToStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardsPerSecond","type":"uint256"}],"name":"updateRewardsPerSecond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"multipliedAmount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e060405273065de42e28e42d90c2052a1b49e7f83806af0e1f6080526000600e553480156200002e57600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001805573c5dfe8884aec69716b3621af2000a305e7e16e2b60a081905260c0526040516200009f9062000247565b604051809103906000f080158015620000bc573d6000803e3d6000fd5b50600280546001600160a01b039283166001600160a01b0319918216179091556a027b46536c66c8e30000006009556000600a819055600b819055600660209081527fcc82402dd09bb21526b47a53a1323e78d55d2899170c8afdd3ee8c28aa0f2e17805460ff1990811660019081179092557f16be138c1cc2752616726dd2f7ed1d111203eb6959a0d366605ff1fe309ce4bf8054909116821790556040805160808101825260a051871681526103e893810184815264174876e7ff92820192835260608201868152600c80549586018155909652905160049093027fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c781018054949098169390961692909217909555517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c884015592517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c9830155517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8ca90910155600e5562000255565b611b978062002c6583390190565b60805160a05160c0516129a8620002bd60003960008181610512015281816106b7015281816109df01528181610ce701528181611197015281816115710152611c310152600061037601526000818161033f01528181611f67015261200001526129a86000f3fe608060405234801561001057600080fd5b50600436106102115760003560e01c8063817b1cd211610125578063b6b55f25116100ad578063eacdaabc1161007c578063eacdaabc146104cb578063f2bee231146104d4578063f2fde38b146104e7578063f40f0f52146104fa578063f7c618c11461050d57600080fd5b8063b6b55f251461045d578063c3c235c214610470578063d4da5eb414610490578063db2e21bc146104c357600080fd5b80639a7c5473116100f45780639a7c5473146103ee5780639d757bb5146103f75780639f5662e21461040a578063a0df342b1461041d578063a913a5f71461043d57600080fd5b8063817b1cd2146103b95780638da5cb5b146103c25780638e0b0198146103d3578063999e2f75146103e657600080fd5b806356a23f33116101a857806372f702f31161017757806372f702f314610371578063746c8ae11461039857806378c196f3146103a05780637b280def146103a857806380dc0672146103b157600080fd5b806356a23f33146103275780636100b0081461033a578063630b5ba114610361578063715018a61461036957600080fd5b80632e1a7d4d116101e45780632e1a7d4d146102e45780633279beab146102f95780633660130b1461030c5780634e71d92d1461031f57600080fd5b806304554443146102165780631526fe27146102325780631959a0021461026f5780632c1f5216146102b9575b600080fd5b61021f600a5481565b6040519081526020015b60405180910390f35b61024561024036600461264a565b610534565b604080516001600160a01b0390951685526020850193909352918301526060820152608001610229565b61029e61027d366004612678565b600d6020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610229565b6002546102cc906001600160a01b031681565b6040516001600160a01b039091168152602001610229565b6102f76102f236600461264a565b610578565b005b6102f761030736600461264a565b610947565b6102f761031a366004612695565b610a5d565b6102f7610ee0565b61021f610335366004612678565b610f83565b6102cc7f000000000000000000000000000000000000000000000000000000000000000081565b6102f7610fdf565b6102f7611030565b6102cc7f000000000000000000000000000000000000000000000000000000000000000081565b6102f76110a4565b61021f611173565b61021f600b5481565b6102f7611211565b61021f60075481565b6000546001600160a01b03166102cc565b6102f76103e136600461264a565b61124c565b61021f6112cc565b61021f60085481565b6102f76104053660046126cf565b611329565b6102f761041836600461264a565b61137e565b61043061042b366004612708565b611433565b6040516102299190612736565b61021f61044b366004612678565b60036020526000908152604090205481565b6102f761046b36600461264a565b61146b565b61021f61047e366004612678565b60046020526000908152604090205481565b6104b361049e366004612678565b60066020526000908152604090205460ff1681565b6040519015158152602001610229565b6102f761189d565b61021f60095481565b6102f76104e2366004612695565b611aad565b6102f76104f5366004612678565b611e2a565b61021f610508366004612678565b611e60565b6102cc7f000000000000000000000000000000000000000000000000000000000000000081565b600c818154811061054457600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b039092169350919084565b6002600154036105a35760405162461bcd60e51b815260040161059a9061277a565b60405180910390fd5b6002600155336000908152600360205260409020544210156106075760405162461bcd60e51b815260206004820181905260248201527f4d6179206e6f7420646f206e6f726d616c207769746864726177206561726c79604482015260640161059a565b6000600c60008154811061061d5761061d6127b1565b60009182526020808320338452600d9091526040832060049092020192509061064590611f4f565b600061067f826002015461067964e8d4a51000610673876003015487600101546121d890919063ffffffff16565b9061225a565b9061229c565b9050610689611173565b811061069a57610697611173565b90505b80156107335760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906106ee90339085906004016127c7565b6020604051808303816000875af115801561070d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073191906127e0565b505b831561083f578382600001600082825461074d9190612813565b909155506064905061075e33610f83565b835461076a919061282a565b6107749190612849565b8260010181905550836007600082825461078e9190612813565b909155506064905061079f33610f83565b6107a9908661282a565b6107b39190612849565b600860008282546107c49190612813565b9091555050825460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906107fa90339088906004016127c7565b6020604051808303816000875af1158015610819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083d91906127e0565b505b60025482546040516338c110ef60e21b81526001600160a01b039092169163e30443bc91610872913391906004016127c7565b600060405180830381600087803b15801561088c57600080fd5b505af11580156108a0573d6000803e3d6000fd5b505050506108c864e8d4a51000610673856003015485600101546121d890919063ffffffff16565b60028301558154156108f657600a546108e1904261286b565b33600090815260036020526040902055610907565b336000908152600360205260408120555b60405184815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364906020015b60405180910390a25050600180555050565b6000546001600160a01b031633146109715760405162461bcd60e51b815260040161059a90612883565b610979611173565b8111156109c85760405162461bcd60e51b815260206004820152601d60248201527f6e6f7420656e6f75676820746f6b656e7320746f2074616b65206f7574000000604482015260640161059a565b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90610a1690339085906004016127c7565b6020604051808303816000875af1158015610a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5991906127e0565b5050565b600260015403610a7f5760405162461bcd60e51b815260040161059a9061277a565b60026001556001600160a01b03821660009081526006602052604090205460ff16610aec5760405162461bcd60e51b815260206004820152601e60248201527f4e46542061646472657373206e6f742076616c696420746f207374616b650000604482015260640161059a565b3360009081526005602090815260408083206001600160a01b03861684529091529020600390610b1b906122de565b10610b795760405162461bcd60e51b815260206004820152602860248201527f43616e6e6f74207374616b65206d6f7265207468616e2033206f6620746865206044820152671cd85b594813919560c21b606482015260840161059a565b336000908152600d60205260408120600c8054859391908290610b9e57610b9e6127b1565b6000918252602090912060405163020604bf60e21b8152600481810188905290920201915030906001600160a01b0385169063081812fc90602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a91906128b8565b6001600160a01b031614610c705760405162461bcd60e51b815260206004820152601d60248201527f4d75737420617070726f766520746f6b656e20746f2062652073656e74000000604482015260640161059a565b610c7a6000611f4f565b815415610d65576000610caf836002015461067964e8d4a51000610673866003015488600101546121d890919063ffffffff16565b9050610cb9611173565b8110610cca57610cc7611173565b90505b8015610d635760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90610d1e90339085906004016127c7565b6020604051808303816000875af1158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906127e0565b505b505b6040516323b872dd60e01b8152336004820152306024820152604481018590526001600160a01b038416906323b872dd90606401600060405180830381600087803b158015610db357600080fd5b505af1158015610dc7573d6000803e3d6000fd5b5050336000908152600460205260408120805460019450909250610dec90849061286b565b90915550503360009081526005602090815260408083206001600160a01b03891684529091529020610e1e90856122e8565b50816001015460086000828254610e359190612813565b9091555060649050610e4633610f83565b8354610e52919061282a565b610e5c9190612849565b6001830181905560088054600090610e7590849061286b565b909155505060038101546001830154610e989164e8d4a5100091610673916121d8565b6002830155604051339085906001600160a01b038816907f31461cc1f2e75f983949638b472aa50bc262a5c01efc3ae2103864f984c4d49f90600090a4505060018055505050565b600260015403610f025760405162461bcd60e51b815260040161059a9061277a565b600260018190555460405163bc4c4b3760e01b8152336004820152600060248201526001600160a01b039091169063bc4c4b37906044016020604051808303816000875af1158015610f58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7c91906127e0565b5060018055565b6001600160a01b0381166000908152600460205260408120548103610faa57506064919050565b6001600160a01b038216600090815260046020526040902054610fce90600f61282a565b610fd990606461286b565b92915050565b6000546001600160a01b031633146110095760405162461bcd60e51b815260040161059a90612883565b600c5460005b81811015610a595761102081611f4f565b611029816128d5565b905061100f565b6000546001600160a01b0316331461105a5760405162461bcd60e51b815260040161059a90612883565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146110ce5760405162461bcd60e51b815260040161059a90612883565b600c6000815481106110e2576110e26127b1565b90600052602060002090600402016002015464174876e7ff146111475760405162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c792073746172742072657761726473206f6e63650000000000604482015260640161059a565b42600c60008154811061115c5761115c6127b1565b906000526020600020906004020160020181905550565b6007546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156111de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120291906128ee565b61120c9190612813565b905090565b6000546001600160a01b0316331461123b5760405162461bcd60e51b815260040161059a90612883565b6112456000611f4f565b6000600955565b6000546001600160a01b031633146112765760405162461bcd60e51b815260040161059a90612883565b60148111156112c75760405162461bcd60e51b815260206004820152601b60248201527f4d6179206e6f742073657420686967686572207468616e203230250000000000604482015260640161059a565b600b55565b600080600c6000815481106112e3576112e36127b1565b90600052602060002090600402019050428160020154111561130757600091505090565b60095460028201546113199042612813565b611323919061282a565b91505090565b6000546001600160a01b031633146113535760405162461bcd60e51b815260040161059a90612883565b6001600160a01b03919091166000908152600660205260409020805460ff1916911515919091179055565b6000546001600160a01b031633146113a85760405162461bcd60e51b815260040161059a90612883565b6298968060095411156114115760405162461bcd60e51b815260206004820152602b60248201527f5265776172647320706572207365636f6e64206d7573742062652062656c6f7760448201526a02031302c3030302c3030360ac1b606482015260840161059a565b61141b6000611f4f565b61142d81670de0b6b3a764000061282a565b60095550565b6001600160a01b038082166000908152600560209081526040808320938616835292905220606090611464906122f4565b9392505050565b60026001540361148d5760405162461bcd60e51b815260040161059a9061277a565b60026001553360009081526003602052604081205490036114c657600a546114b5904261286b565b336000908152600360205260409020555b6000600c6000815481106114dc576114dc6127b1565b60009182526020808320338452600d9091526040832060049092020192509061150490611f4f565b8054156115ef576000611539826002015461067964e8d4a51000610673876003015487600101546121d890919063ffffffff16565b9050611543611173565b811061155457611551611173565b90505b80156115ed5760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906115a890339085906004016127c7565b6020604051808303816000875af11580156115c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115eb91906127e0565b505b505b600083156117dd5782546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561163f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166391906128ee565b84546040516323b872dd60e01b8152336004820152306024820152604481018890529192506001600160a01b0316906323b872dd906064016020604051808303816000875af11580156116ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116de91906127e0565b5083546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015611726573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174a91906128ee565b6117549190612813565b915082600101546008600082825461176c9190612813565b9091555050825461177d9083612301565b8355606461178a33610f83565b8454611796919061282a565b6117a09190612849565b836001018190555081600760008282546117ba919061286b565b90915550506001830154600880546000906117d690849061286b565b9091555050505b60025482546040516338c110ef60e21b81526001600160a01b039092169163e30443bc91611810913391906004016127c7565b600060405180830381600087803b15801561182a57600080fd5b505af115801561183e573d6000803e3d6000fd5b5050505061186664e8d4a51000610673856003015485600101546121d890919063ffffffff16565b600283015560405184815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90602001610935565b6002600154036118bf5760405162461bcd60e51b815260040161059a9061277a565b60026001819055506000600c6000815481106118dd576118dd6127b1565b60009182526020808320338452600d90915260408320805460078054600490950290930195509093909283929190611916908490612813565b9091555050600182015460088054600090611932908490612813565b9091555050336000908152600360205260409020544211611974576064600b548261195d919061282a565b6119679190612849565b6119719082612813565b90505b33600081815260036020526040808220919091558454905163a9059cbb60e01b81526001600160a01b039091169163a9059cbb916119b7919085906004016127c7565b6020604051808303816000875af11580156119d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fa91906127e0565b506000808355600183018190556002808401829055546040516338c110ef60e21b81526001600160a01b039091169163e30443bc91611a3d9133916004016127c7565b600060405180830381600087803b158015611a5757600080fd5b505af1158015611a6b573d6000803e3d6000fd5b50506040518381523392507f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695915060200160405180910390a250506001805550565b600260015403611acf5760405162461bcd60e51b815260040161059a9061277a565b60026001553360009081526005602090815260408083206001600160a01b03861684529091529020611b019082612360565b611b855760405162461bcd60e51b815260206004820152604960248201527f43616e206f6e6c7920756e7374616b65206120746f6b656e494420616c6c6f6360448201527f617465642066726f6d2074686973204e4654206164647265737320666f72207460648201526834329039b2b73232b960b91b608482015260a40161059a565b336000908152600d60205260408120600c8054859391908290611baa57611baa6127b1565b90600052602060002090600402019050611bc46000611f4f565b815415611caf576000611bf9836002015461067964e8d4a51000610673866003015488600101546121d890919063ffffffff16565b9050611c03611173565b8110611c1457611c11611173565b90505b8015611cad5760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90611c6890339085906004016127c7565b6020604051808303816000875af1158015611c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cab91906127e0565b505b505b6040516323b872dd60e01b8152306004820152336024820152604481018590526001600160a01b038416906323b872dd90606401600060405180830381600087803b158015611cfd57600080fd5b505af1158015611d11573d6000803e3d6000fd5b5050336000908152600460205260408120805460019450909250611d36908490612813565b90915550503360009081526005602090815260408083206001600160a01b03891684529091529020611d689085612378565b50816001015460086000828254611d7f9190612813565b9091555060649050611d9033610f83565b8354611d9c919061282a565b611da69190612849565b6001830181905560088054600090611dbf90849061286b565b909155505060038101546001830154611de29164e8d4a5100091610673916121d8565b6002830155604051339085906001600160a01b038816907fb2f8dc0208beec4fd9cd28491960f2897e6bf6eed6e00d2d1eb4cbfa5e76b25990600090a4505060018055505050565b6000546001600160a01b03163314611e545760405162461bcd60e51b815260040161059a90612883565b611e5d81612384565b50565b600080600c600081548110611e7757611e776127b1565b600091825260208083206001600160a01b0387168452600d9091526040909220600260049092029092019081015490925064174876e7ff03611ebd575060009392505050565b6003820154600854600284015442118015611ed757508015155b15611f1d576000611efa600e546106738760010154611ef46112cc565b906121d8565b9050611f19611f12836106738464e8d4a510006121d8565b8490612301565b9250505b611f45836002015461067964e8d4a510006106738688600101546121d890919063ffffffff16565b9695505050505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fda91906128ee565b11156120d9576002546040516370a0823160e01b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263a9059cbb9291169083906370a0823190602401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207791906128ee565b6040518363ffffffff1660e01b81526004016120949291906127c7565b6020604051808303816000875af11580156120b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d791906127e0565b505b600260009054906101000a90046001600160a01b03166001600160a01b031663b51312916040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561212957600080fd5b505af115801561213d573d6000803e3d6000fd5b505050506000600c8281548110612156576121566127b1565b9060005260206000209060040201905080600201544211612175575050565b600854600081900361218c57504260029091015550565b60006121a4600e546106738560010154611ef46112cc565b90506121c76121bc836106738464e8d4a510006121d8565b600385015490612301565b600384015550504260029091015550565b6000826000036121ea57506000610fd9565b60006121f6838561282a565b9050826122038583612849565b146114645760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b606482015260840161059a565b600061146483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612444565b600061146483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061247b565b6000610fd9825490565b600061146483836124ac565b60606000611464836124fb565b60008061230e838561286b565b9050838110156114645760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640161059a565b60008181526001830160205260408120541515611464565b60006114648383612557565b6001600160a01b0381166123e95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161059a565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600081836124655760405162461bcd60e51b815260040161059a9190612907565b5060006124728486612849565b95945050505050565b6000818484111561249f5760405162461bcd60e51b815260040161059a9190612907565b5060006124728486612813565b60008181526001830160205260408120546124f357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610fd9565b506000610fd9565b60608160000180548060200260200160405190810160405280929190818152602001828054801561254b57602002820191906000526020600020905b815481526020019060010190808311612537575b50505050509050919050565b6000818152600183016020526040812054801561264057600061257b600183612813565b855490915060009061258f90600190612813565b90508181146125f45760008660000182815481106125af576125af6127b1565b90600052602060002001549050808760000184815481106125d2576125d26127b1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806126055761260561295c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610fd9565b6000915050610fd9565b60006020828403121561265c57600080fd5b5035919050565b6001600160a01b0381168114611e5d57600080fd5b60006020828403121561268a57600080fd5b813561146481612663565b600080604083850312156126a857600080fd5b82356126b381612663565b946020939093013593505050565b8015158114611e5d57600080fd5b600080604083850312156126e257600080fd5b82356126ed81612663565b915060208301356126fd816126c1565b809150509250929050565b6000806040838503121561271b57600080fd5b823561272681612663565b915060208301356126fd81612663565b6020808252825182820181905260009190848201906040850190845b8181101561276e57835183529284019291840191600101612752565b50909695505050505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000602082840312156127f257600080fd5b8151611464816126c1565b634e487b7160e01b600052601160045260246000fd5b600082821015612825576128256127fd565b500390565b6000816000190483118215151615612844576128446127fd565b500290565b60008261286657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561287e5761287e6127fd565b500190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6000602082840312156128ca57600080fd5b815161146481612663565b6000600182016128e7576128e76127fd565b5060010190565b60006020828403121561290057600080fd5b5051919050565b600060208083528351808285015260005b8181101561293457858101830151858201604001528201612918565b81811115612946576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220c4d3d2a4007486a1b18c3ca573189935ad23a46e49a2ffaa22e8227c9e4ddfa764736f6c634300080d003360c060405273065de42e28e42d90c2052a1b49e7f83806af0e1f60805234801561002857600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600f55670de0b6b3a764000060a05260805160a051611ae26100b5600039600081816104c10152610bac0152600081816105c001528181610901015261137f0152611ae26000f3fe6080604052600436106101d15760003560e01c8063aafd847a116100f7578063e30443bc11610095578063f2fde38b11610064578063f2fde38b1461056e578063fbcbc0f11461058e578063fc0c546a146105ae578063ffb2c479146105e257600080fd5b8063e30443bc14610503578063e7841ec014610523578063e98030c714610538578063f2e65d6f1461055857600080fd5b8063b5131291116100d1578063b51312911461047a578063bc4c4b371461048f578063be10b614146104af578063c0f306ef146104e357600080fd5b8063aafd847a14610401578063ab6ddfa814610437578063ad7a672f1461046457600080fd5b80635183d6fd1161016f57806385a6b3ae1161013e57806385a6b3ae146103795780638da5cb5b1461038f57806391b89fba146103c1578063a8b9d240146103e157600080fd5b80635183d6fd146102d45780636a474002146103395780636f2789ec1461034e578063715018a61461036457600080fd5b806327ce0147116101ab57806327ce01471461023e5780633009a6091461025e57806331e79db0146102745780634e7b827f1461029457600080fd5b806303c83302146101e557806309bbedde146101ed578063226cfa3d1461021157600080fd5b366101e0576101de61061d565b005b600080fd5b6101de61061d565b3480156101f957600080fd5b506008545b6040519081526020015b60405180910390f35b34801561021d57600080fd5b506101fe61022c3660046117f8565b600e6020526000908152604090205481565b34801561024a57600080fd5b506101fe6102593660046117f8565b610692565b34801561026a57600080fd5b506101fe600c5481565b34801561028057600080fd5b506101de61028f3660046117f8565b6106f5565b3480156102a057600080fd5b506102c46102af3660046117f8565b600d6020526000908152604090205460ff1681565b6040519015158152602001610208565b3480156102e057600080fd5b506102f46102ef366004611815565b61078d565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e082015261010001610208565b34801561034557600080fd5b506101de6107fa565b34801561035a57600080fd5b506101fe600f5481565b34801561037057600080fd5b506101de610806565b34801561038557600080fd5b506101fe60065481565b34801561039b57600080fd5b506000546001600160a01b03165b6040516001600160a01b039091168152602001610208565b3480156103cd57600080fd5b506101fe6103dc3660046117f8565b61087a565b3480156103ed57600080fd5b506101fe6103fc3660046117f8565b610881565b34801561040d57600080fd5b506101fe61041c3660046117f8565b6001600160a01b031660009081526003602052604090205490565b34801561044357600080fd5b506101fe6104523660046117f8565b60046020526000908152604090205481565b34801561047057600080fd5b506101fe60055481565b34801561048657600080fd5b506101de6108ad565b34801561049b57600080fd5b506102c46104aa36600461183c565b610a1c565b3480156104bb57600080fd5b506101fe7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104ef57600080fd5b506101de6104fe3660046117f8565b610ac8565b34801561050f57600080fd5b506101de61051e366004611875565b610b60565b34801561052f57600080fd5b50600c546101fe565b34801561054457600080fd5b506101de610553366004611815565b610c0e565b34801561056457600080fd5b506101fe60075481565b34801561057a57600080fd5b506101de6105893660046117f8565b610d77565b34801561059a57600080fd5b506102f46105a93660046117f8565b610daa565b3480156105ba57600080fd5b506103a97f000000000000000000000000000000000000000000000000000000000000000081565b3480156105ee57600080fd5b506106026105fd366004611815565b610e91565b60408051938452602084019290925290820152606001610208565b60405162461bcd60e51b815260206004820152603a60248201527f43616e6e6f742073656e6420424e42206469726563746c7920746f207472616360448201527f6b657220617320697420697320756e7265636f76657261626c6500000000000060648201526084015b60405180910390fd5b565b6001600160a01b0381166000908152600260209081526040808320546004909252822054600154600160801b926106e5926106e0926106da916106d59190610fae565b611037565b90611047565b611085565b6106ef91906118b7565b92915050565b6000546001600160a01b0316331461071f5760405162461bcd60e51b8152600401610687906118d9565b6001600160a01b0381166000908152600d60205260408120805460ff1916600117905561074d908290611098565b61075681611131565b6040516001600160a01b038216907fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b2590600090a250565b6000806000806000806000806107a260085490565b89106107c75750600096506000199550859450869350839250829150819050806107ef565b60006107d28a611264565b90506107dd81610daa565b98509850985098509850985098509850505b919395975091939597565b61080333611297565b50565b6000546001600160a01b031633146108305760405162461bcd60e51b8152600401610687906118d9565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60006106ef825b6001600160a01b0381166000908152600360205260408120546106ef906108a784610692565b9061144d565b6000546001600160a01b031633146108d75760405162461bcd60e51b8152600401610687906118d9565b60055415610690576040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610948573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096c919061190e565b905080600754101561098c576007546109859082611927565b9150610991565b600091505b8115610a18576005546109bf906109ac84600160801b610fae565b6109b691906118b7565b6001549061148f565b60015560405182815233907fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d784541165119060200160405180910390a2600654610a04908361148f565b600655600754610a14908361148f565b6007555b5050565b600080546001600160a01b03163314610a475760405162461bcd60e51b8152600401610687906118d9565b6000610a5284611297565b90508015610abe576001600160a01b0384166000818152600e6020526040908190204290555184151591907fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf09290610aac9085815260200190565b60405180910390a360019150506106ef565b5060009392505050565b6000546001600160a01b03163314610af25760405162461bcd60e51b8152600401610687906118d9565b6001600160a01b0381166000908152600d602052604090205460ff16610b1757600080fd5b6001600160a01b0381166000818152600d6020526040808220805460ff19169055517f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329190a250565b6000546001600160a01b03163314610b8a5760405162461bcd60e51b8152600401610687906118d9565b6001600160a01b0382166000908152600d602052604090205460ff16610a18577f00000000000000000000000000000000000000000000000000000000000000008110610bea57610bdb8282611098565b610be582826114ee565b610bfe565b610bf5826000611098565b610bfe82611131565b610c09826001610a1c565b505050565b6000546001600160a01b03163314610c385760405162461bcd60e51b8152600401610687906118d9565b6104b08110158015610c4d5750620151808111155b610ccd5760405162461bcd60e51b815260206004820152604560248201527f4469766964656e645f547261636b65723a20636c61696d57616974206d75737460448201527f206265207570646174656420746f206265747765656e203120616e6420323420606482015264686f75727360d81b608482015260a401610687565b600f548103610d445760405162461bcd60e51b815260206004820152603760248201527f4469766964656e645f547261636b65723a2043616e6e6f74207570646174652060448201527f636c61696d5761697420746f2073616d652076616c75650000000000000000006064820152608401610687565b600f5460405182907f474ea64804364a1e29a4487ddb63c3342a2dd826ccd8acf48825e680a0e6f20f90600090a3600f55565b6000546001600160a01b03163314610da15760405162461bcd60e51b8152600401610687906118d9565b610803816115ac565b806000808080808080610dbc8861166c565b9650600019955060008712610e1e57600c54871115610dea57600c54610de39088906116b1565b9550610e1e565b600c5460085460009110610dff576000610e0e565b600c54600854610e0e9161144d565b9050610e1a8882611047565b9650505b610e2788610881565b9450610e3288610692565b6001600160a01b0389166000908152600e6020526040902054909450925082610e5c576000610e6a565b600f54610e6a90849061148f565b9150428211610e7a576000610e84565b610e84824261144d565b9050919395975091939597565b60085460009081908190808203610eb3575050600c5460009250829150610fa7565b600c546000805a90506000805b8984108015610ece57508582105b15610f965784610edd8161193e565b60085490965086109050610ef057600094505b600060086000018681548110610f0857610f08611957565b60009182526020808320909101546001600160a01b0316808352600e909152604090912054909150610f39906116ee565b15610f5c57610f49816001610a1c565b15610f5c5781610f588161193e565b9250505b82610f668161193e565b93505060005a905080851115610f8d57610f8a610f83868361144d565b879061148f565b95505b9350610ec09050565b600c85905590975095509193505050505b9193909250565b600082600003610fc0575060006106ef565b6000610fcc838561196d565b905082610fd985836118b7565b146110305760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608401610687565b9392505050565b600081818112156106ef57600080fd5b600080611054838561198c565b9050600083121580156110675750838112155b8061107c575060008312801561107c57508381125b61103057600080fd5b60008082121561109457600080fd5b5090565b6001600160a01b0382166000908152600460205260409020805490829055808211156110f45760006110ca838361144d565b90506110d68482611715565b80600560008282546110e891906119cd565b90915550610c09915050565b80821015610c09576000611108828461144d565b9050611114848261176f565b80600560008282546111269190611927565b909155505050505050565b6001600160a01b0381166000908152600b602052604090205460ff166111545750565b6001600160a01b0381166000908152600b60209081526040808320805460ff1916905560098252808320839055600a90915281205460085490919061119b90600190611927565b90506000600860000182815481106111b5576111b5611957565b60009182526020808320909101546001600160a01b03908116808452600a909252604080842087905590871683528220919091556008805491925082918590811061120257611202611957565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600880548061123c5761123c6119e5565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b60006008600001828154811061127c5761127c611957565b6000918252602090912001546001600160a01b031692915050565b6000806112a383610881565b90508015611444576001600160a01b0383166000908152600360205260409020546112ce908261148f565b6001600160a01b038416600090815260036020526040902055600754811161130d5780600760008282546113029190611927565b909155506113139050565b60006007555b826001600160a01b03167fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d8260405161134e91815260200190565b60405180910390a260405163a9059cbb60e01b81526001600160a01b038481166004830152602482018390526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af11580156113ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ee91906119fb565b90508061143d576001600160a01b038416600090815260036020526040902054611418908361144d565b6001600160a01b03909416600090815260036020526040812094909455509192915050565b5092915050565b50600092915050565b600061103083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506117a9565b60008061149c83856119cd565b9050838110156110305760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610687565b6001600160a01b0382166000908152600b602052604090205460ff161561152c576001600160a01b0391909116600090815260096020526040902055565b6001600160a01b0382166000818152600b60209081526040808320805460ff191660019081179091556009835281842086905560088054600a909452918420839055820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03191690911790555050565b6001600160a01b0381166116115760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610687565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600b602052604081205460ff166116955750600019919050565b506001600160a01b03166000908152600a602052604090205490565b6000806116be8385611a18565b9050600083121580156116d15750838113155b8061107c575060008312801561107c575083811361103057600080fd5b60004282111561170057506000919050565b600f5461170d428461144d565b101592915050565b61174f6117306106d583600154610fae90919063ffffffff16565b6001600160a01b038416600090815260026020526040902054906116b1565b6001600160a01b0390921660009081526002602052604090209190915550565b61174f61178a6106d583600154610fae90919063ffffffff16565b6001600160a01b03841660009081526002602052604090205490611047565b600081848411156117cd5760405162461bcd60e51b81526004016106879190611a57565b5060006117da8486611927565b95945050505050565b6001600160a01b038116811461080357600080fd5b60006020828403121561180a57600080fd5b8135611030816117e3565b60006020828403121561182757600080fd5b5035919050565b801515811461080357600080fd5b6000806040838503121561184f57600080fd5b823561185a816117e3565b9150602083013561186a8161182e565b809150509250929050565b6000806040838503121561188857600080fd5b8235611893816117e3565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000826118d457634e487b7160e01b600052601260045260246000fd5b500490565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561192057600080fd5b5051919050565b600082821015611939576119396118a1565b500390565b600060018201611950576119506118a1565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615611987576119876118a1565b500290565b600080821280156001600160ff1b03849003851316156119ae576119ae6118a1565b600160ff1b83900384128116156119c7576119c76118a1565b50500190565b600082198211156119e0576119e06118a1565b500190565b634e487b7160e01b600052603160045260246000fd5b600060208284031215611a0d57600080fd5b81516110308161182e565b60008083128015600160ff1b850184121615611a3657611a366118a1565b6001600160ff1b0384018313811615611a5157611a516118a1565b50500390565b600060208083528351808285015260005b81811015611a8457858101830151858201604001528201611a68565b81811115611a96576000604083870101525b50601f01601f191692909201604001939250505056fea2646970667358221220ed4fbbe316118c57be5db0bf28466d82e4727bb327c4bb5e80c25834d89e622b64736f6c634300080d0033
Deployed ByteCode Sourcemap
60295:14165:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61728:27;;;;;;;;;160:25:1;;;148:2;133:18;61728:27:0;;;;;;;;61828:26;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;645:32:1;;;627:51;;709:2;694:18;;687:34;;;;737:18;;;730:34;795:2;780:18;;773:34;614:3;599:19;61828:26:0;381:432:1;61910:45:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1408:25:1;;;1464:2;1449:18;;1442:34;;;;1492:18;;;1485:34;1396:2;1381:18;61910:45:0;1206:319:1;60441:38:0;;;;;-1:-1:-1;;;;;60441:38:0;;;;;;-1:-1:-1;;;;;1726:32:1;;;1708:51;;1696:2;1681:18;60441:38:0;1530:235:1;70786:1383:0;;;;;;:::i;:::-;;:::i;:::-;;73204:220;;;;;;:::i;:::-;;:::i;63905:1487::-;;;;;;:::i;:::-;;:::i;74341:116::-;;;:::i;66838:275::-;;;;;;:::i;:::-;;:::i;60488:80::-;;;;;68939:190;;;:::i;20848:140::-;;;:::i;61245:36::-;;;;;63690:207;;;:::i;73729:133::-;;;:::i;61762:30::-;;;;;;63419:104;;;:::i;61614:26::-;;;;;;20206:79;20244:7;20271:6;-1:-1:-1;;;;;20271:6:0;20206:79;;74141:192;;;;;;:::i;:::-;;:::i;73432:289::-;;;:::i;61647:36::-;;;;;;63531:151;;;;;;:::i;:::-;;:::i;73870:263::-;;;;;;:::i;:::-;;:::i;63241:170::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;61330:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;69166:1564;;;;;;:::i;:::-;;:::i;61391:58::-;;;;;;:::i;:::-;;;;;;;;;;;;;;61555:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4226:14:1;;4219:22;4201:41;;4189:2;4174:18;61555:50:0;4061:187:1;72240:815:0;;;:::i;61690:31::-;;;;;;65400:1345;;;;;;:::i;:::-;;:::i;21143:109::-;;;;;;:::i;:::-;;:::i;67178:747::-;;;;;;:::i;:::-;;:::i;61288:35::-;;;;;61828:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;61828:26:0;;;;-1:-1:-1;61828:26:0;;;:::o;70786:1383::-;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;;;;;;;;;59348:1;60079:7;:18;70879:10:::1;70862:28;::::0;;;:16:::1;:28;::::0;;;;;70894:15:::1;-1:-1:-1::0;70862:47:0::1;70854:92;;;::::0;-1:-1:-1;;;70854:92:0;;4815:2:1;70854:92:0::1;::::0;::::1;4797:21:1::0;;;4834:18;;;4827:30;4893:34;4873:18;;;4866:62;4945:18;;70854:92:0::1;4613:356:1::0;70854:92:0::1;70967:21;70991:8;71000:1;70991:11;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;71046:10:::1;71037:20:::0;;:8:::1;:20:::0;;;;;;70991:11:::1;::::0;;::::1;;::::0;-1:-1:-1;71037:20:0;71070:13:::1;::::0;:10:::1;:13::i;:::-;71094:15;71112:80;71176:4;:15;;;71112:59;71166:4;71112:49;71138:4;:22;;;71112:4;:21;;;:25;;:49;;;;:::i;:::-;:53:::0;::::1;:59::i;:::-;:63:::0;::::1;:80::i;:::-;71094:98;;71217:18;:16;:18::i;:::-;71206:7;:29;71203:88;;71261:18;:16;:18::i;:::-;71251:28;;71203:88;71304:11:::0;;71301:102:::1;;71332:59;::::0;-1:-1:-1;;;71332:59:0;;-1:-1:-1;;;;;71332:11:0::1;:20;::::0;::::1;::::0;:59:::1;::::0;71369:10:::1;::::0;71383:7;;71332:59:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;71301:102;71418:11:::0;;71415:347:::1;;71461:7;71446:4;:11;;;:22;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;71556:3:0::1;::::0;-1:-1:-1;71521:32:0::1;71542:10;71521:20;:32::i;:::-;71507:11:::0;;:46:::1;::::0;;::::1;:::i;:::-;:52;;;;:::i;:::-;71483:4;:21;;:76;;;;71589:7;71574:11;;:22;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;71681:3:0::1;::::0;-1:-1:-1;71646:32:0::1;71667:10;71646:20;:32::i;:::-;71636:42;::::0;:7;:42:::1;:::i;:::-;:48;;;;:::i;:::-;71611:21;;:73;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;71699:12:0;;:51:::1;::::0;-1:-1:-1;;;71699:51:0;;-1:-1:-1;;;;;71699:12:0;;::::1;::::0;:21:::1;::::0;:51:::1;::::0;71729:10:::1;::::0;71742:7;;71699:51:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;71415:347;71774:15;::::0;71822:11;;71774:60:::1;::::0;-1:-1:-1;;;71774:60:0;;-1:-1:-1;;;;;71774:15:0;;::::1;::::0;:26:::1;::::0;:60:::1;::::0;71809:10:::1;::::0;71822:11;71774:60:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;71863:59;71917:4;71863:49;71889:4;:22;;;71863:4;:21;;;:25;;:49;;;;:::i;:59::-;71845:15;::::0;::::1;:77:::0;71946:11;;:15;71943:172:::1;;72026:12;::::0;72008:30:::1;::::0;:15:::1;:30;:::i;:::-;71994:10;71977:28;::::0;;;:16:::1;:28;::::0;;;;:61;71943:172:::1;;;72088:10;72102:1;72071:28:::0;;;:16:::1;:28;::::0;;;;:32;71943:172:::1;72132:29;::::0;160:25:1;;;72141:10:0::1;::::0;72132:29:::1;::::0;148:2:1;133:18;72132:29:0::1;;;;;;;;-1:-1:-1::0;;59304:1:0;60258:22;;-1:-1:-1;;70786:1383:0:o;73204:220::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;73303:18:::1;:16;:18::i;:::-;73292:7;:29;;73284:71;;;::::0;-1:-1:-1;;;73284:71:0;;7570:2:1;73284:71:0::1;::::0;::::1;7552:21:1::0;7609:2;7589:18;;;7582:30;7648:31;7628:18;;;7621:59;7697:18;;73284:71:0::1;7368:353:1::0;73284:71:0::1;73366:50;::::0;-1:-1:-1;;;73366:50:0;;-1:-1:-1;;;;;73366:11:0::1;:20;::::0;::::1;::::0;:50:::1;::::0;73395:10:::1;::::0;73408:7;;73366:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;73204:220:::0;:::o;63905:1487::-;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;59348:1;60079:7;:18;-1:-1:-1;;;;;64001:29:0;::::1;;::::0;;;:17:::1;:29;::::0;;;;;::::1;;63993:72;;;::::0;-1:-1:-1;;;63993:72:0;;7928:2:1;63993:72:0::1;::::0;::::1;7910:21:1::0;7967:2;7947:18;;;7940:30;8006:32;7986:18;;;7979:60;8056:18;;63993:72:0::1;7726:354:1::0;63993:72:0::1;64101:10;64084:28;::::0;;;:16:::1;:28;::::0;;;;;;;-1:-1:-1;;;;;64084:40:0;::::1;::::0;;;;;;;64136:1:::1;::::0;64084:49:::1;::::0;:47:::1;:49::i;:::-;:53;64076:106;;;::::0;-1:-1:-1;;;64076:106:0;;8287:2:1;64076:106:0::1;::::0;::::1;8269:21:1::0;8326:2;8306:18;;;8299:30;8365:34;8345:18;;;8338:62;-1:-1:-1;;;8416:18:1;;;8409:38;8464:19;;64076:106:0::1;8085:404:1::0;64076:106:0::1;64290:10;64203:11;64281:20:::0;;;:8:::1;:20;::::0;;;;64336:8:::1;:11:::0;;64225:10;;64203:11;64336:8;64203:11;;64336::::1;;;;:::i;:::-;;::::0;;;::::1;::::0;;;64368:24:::1;::::0;-1:-1:-1;;;64368:24:0;;64336:11:::1;64368:24:::0;;::::1;160:25:1::0;;;64336:11:0;;::::1;;::::0;-1:-1:-1;64404:4:0::1;::::0;-1:-1:-1;;;;;64368:15:0;::::1;::::0;::::1;::::0;133:18:1;;64368:24:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;64368:41:0::1;;64360:83;;;::::0;-1:-1:-1;;;64360:83:0;;8952:2:1;64360:83:0::1;::::0;::::1;8934:21:1::0;8991:2;8971:18;;;8964:30;9030:31;9010:18;;;9003:59;9079:18;;64360:83:0::1;8750:353:1::0;64360:83:0::1;64456:13;64467:1;64456:10;:13::i;:::-;64486:11:::0;;:15;64482:371:::1;;64518:15;64536:80;64600:4;:15;;;64536:59;64590:4;64536:49;64562:4;:22;;;64536:4;:21;;;:25;;:49;;;;:::i;:80::-;64518:98;;64645:18;:16;:18::i;:::-;64634:7;:29;64631:96;;64693:18;:16;:18::i;:::-;64683:28;;64631:96;64744:11:::0;;64741:101:::1;;64776:50;::::0;-1:-1:-1;;;64776:50:0;;-1:-1:-1;;;;;64776:11:0::1;:20;::::0;::::1;::::0;:50:::1;::::0;64805:10:::1;::::0;64818:7;;64776:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;64741:101;64503:350;64482:371;64865:52;::::0;-1:-1:-1;;;64865:52:0;;64882:10:::1;64865:52;::::0;::::1;9348:34:1::0;64902:4:0::1;9398:18:1::0;;;9391:43;9450:18;;;9443:34;;;-1:-1:-1;;;;;64865:16:0;::::1;::::0;::::1;::::0;9283:18:1;;64865:52:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;64951:10:0::1;64928:34;::::0;;;:22:::1;:34;::::0;;;;:39;;64966:1:::1;::::0;-1:-1:-1;64928:34:0;;-1:-1:-1;64928:39:0::1;::::0;64966:1;;64928:39:::1;:::i;:::-;::::0;;;-1:-1:-1;;64995:10:0::1;64978:28;::::0;;;:16:::1;:28;::::0;;;;;;;-1:-1:-1;;;;;64978:40:0;::::1;::::0;;;;;;;:53:::1;::::0;65023:7;64978:44:::1;:53::i;:::-;;65069:4;:21;;;65044;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;65174:3:0::1;::::0;-1:-1:-1;65139:32:0::1;65160:10;65139:20;:32::i;:::-;65125:11:::0;;:46:::1;::::0;;::::1;:::i;:::-;:52;;;;:::i;:::-;65101:21;::::0;::::1;:76:::0;;;65188:21:::1;:46:::0;;:21:::1;::::0;:46:::1;::::0;65101:76;;65188:46:::1;:::i;:::-;::::0;;;-1:-1:-1;;65291:22:0::1;::::0;::::1;::::0;65265:21:::1;::::0;::::1;::::0;:59:::1;::::0;65319:4:::1;::::0;65265:49:::1;::::0;:25:::1;:49::i;:59::-;65247:15;::::0;::::1;:77:::0;65342:42:::1;::::0;65373:10:::1;::::0;65364:7;;-1:-1:-1;;;;;65342:42:0;::::1;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;;59304:1:0;60258:22;;-1:-1:-1;;;63905:1487:0:o;74341:116::-;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;59348:1;60079:7;:18;;;74391:15;:58:::1;::::0;-1:-1:-1;;;74391:58:0;;74430:10:::1;74391:58;::::0;::::1;9672:51:1::0;74391:15:0::1;9739:18:1::0;;;9732:50;-1:-1:-1;;;;;74391:15:0;;::::1;::::0;:30:::1;::::0;9645:18:1;;74391:58:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;59304:1:0;60258:22;;74341:116::o;66838:275::-;-1:-1:-1;;;;;66928:30:0;;66905:7;66928:30;;;:22;:30;;;;;;:35;;66925:76;;-1:-1:-1;66986:3:0;;66838:275;-1:-1:-1;66838:275:0:o;66925:76::-;-1:-1:-1;;;;;67071:30:0;;;;;;:22;:30;;;;;;:33;;67102:2;67071:33;:::i;:::-;67064:41;;:3;:41;:::i;:::-;67057:48;66838:275;-1:-1:-1;;66838:275:0:o;68939:190::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;69011:8:::1;:15:::0;68994:14:::1;69037:85;69065:6;69059:3;:12;69037:85;;;69095:15;69106:3;69095:10;:15::i;:::-;69073:5;::::0;::::1;:::i;:::-;;;69037:85;;20848:140:::0;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;20947:1:::1;20931:6:::0;;20910:40:::1;::::0;-1:-1:-1;;;;;20931:6:0;;::::1;::::0;20910:40:::1;::::0;20947:1;;20910:40:::1;20978:1;20961:19:::0;;-1:-1:-1;;;;;;20961:19:0::1;::::0;;20848:140::o;63690:207::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;63751:8:::1;63760:1;63751:11;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;63786:11;63751:46;63743:86;;;::::0;-1:-1:-1;;;63743:86:0;;10135:2:1;63743:86:0::1;::::0;::::1;10117:21:1::0;10174:2;10154:18;;;10147:30;10213:29;10193:18;;;10186:57;10260:18;;63743:86:0::1;9933:351:1::0;63743:86:0::1;63874:15;63840:8;63849:1;63840:11;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;:49;;;;63690:207::o:0;73729:133::-;73843:11;;73804:36;;-1:-1:-1;;;73804:36:0;;73834:4;73804:36;;;1708:51:1;73778:7:0;;73843:11;-1:-1:-1;;;;;73804:11:0;:21;;;;1681:18:1;;73804:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;;;:::i;:::-;73797:57;;73729:133;:::o;63419:104::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;63471:13:::1;63482:1;63471:10;:13::i;:::-;63514:1;63495:16;:20:::0;63419:104::o;74141:192::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;74248:2:::1;74230:14;:20;;74222:60;;;::::0;-1:-1:-1;;;74222:60:0;;10680:2:1;74222:60:0::1;::::0;::::1;10662:21:1::0;10719:2;10699:18;;;10692:30;10758:29;10738:18;;;10731:57;10805:18;;74222:60:0::1;10478:351:1::0;74222:60:0::1;74293:15;:32:::0;74141:192::o;73432:289::-;73484:7;73504:21;73528:8;73537:1;73528:11;;;;;;;;:::i;:::-;;;;;;;;;;;73504:35;;73580:15;73553:4;:24;;;:42;73550:81;;;73618:1;73611:8;;;73432:289;:::o;73550:81::-;73696:16;;73668:24;;;;73650:42;;:15;:42;:::i;:::-;73649:63;;;;:::i;:::-;73641:72;;;73432:289;:::o;63531:151::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;63628:29:0;;;::::1;;::::0;;;:17:::1;:29;::::0;;;;:46;;-1:-1:-1;;63628:46:0::1;::::0;::::1;;::::0;;;::::1;::::0;;63531:151::o;73870:263::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;73989:8:::1;73969:16;;:28;;73961:84;;;::::0;-1:-1:-1;;;73961:84:0;;11036:2:1;73961:84:0::1;::::0;::::1;11018:21:1::0;11075:2;11055:18;;;11048:30;11114:34;11094:18;;;11087:62;-1:-1:-1;;;11165:18:1;;;11158:41;11216:19;;73961:84:0::1;10834:407:1::0;73961:84:0::1;74056:13;74067:1;74056:10;:13::i;:::-;74099:26;:19:::0;74121:4:::1;74099:26;:::i;:::-;74080:16;:45:::0;-1:-1:-1;73870:263:0:o;63241:170::-;-1:-1:-1;;;;;63358:24:0;;;;;;;:16;:24;;;;;;;;:36;;;;;;;;;63323:16;;63358:45;;:43;:45::i;:::-;63351:52;63241:170;-1:-1:-1;;;63241:170:0:o;69166:1564::-;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;59348:1;60079:7;:18;69251:10:::1;69234:28;::::0;;;:16:::1;:28;::::0;;;;;:33;;69231:125:::1;;69332:12;::::0;69314:30:::1;::::0;:15:::1;:30;:::i;:::-;69300:10;69283:28;::::0;;;:16:::1;:28;::::0;;;;:61;69231:125:::1;69366:21;69390:8;69399:1;69390:11;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;69445:10:::1;69436:20:::0;;:8:::1;:20:::0;;;;;;69390:11:::1;::::0;;::::1;;::::0;-1:-1:-1;69436:20:0;69469:13:::1;::::0;:10:::1;:13::i;:::-;69497:11:::0;;:15;69493:371:::1;;69529:15;69547:80;69611:4;:15;;;69547:59;69601:4;69547:49;69573:4;:22;;;69547:4;:21;;;:25;;:49;;;;:::i;:80::-;69529:98;;69656:18;:16;:18::i;:::-;69645:7;:29;69642:96;;69704:18;:16;:18::i;:::-;69694:28;;69642:96;69755:11:::0;;69752:101:::1;;69787:50;::::0;-1:-1:-1;;;69787:50:0;;-1:-1:-1;;;;;69787:11:0::1;:20;::::0;::::1;::::0;:50:::1;::::0;69816:10:::1;::::0;69829:7;;69787:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;69752:101;69514:350;69493:371;69874:25;69917:11:::0;;69914:602:::1;;69970:12:::0;;:37:::1;::::0;-1:-1:-1;;;69970:37:0;;70001:4:::1;69970:37;::::0;::::1;1708:51:1::0;69945:22:0::1;::::0;-1:-1:-1;;;;;69970:12:0::1;::::0;:22:::1;::::0;1681:18:1;;69970:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70022:12:::0;;:70:::1;::::0;-1:-1:-1;;;70022:70:0;;70056:10:::1;70022:70;::::0;::::1;9348:34:1::0;70077:4:0::1;9398:18:1::0;;;9391:43;9450:18;;;9443:34;;;69945:62:0;;-1:-1:-1;;;;;;70022:12:0::1;::::0;:25:::1;::::0;9283:18:1;;70022:70:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;70127:12:0;;:37:::1;::::0;-1:-1:-1;;;70127:37:0;;70158:4:::1;70127:37;::::0;::::1;1708:51:1::0;70167:14:0;;-1:-1:-1;;;;;70127:12:0::1;::::0;:22:::1;::::0;1681:18:1;;70127:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;;:::i;:::-;70107:74;;70221:4;:21;;;70196;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;70271:11:0;;:34:::1;::::0;70287:17;70271:15:::1;:34::i;:::-;70257:48:::0;;70393:3:::1;70358:32;70379:10;70358:20;:32::i;:::-;70344:11:::0;;:46:::1;::::0;;::::1;:::i;:::-;:52;;;;:::i;:::-;70320:4;:21;;:76;;;;70426:17;70411:11;;:32;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;70483:21:0::1;::::0;::::1;::::0;70458::::1;:46:::0;;:21:::1;::::0;:46:::1;::::0;70483:21;;70458:46:::1;:::i;:::-;::::0;;;-1:-1:-1;;;69914:602:0::1;70528:15;::::0;70576:11;;70528:60:::1;::::0;-1:-1:-1;;;70528:60:0;;-1:-1:-1;;;;;70528:15:0;;::::1;::::0;:26:::1;::::0;:60:::1;::::0;70563:10:::1;::::0;70576:11;70528:60:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;70617:59;70671:4;70617:49;70643:4;:22;;;70617:4;:21;;;:25;;:49;;;;:::i;:59::-;70599:15;::::0;::::1;:77:::0;70694:28:::1;::::0;160:25:1;;;70702:10:0::1;::::0;70694:28:::1;::::0;148:2:1;133:18;70694:28:0::1;14:177:1::0;72240:815:0;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;59348:1;60079:7;:18;;;;72302:21:::1;72326:8;72335:1;72326:11;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;72381:10:::1;72372:20:::0;;:8:::1;:20:::0;;;;;;72421:11;;72443::::1;:22:::0;;72326:11:::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;72372:20:0;;72421:11;;;;72443;72326;72443:22:::1;::::0;72421:11;;72443:22:::1;:::i;:::-;::::0;;;-1:-1:-1;;72501:21:0::1;::::0;::::1;::::0;72476::::1;:46:::0;;:21:::1;::::0;:46:::1;::::0;72501:21;;72476:46:::1;:::i;:::-;::::0;;;-1:-1:-1;;72636:10:0::1;72619:28;::::0;;;:16:::1;:28;::::0;;;;;72651:15:::1;-1:-1:-1::0;72616:120:0::1;;72721:3;72703:15;;72693:7;:25;;;;:::i;:::-;:31;;;;:::i;:::-;72682:42;::::0;;::::1;:::i;:::-;;;72616:120;72763:10;72777:1;72746:28:::0;;;:16:::1;:28;::::0;;;;;:32;;;;72789:12;;:51;;-1:-1:-1;;;72789:51:0;;-1:-1:-1;;;;;72789:12:0;;::::1;::::0;:21:::1;::::0;:51:::1;::::0;72763:10;72832:7;;72789:51:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;72865:1:0::1;72851:15:::0;;;72877:21:::1;::::0;::::1;:25:::0;;;72913:15:::1;::::0;;::::1;:19:::0;;;72943:15;:50:::1;::::0;-1:-1:-1;;;72943:50:0;;-1:-1:-1;;;;;72943:15:0;;::::1;::::0;:26:::1;::::0;:50:::1;::::0;72978:10:::1;::::0;72943:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;73009:38:0::1;::::0;160:25:1;;;73027:10:0::1;::::0;-1:-1:-1;73009:38:0::1;::::0;-1:-1:-1;148:2:1;133:18;73009:38:0::1;;;;;;;-1:-1:-1::0;;59304:1:0;60258:22;;-1:-1:-1;72240:815:0:o;65400:1345::-;59348:1;59946:7;;:19;59938:63;;;;-1:-1:-1;;;59938:63:0;;;;;;;:::i;:::-;59348:1;60079:7;:18;65515:10:::1;65498:28;::::0;;;:16:::1;:28;::::0;;;;;;;-1:-1:-1;;;;;65498:40:0;::::1;::::0;;;;;;;:58:::1;::::0;65548:7;65498:49:::1;:58::i;:::-;65490:144;;;::::0;-1:-1:-1;;;65490:144:0;;11751:2:1;65490:144:0::1;::::0;::::1;11733:21:1::0;11790:2;11770:18;;;11763:30;11829:34;11809:18;;;11802:62;11900:34;11880:18;;;11873:62;-1:-1:-1;;;11951:19:1;;;11944:40;12001:19;;65490:144:0::1;11549:477:1::0;65490:144:0::1;65734:10;65655:11;65725:20:::0;;;:8:::1;:20;::::0;;;;65780:8:::1;:11:::0;;65677:10;;65655:11;65780:8;65655:11;;65780::::1;;;;:::i;:::-;;;;;;;;;;;65756:35;;65804:13;65815:1;65804:10;:13::i;:::-;65834:11:::0;;:15;65830:371:::1;;65866:15;65884:80;65948:4;:15;;;65884:59;65938:4;65884:49;65910:4;:22;;;65884:4;:21;;;:25;;:49;;;;:::i;:80::-;65866:98;;65993:18;:16;:18::i;:::-;65982:7;:29;65979:96;;66041:18;:16;:18::i;:::-;66031:28;;65979:96;66092:11:::0;;66089:101:::1;;66124:50;::::0;-1:-1:-1;;;66124:50:0;;-1:-1:-1;;;;;66124:11:0::1;:20;::::0;::::1;::::0;:50:::1;::::0;66153:10:::1;::::0;66166:7;;66124:50:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;66089:101;65851:350;65830:371;66213:52;::::0;-1:-1:-1;;;66213:52:0;;66238:4:::1;66213:52;::::0;::::1;9348:34:1::0;66245:10:0::1;9398:18:1::0;;;9391:43;9450:18;;;9443:34;;;-1:-1:-1;;;;;66213:16:0;::::1;::::0;::::1;::::0;9283:18:1;;66213:52:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;66299:10:0::1;66276:34;::::0;;;:22:::1;:34;::::0;;;;:39;;66314:1:::1;::::0;-1:-1:-1;66276:34:0;;-1:-1:-1;66276:39:0::1;::::0;66314:1;;66276:39:::1;:::i;:::-;::::0;;;-1:-1:-1;;66343:10:0::1;66326:28;::::0;;;:16:::1;:28;::::0;;;;;;;-1:-1:-1;;;;;66326:40:0;::::1;::::0;;;;;;;:56:::1;::::0;66374:7;66326:47:::1;:56::i;:::-;;66420:4;:21;;;66395;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;66525:3:0::1;::::0;-1:-1:-1;66490:32:0::1;66511:10;66490:20;:32::i;:::-;66476:11:::0;;:46:::1;::::0;;::::1;:::i;:::-;:52;;;;:::i;:::-;66452:21;::::0;::::1;:76:::0;;;66539:21:::1;:46:::0;;:21:::1;::::0;:46:::1;::::0;66452:76;;66539:46:::1;:::i;:::-;::::0;;;-1:-1:-1;;66642:22:0::1;::::0;::::1;::::0;66616:21:::1;::::0;::::1;::::0;:59:::1;::::0;66670:4:::1;::::0;66616:49:::1;::::0;:25:::1;:49::i;:59::-;66598:15;::::0;::::1;:77:::0;66693:44:::1;::::0;66726:10:::1;::::0;66717:7;;-1:-1:-1;;;;;66693:44:0;::::1;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;;59304:1:0;60258:22;;-1:-1:-1;;;65400:1345:0:o;21143:109::-;20418:6;;-1:-1:-1;;;;;20418:6:0;13492:10;20418:22;20410:67;;;;-1:-1:-1;;;20410:67:0;;;;;;;:::i;:::-;21216:28:::1;21235:8;21216:18;:28::i;:::-;21143:109:::0;:::o;67178:747::-;67239:7;67259:21;67283:8;67292:1;67283:11;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;67329:15:0;;;;:8;:15;;;;;;;67358:24;67283:11;;;;;;;67358:24;;;;67283:11;;-1:-1:-1;67386:11:0;67358:39;67355:78;;-1:-1:-1;67420:1:0;;67178:747;-1:-1:-1;;;67178:747:0:o;67355:78::-;67471:22;;;;67523:21;;67577:24;;;;67559:15;:42;:59;;;;-1:-1:-1;67605:13:0;;;67559:59;67555:270;;;67635:19;67657:63;67704:15;;67657:42;67683:4;:15;;;67657:21;:19;:21::i;:::-;:25;;:42::i;:63::-;67635:85;-1:-1:-1;67755:58:0;67777:35;67803:8;67777:21;67635:85;67793:4;67777:15;:21::i;:35::-;67755:17;;:21;:58::i;:::-;67735:78;;67620:205;67555:270;67842:75;67901:4;:15;;;67842:54;67891:4;67842:44;67868:17;67842:4;:21;;;:25;;:44;;;;:::i;:75::-;67835:82;67178:747;-1:-1:-1;;;;;;67178:747:0:o;68001:855::-;68103:28;;-1:-1:-1;;;68103:28:0;;68125:4;68103:28;;;1708:51:1;68134:1:0;;68103:3;-1:-1:-1;;;;;68103:13:0;;;;1681:18:1;;68103:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;68100:131;;;68172:15;;68190:28;;-1:-1:-1;;;68190:28:0;;68212:4;68190:28;;;1708:51:1;-1:-1:-1;;;;;68151:3:0;:12;;;;;68172:15;;;68151:12;;68190:13;;1681:18:1;;68190:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68151:68;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;68100:131;68247:15;;;;;;;;;-1:-1:-1;;;;;68247:15:0;-1:-1:-1;;;;;68247:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68300:21;68324:8;68333:4;68324:14;;;;;;;;:::i;:::-;;;;;;;;;;;68300:38;;68372:4;:24;;;68353:15;:43;68349:82;;68413:7;68001:855;:::o;68349:82::-;68460:21;;68441:16;68496:13;;;68492:109;;-1:-1:-1;68553:15:0;68526:24;;;;:42;-1:-1:-1;68001:855:0:o;68492:109::-;68611:19;68633:63;68680:15;;68633:42;68659:4;:15;;;68633:21;:19;:21::i;:63::-;68611:85;-1:-1:-1;68732:63:0;68759:35;68785:8;68759:21;68611:85;68775:4;68759:15;:21::i;:35::-;68732:22;;;;;:26;:63::i;:::-;68707:22;;;:88;-1:-1:-1;;68833:15:0;68806:24;;;;:42;-1:-1:-1;68001:855:0:o;23822:471::-;23880:7;24125:1;24130;24125:6;24121:47;;-1:-1:-1;24155:1:0;24148:8;;24121:47;24180:9;24192:5;24196:1;24192;:5;:::i;:::-;24180:17;-1:-1:-1;24225:1:0;24216:5;24220:1;24180:17;24216:5;:::i;:::-;:10;24208:56;;;;-1:-1:-1;;;24208:56:0;;12233:2:1;24208:56:0;;;12215:21:1;12272:2;12252:18;;;12245:30;12311:34;12291:18;;;12284:62;-1:-1:-1;;;12362:18:1;;;12355:31;12403:19;;24208:56:0;12031:397:1;24769:132:0;24827:7;24854:39;24858:1;24861;24854:39;;;;;;;;;;;;;;;;;:3;:39::i;22898:136::-;22956:7;22983:43;22987:1;22990;22983:43;;;;;;;;;;;;;;;;;:3;:43::i;11167:114::-;11227:7;11254:19;11262:3;4196:18;;4113:109;10405:131;10472:4;10496:32;10501:3;10521:5;10496:4;:32::i;12322:263::-;12382:16;12411:22;12436:19;12444:3;12436:7;:19::i;22434:181::-;22492:7;;22524:5;22528:1;22524;:5;:::i;:::-;22512:17;;22553:1;22548;:6;;22540:46;;;;-1:-1:-1;;;22540:46:0;;12635:2:1;22540:46:0;;;12617:21:1;12674:2;12654:18;;;12647:30;12713:29;12693:18;;;12686:57;12760:18;;22540:46:0;12433:351:1;10935:146:0;11012:4;3995:19;;;:12;;;:19;;;;;;:24;;11036:37;3898:129;10712:137;10782:4;10806:35;10814:3;10834:5;10806:7;:35::i;21358:229::-;-1:-1:-1;;;;;21432:22:0;;21424:73;;;;-1:-1:-1;;;21424:73:0;;12991:2:1;21424:73:0;;;12973:21:1;13030:2;13010:18;;;13003:30;13069:34;13049:18;;;13042:62;-1:-1:-1;;;13120:18:1;;;13113:36;13166:19;;21424:73:0;12789:402:1;21424:73:0;21534:6;;;21513:38;;-1:-1:-1;;;;;21513:38:0;;;;21534:6;;;21513:38;;;21562:6;:17;;-1:-1:-1;;;;;;21562:17:0;-1:-1:-1;;;;;21562:17:0;;;;;;;;;;21358:229::o;25397:312::-;25517:7;25552:12;25545:5;25537:28;;;;-1:-1:-1;;;25537:28:0;;;;;;;;:::i;:::-;-1:-1:-1;25576:9:0;25588:5;25592:1;25588;:5;:::i;:::-;25576:17;25397:312;-1:-1:-1;;;;;25397:312:0:o;23337:226::-;23457:7;23493:12;23485:6;;;;23477:29;;;;-1:-1:-1;;;23477:29:0;;;;;;;;:::i;:::-;-1:-1:-1;23517:9:0;23529:5;23533:1;23529;:5;:::i;1802:414::-;1865:4;3995:19;;;:12;;;:19;;;;;;1882:327;;-1:-1:-1;1925:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;2108:18;;2086:19;;;:12;;;:19;;;;;;:40;;;;2141:11;;1882:327;-1:-1:-1;2192:5:0;2185:12;;5246:111;5302:16;5338:3;:11;;5331:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5246:111;;;:::o;2392:1420::-;2458:4;2597:19;;;:12;;;:19;;;;;;2633:15;;2629:1176;;3008:21;3032:14;3045:1;3032:10;:14;:::i;:::-;3081:18;;3008:38;;-1:-1:-1;3061:17:0;;3081:22;;3102:1;;3081:22;:::i;:::-;3061:42;;3137:13;3124:9;:26;3120:405;;3171:17;3191:3;:11;;3203:9;3191:22;;;;;;;;:::i;:::-;;;;;;;;;3171:42;;3345:9;3316:3;:11;;3328:13;3316:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;3430:23;;;:12;;;:23;;;;;:36;;;3120:405;3606:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;3701:3;:12;;:19;3714:5;3701:19;;;;;;;;;;;3694:26;;;3744:4;3737:11;;;;;;;2629:1176;3788:5;3781:12;;;;;196:180:1;255:6;308:2;296:9;287:7;283:23;279:32;276:52;;;324:1;321;314:12;276:52;-1:-1:-1;347:23:1;;196:180;-1:-1:-1;196:180:1:o;818:131::-;-1:-1:-1;;;;;893:31:1;;883:42;;873:70;;939:1;936;929:12;954:247;1013:6;1066:2;1054:9;1045:7;1041:23;1037:32;1034:52;;;1082:1;1079;1072:12;1034:52;1121:9;1108:23;1140:31;1165:5;1140:31;:::i;1770:315::-;1838:6;1846;1899:2;1887:9;1878:7;1874:23;1870:32;1867:52;;;1915:1;1912;1905:12;1867:52;1954:9;1941:23;1973:31;1998:5;1973:31;:::i;:::-;2023:5;2075:2;2060:18;;;;2047:32;;-1:-1:-1;;;1770:315:1:o;2521:118::-;2607:5;2600:13;2593:21;2586:5;2583:32;2573:60;;2629:1;2626;2619:12;2644:382;2709:6;2717;2770:2;2758:9;2749:7;2745:23;2741:32;2738:52;;;2786:1;2783;2776:12;2738:52;2825:9;2812:23;2844:31;2869:5;2844:31;:::i;:::-;2894:5;-1:-1:-1;2951:2:1;2936:18;;2923:32;2964:30;2923:32;2964:30;:::i;:::-;3013:7;3003:17;;;2644:382;;;;;:::o;3031:388::-;3099:6;3107;3160:2;3148:9;3139:7;3135:23;3131:32;3128:52;;;3176:1;3173;3166:12;3128:52;3215:9;3202:23;3234:31;3259:5;3234:31;:::i;:::-;3284:5;-1:-1:-1;3341:2:1;3326:18;;3313:32;3354:33;3313:32;3354:33;:::i;3424:632::-;3595:2;3647:21;;;3717:13;;3620:18;;;3739:22;;;3566:4;;3595:2;3818:15;;;;3792:2;3777:18;;;3566:4;3861:169;3875:6;3872:1;3869:13;3861:169;;;3936:13;;3924:26;;4005:15;;;;3970:12;;;;3897:1;3890:9;3861:169;;;-1:-1:-1;4047:3:1;;3424:632;-1:-1:-1;;;;;;3424:632:1:o;4253:355::-;4455:2;4437:21;;;4494:2;4474:18;;;4467:30;4533:33;4528:2;4513:18;;4506:61;4599:2;4584:18;;4253:355::o;4974:127::-;5035:10;5030:3;5026:20;5023:1;5016:31;5066:4;5063:1;5056:15;5090:4;5087:1;5080:15;5106:282;-1:-1:-1;;;;;5306:32:1;;;;5288:51;;5370:2;5355:18;;5348:34;5276:2;5261:18;;5106:282::o;5393:245::-;5460:6;5513:2;5501:9;5492:7;5488:23;5484:32;5481:52;;;5529:1;5526;5519:12;5481:52;5561:9;5555:16;5580:28;5602:5;5580:28;:::i;5643:127::-;5704:10;5699:3;5695:20;5692:1;5685:31;5735:4;5732:1;5725:15;5759:4;5756:1;5749:15;5775:125;5815:4;5843:1;5840;5837:8;5834:34;;;5848:18;;:::i;:::-;-1:-1:-1;5885:9:1;;5775:125::o;5905:168::-;5945:7;6011:1;6007;6003:6;5999:14;5996:1;5993:21;5988:1;5981:9;5974:17;5970:45;5967:71;;;6018:18;;:::i;:::-;-1:-1:-1;6058:9:1;;5905:168::o;6078:217::-;6118:1;6144;6134:132;;6188:10;6183:3;6179:20;6176:1;6169:31;6223:4;6220:1;6213:15;6251:4;6248:1;6241:15;6134:132;-1:-1:-1;6280:9:1;;6078:217::o;6874:128::-;6914:3;6945:1;6941:6;6938:1;6935:13;6932:39;;;6951:18;;:::i;:::-;-1:-1:-1;6987:9:1;;6874:128::o;7007:356::-;7209:2;7191:21;;;7228:18;;;7221:30;7287:34;7282:2;7267:18;;7260:62;7354:2;7339:18;;7007:356::o;8494:251::-;8564:6;8617:2;8605:9;8596:7;8592:23;8588:32;8585:52;;;8633:1;8630;8623:12;8585:52;8665:9;8659:16;8684:31;8709:5;8684:31;:::i;9793:135::-;9832:3;9853:17;;;9850:43;;9873:18;;:::i;:::-;-1:-1:-1;9920:1:1;9909:13;;9793:135::o;10289:184::-;10359:6;10412:2;10400:9;10391:7;10387:23;10383:32;10380:52;;;10428:1;10425;10418:12;10380:52;-1:-1:-1;10451:16:1;;10289:184;-1:-1:-1;10289:184:1:o;13196:597::-;13308:4;13337:2;13366;13355:9;13348:21;13398:6;13392:13;13441:6;13436:2;13425:9;13421:18;13414:34;13466:1;13476:140;13490:6;13487:1;13484:13;13476:140;;;13585:14;;;13581:23;;13575:30;13551:17;;;13570:2;13547:26;13540:66;13505:10;;13476:140;;;13634:6;13631:1;13628:13;13625:91;;;13704:1;13699:2;13690:6;13679:9;13675:22;13671:31;13664:42;13625:91;-1:-1:-1;13777:2:1;13756:15;-1:-1:-1;;13752:29:1;13737:45;;;;13784:2;13733:54;;13196:597;-1:-1:-1;;;13196:597:1:o;13798:127::-;13859:10;13854:3;13850:20;13847:1;13840:31;13890:4;13887:1;13880:15;13914:4;13911:1;13904:15
Swarm Source
ipfs://ed4fbbe316118c57be5db0bf28466d82e4727bb327c4bb5e80c25834d89e622b
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.