More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 8 from a total of 8 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 19348367 | 335 days ago | IN | 0 ETH | 0.00227044 | ||||
Set Approval For... | 19348247 | 335 days ago | IN | 0 ETH | 0.00263664 | ||||
Set Approval For... | 19348243 | 335 days ago | IN | 0 ETH | 0.00252197 | ||||
Set Approval For... | 19348237 | 335 days ago | IN | 0 ETH | 0.00226951 | ||||
Transfer | 19348223 | 335 days ago | IN | 0 ETH | 0.00606122 | ||||
Set Approval For... | 19348172 | 335 days ago | IN | 0 ETH | 0.00269194 | ||||
Register All | 19348171 | 335 days ago | IN | 0 ETH | 0.00610038 | ||||
Transfer | 19348125 | 335 days ago | IN | 0 ETH | 0.00873616 |
Latest 16 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19354479 | 334 days ago | 0.0136 ETH | ||||
19354479 | 334 days ago | 0.0136 ETH | ||||
19354462 | 334 days ago | 0.012 ETH | ||||
19354462 | 334 days ago | 0.012 ETH | ||||
19354457 | 334 days ago | 0.0112 ETH | ||||
19354457 | 334 days ago | 0.0112 ETH | ||||
19354454 | 334 days ago | 0.0104 ETH | ||||
19354454 | 334 days ago | 0.0104 ETH | ||||
19354419 | 334 days ago | 0.0096 ETH | ||||
19354419 | 334 days ago | 0.0096 ETH | ||||
19353056 | 334 days ago | 0.008 ETH | ||||
19353056 | 334 days ago | 0.008 ETH | ||||
19353038 | 334 days ago | 0.008 ETH | ||||
19353038 | 334 days ago | 0.008 ETH | ||||
19352808 | 334 days ago | 0.008 ETH | ||||
19352808 | 334 days ago | 0.008 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
WHO404
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {ERC333} from "./ERC333/ERC333.sol"; import {FullMath} from "./utils/FullMath.sol"; contract WHO404 is ERC333 { using Strings for uint256; string private constant __NAME = "WHO404"; string private constant __SYM = "WHO"; uint256 private constant __MINT_SUPPLY = 1000; uint24 private constant __TAX_PERCENT = 80000; uint8 private constant __DECIMALS = 18; uint8 private constant __RATIO = 100; address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; mapping(address => bool) public operators; bool marketLimit = false; constructor( address initialOwner_, address initialMintRecipient_ ) ERC333( initialOwner_, initialMintRecipient_, __MINT_SUPPLY, __TAX_PERCENT, __NAME, __SYM, __DECIMALS, __RATIO ) { baseURI = "https://who404.wtf/assets/"; } function initialize() external payable override onlyOwner { address positionManagerAddress = 0xC36442b4a4522E871399CD717aBDD847Ab11FE88; address swapRouterAddress = 0xE592427A0AEce92De3Edee1F18E0157C05861564; if (msg.value > 0) { depositETH(msg.value); } uint160 sqrtPriceX96 = (address(this) < WETH) ? 1372272028650297984479657984 // 0.0003 : 4574240095500993129133247561728; // 3333.333333333333 uint256 quoteTokenAmount = _getWETHAtSqrtPriceX96(sqrtPriceX96); // require(quoteTokenAmount > 14e17, "quoteTokenAmount"); uint256 wethAmount = balanceOfWETH(); require(wethAmount >= quoteTokenAmount, "weth amount is too low"); _initialize( sqrtPriceX96, 3000, WETH, quoteTokenAmount, 60, positionManagerAddress, swapRouterAddress ); } function register(address operator_, bool value) external onlyOwner { operators[operator_] = value; } function registerAll() external onlyOwner { operators[0xa7FD99748cE527eAdC0bDAc60cba8a4eF4090f7c] = true; // 聚合器 operators[0x82C0fDFA607d9aFbe82Db5cBD103D1a4D5a43B77] = true; // 强制版税市场 operators[0x5B93A825829f4B7B5177c259Edc22b63d6E4e380] = true; // 批量转移工具 marketLimit = true; } function _transferERC721( address from_, address to_, uint256 id_ ) internal override { if (marketLimit == true) { require( msg.sender == owner() || msg.sender == initialMintRecipient || operators[msg.sender], "not allowed" ); } super._transferERC721(from_, to_, id_); } function balanceOfWETH() internal returns (uint256 amount) { // Call balanceOf // 0x70a08231: keccak256(balanceOf(address)) (bool success, bytes memory data) = WETH.staticcall( abi.encodeWithSelector(0x70a08231, address(this)) ); if (success) { // Decode `uint256` from returned data amount = abi.decode(data, (uint256)); } } function depositETH(uint256 amount) internal returns (bool) { // Deposit the eth // Call deposit // 0xd0e30db0: keccak256(deposit()) (bool success, ) = WETH.call{value: amount}( abi.encodeWithSelector(0xd0e30db0) ); return success; } function _getWETHAtSqrtPriceX96( uint160 sqrtPriceX96 ) private view returns (uint256 quoteAmount) { // Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself uint256 thisAmount = balanceOf[address(this)]; if (sqrtPriceX96 <= type(uint128).max) { uint256 ratioX192 = uint256(sqrtPriceX96) * sqrtPriceX96; quoteAmount = address(this) < WETH ? FullMath.mulDiv(ratioX192, thisAmount, 1 << 192) : FullMath.mulDiv(1 << 192, thisAmount, ratioX192); } else { uint256 ratioX128 = FullMath.mulDiv( sqrtPriceX96, sqrtPriceX96, 1 << 64 ); quoteAmount = address(this) < WETH ? FullMath.mulDiv(ratioX128, thisAmount, 1 << 128) : FullMath.mulDiv(1 << 128, thisAmount, ratioX128); } } function tokenURI(uint256 id) public view override returns (string memory) { uint8 seed = uint8(bytes1(keccak256(abi.encodePacked(id)))); string memory image; string memory color; if (seed <= 64) { image = "0.png"; color = "Red"; } else if (seed <= 128) { image = "1.png"; color = "Blue"; } else if (seed <= 192) { image = "2.png"; color = "Green"; } else { image = "3.png"; color = "Purple"; } return string( abi.encodePacked( '{"name": "WHO404 NFT#', Strings.toString(id), '","description":"A collection of ', Strings.toString(mintSupply), " pots of liquidity that tokenizes decentralized reserve currency idea for the IQ50, #ERC333.", '","external_url":"https://who404.wtf/","image":"', baseURI, image, '","attributes":[{"trait_type":"Color","value":"', color, '"}]}' ) ); } receive() external payable { depositETH(msg.value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.20; import {IERC721} from "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @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`. * * 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 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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 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 address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {ERC404} from "../ERC404/ERC404.sol"; import {ERC5169} from "stl-contracts/ERC/ERC5169.sol"; import {IERC721Metadata} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import {PoolAddress} from "../utils/PoolAddress.sol"; import {TickMath} from "../utils/TickMath.sol"; import {PoolData} from "../structs/PoolData.sol"; import {MintParams, IncreaseLiquidityParams, DecreaseLiquidityParams, CollectParams} from "../structs/PositionParams.sol"; import {ExactInputSingleParams} from "../structs/RouterParams.sol"; abstract contract ERC333 is Ownable, ERC404, ERC5169 { event Initialize(PoolData poolData); event ReceiveTax(uint256 value); event ERC20Burn(uint256 value); event RefundETH(address sender, uint256 value); // event IncreaseLiquidity(uint256 amount); using Strings for uint256; string constant _JSON_FILE = ".json"; // default settings uint256 public mintSupply = 10000; // max NFT count uint24 public taxPercent = 80000; address public initialMintRecipient; // the first token owner bool public initialized; PoolData public currentPoolData; /// @dev for the tick bar of ERC333 int24 public tickThreshold; int24 public currentTick; uint256 public mintTimestamp; /// @dev Total tax in ERC-20 token representation uint256 public totalTax; address public positionManagerAddress; address public swapRouterAddress; /// @dev for compute arithmetic mean tick by observation uint32 constant TWAP_INTERVAL = 30 minutes; event BaseUriUpdate(string uri); string public baseURI; constructor( address initialOwner_, address initialMintRecipient_, uint256 mintSupply_, uint24 taxPercent_, string memory name_, string memory sym_, uint8 decimals_, uint8 ratio_ ) ERC404(name_, sym_, decimals_, ratio_) Ownable(initialOwner_) { // init settings mintSupply = mintSupply_; taxPercent = taxPercent_; initialMintRecipient = initialMintRecipient_; // Do not mint the ERC721s to the initial owner, as it's a waste of gas. _setERC721TransferExempt(initialMintRecipient_, true); _mintERC20(initialMintRecipient_, mintSupply * units, false); } // Treat as ERC721 type, provide ERC20 interface in TokenScript function supportsInterface( bytes4 interfaceId ) public view override(ERC5169, ERC404) returns (bool) { return ERC5169.supportsInterface(interfaceId) || ERC404.supportsInterface(interfaceId); } // ERC-5169 function _authorizeSetScripts( string[] memory ) internal view override(ERC5169) onlyOwner {} // ====================================================================================================== // // ERC333 overrides // // ====================================================================================================== function initialize() external payable virtual; function _initialize( uint160 sqrtPriceX96, uint24 fee, address quoteToken, uint256 quoteTokenAmount, uint16 observationCardinalityNext, address positionManagerAddress_, address swapRouterAddress_ ) internal virtual onlyOwner { require(!initialized, "has initialized"); positionManagerAddress = positionManagerAddress_; swapRouterAddress = swapRouterAddress_; currentPoolData.quoteToken = quoteToken; currentPoolData.fee = fee; currentPoolData.sqrtPriceX96 = sqrtPriceX96; (address token0, address token1) = (address(this), quoteToken); (uint256 amount0, uint256 amount1) = ( balanceOf[address(this)], quoteTokenAmount ); if (token0 > token1) { (token0, token1) = (token1, token0); (amount0, amount1) = (amount1, amount0); } _approveUniswap(token0, type(uint256).max); _approveUniswap(token1, type(uint256).max); // step1 create pool int24 tickSpacing; ( currentPoolData.poolAddress, currentTick, tickSpacing ) = _initializePool(token0, token1, fee, sqrtPriceX96); require( currentPoolData.poolAddress != address(0) && tickSpacing != 0, "initialize pool failed" ); tickThreshold = currentTick; if (_thisIsToken0()) { currentPoolData.tickLower = (tickThreshold / tickSpacing) * tickSpacing; if (tickThreshold < 0) { currentPoolData.tickLower -= tickSpacing; } // currentPoolData.tickLower = // (TickMath.MIN_TICK / tickSpacing) * // tickSpacing; currentPoolData.tickUpper = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; } else { currentPoolData.tickUpper = (tickThreshold / tickSpacing) * tickSpacing; if (tickThreshold > 0) { currentPoolData.tickUpper += tickSpacing; } currentPoolData.tickLower = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; } // step2 increase observation cardinality if (observationCardinalityNext > 0) { bool success = _initializeObservations( currentPoolData.poolAddress, observationCardinalityNext ); require(success, "initialize observations failed"); } // step3 create liquidity ( currentPoolData.positionId, currentPoolData.liquidity, , ) = _initializeLiquidity( token0, token1, fee, amount0, amount1, currentPoolData.tickLower, currentPoolData.tickUpper, address(this) ); require(currentPoolData.positionId != 0, "initialize liquidity failed"); mintTimestamp = block.timestamp; initialized = true; emit Initialize(currentPoolData); } /// @notice Explain to an end user what this does /// @dev Explain to a developer any extra details function _getCurrentTokenTick() internal virtual returns (int24) { if (!initialized) { return tickThreshold; } // Call uniswapV3Pool.slot0 // 0x3850c7bd: keccak256(slot0()) (bool success0, bytes memory data0) = currentPoolData .poolAddress .staticcall(abi.encodeWithSelector(0x3850c7bd)); if (!success0) { return tickThreshold; } // Decode `Slot` from returned data (, int24 tick, uint16 index, uint16 cardinality, , , ) = abi.decode( data0, (uint160, int24, uint16, uint16, uint16, uint8, bool) ); uint32 delta = TWAP_INTERVAL; if (uint32(block.timestamp - mintTimestamp) < delta) { return tick; } uint32[] memory secondsTwapIntervals = new uint32[](2); secondsTwapIntervals[0] = delta; secondsTwapIntervals[1] = 0; // Call uniswapV3Pool.observe // 0x883bdbfd: keccak256(observe(uint32[])) // require(pools[poolFee] != address(0), "Pool must init"); (bool success, bytes memory data) = currentPoolData .poolAddress .staticcall( abi.encodeWithSelector(0x883bdbfd, secondsTwapIntervals) ); if (!success) { return tick; } // Decode `tickCumulatives` from returned data (int56[] memory tickCumulatives, ) = abi.decode( data, (int56[], uint160[]) ); int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0]; tick = int24(tickCumulativesDelta / int56(uint56(delta))); // Always round to negative infinity if ( tickCumulativesDelta < 0 && (tickCumulativesDelta % int56(uint56(delta)) != 0) ) tick--; return tick; } function _approveUniswap( address token, uint256 amount ) internal virtual returns (bool) { if (amount == 0) { return true; } if (token == address(this)) { allowance[address(this)][positionManagerAddress] = amount; allowance[address(this)][swapRouterAddress] = amount; return true; } // Approve the position manager // Call approve // 0x095ea7b3: keccak256(approve(address,uint256)) (bool success0, ) = token.call( abi.encodeWithSelector(0x095ea7b3, positionManagerAddress, amount) ); (bool success1, ) = token.call( abi.encodeWithSelector(0x095ea7b3, swapRouterAddress, amount) ); return success0 && success1; } function _initializePool( address token0, address token1, uint24 fee, uint160 sqrtPriceX96 ) internal virtual returns (address poolAddress, int24 tick, int24 tickSpacing) { // Call position manager createAndInitializePoolIfNecessary // 0x13ead562: keccak256(createAndInitializePoolIfNecessary(address,address,uint24,uint160)) (bool success0, bytes memory data0) = positionManagerAddress.call( abi.encodeWithSelector( 0x13ead562, token0, token1, fee, sqrtPriceX96 ) ); // If createAndInitializePoolIfNecessary hasn't reverted if (!success0) { return (address(0), 0, 0); } // Decode `address` from returned data poolAddress = abi.decode(data0, (address)); // Call uniswapV3Pool.slot0 // 0x3850c7bd: keccak256(slot0()) (bool success1, bytes memory data1) = poolAddress.staticcall( abi.encodeWithSelector(0x3850c7bd) ); if (!success1) { return (address(0), 0, 0); } // Decode `Slot` from returned data (, tick, , , , , ) = abi.decode( data1, (uint160, int24, uint16, uint16, uint16, uint8, bool) ); // Call uniswapV3Pool.tickSpacing // 0xd0c93a7c: keccak256(tickSpacing()) (bool success2, bytes memory data2) = poolAddress.staticcall( abi.encodeWithSelector(0xd0c93a7c) ); if (!success2) { return (address(0), 0, 0); } tickSpacing = abi.decode(data2, (int24)); } function _initializeObservations( address poolAddress, uint16 observationCardinalityNext ) internal virtual returns (bool) { // Call pool increaseObservationCardinalityNext // 0x32148f67: keccak256(increaseObservationCardinalityNext(uint16)) (bool success, ) = poolAddress.call( abi.encodeWithSelector(0x32148f67, observationCardinalityNext) ); return success; } function _initializeLiquidity( address token0, address token1, uint24 fee, uint256 amount0, uint256 amount1, int24 tickLower, int24 tickUpper, address recipient ) internal virtual returns ( uint256 positionId, uint128 liquidity, uint256 amount0Used, uint256 amount1Used ) { MintParams memory params = MintParams({ token0: token0, token1: token1, fee: fee, tickLower: tickLower, tickUpper: tickUpper, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0, amount1Min: 0, recipient: recipient, deadline: block.timestamp }); // Call position manager mint // 0x88316456: keccak256(mint((address,address,uint24,int24,int24,uint256, // uint256,uint256,uint256,address,uint256))) (bool success, bytes memory data) = positionManagerAddress.call( abi.encodeWithSelector(0x88316456, params) ); // If mint hasn't reverted if (success) { // Decode `(uint256, uint128, uint256, uint256)` from returned data (positionId, liquidity, amount0Used, amount1Used) = abi.decode( data, (uint256, uint128, uint256, uint256) ); } } function _exactInputSingle( address tokenIn, address tokenOut, address recipient, uint256 amountIn ) internal virtual returns (uint256 amountOut) { ExactInputSingleParams memory params = ExactInputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: currentPoolData.fee, recipient: recipient, amountIn: amountIn, amountOutMinimum: 0, sqrtPriceLimitX96: 0, deadline: block.timestamp }); // Call position manager increaseLiquidity // 0x414bf389: keccak256(exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))) (bool success, bytes memory data) = swapRouterAddress.call( abi.encodeWithSelector(0x414bf389, params) ); // If exactInputSingle hasn't reverted if (success) { // Decode `(uint128, uint256, uint256)` from returned data amountOut = abi.decode(data, (uint256)); } } function _increaseLiquidity( uint256 positionId, uint256 amount0, uint256 amount1 ) internal virtual returns (uint128 liquidity, uint256 amount0Used, uint256 amount1Used) { IncreaseLiquidityParams memory params = IncreaseLiquidityParams({ tokenId: positionId, amount0Desired: amount0, amount1Desired: amount1, amount0Min: 0, amount1Min: 0, deadline: block.timestamp }); // Call position manager increaseLiquidity // 0x219f5d17: keccak256(increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256))) (bool success, bytes memory data) = positionManagerAddress.call( abi.encodeWithSelector(0x219f5d17, params) ); // If increaseLiquidity hasn't reverted if (success) { // Decode `(uint128, uint256, uint256)` from returned data (liquidity, amount0Used, amount1Used) = abi.decode( data, (uint128, uint256, uint256) ); } } function _decreaseLiquidity( uint256 positionId, uint128 liquidity ) internal virtual returns (uint256 amount0, uint256 amount1) { DecreaseLiquidityParams memory params = DecreaseLiquidityParams({ tokenId: positionId, liquidity: liquidity, amount0Min: 0, amount1Min: 0, deadline: block.timestamp }); // Call position manager increaseLiquidity // 0x0c49ccbe: keccak256(decreaseLiquidity((uint256,uint128,uint256,uint256,uint256))) (bool success, bytes memory data) = positionManagerAddress.call( abi.encodeWithSelector(0x0c49ccbe, params) ); // If decreaseLiquidity hasn't reverted if (success) { // Decode `(uint128, uint256, uint256)` from returned data (amount0, amount1) = abi.decode(data, (uint256, uint256)); } } function _collect( uint256 positionId, address recipient ) internal virtual returns (uint256 amount0, uint256 amount1) { CollectParams memory params = CollectParams({ tokenId: positionId, recipient: recipient, amount0Max: type(uint128).max, amount1Max: type(uint128).max }); // Call position manager increaseLiquidity // 0xfc6f7865: keccak256(collect((uint256,address,uint128,uint128))) (bool success, bytes memory data) = positionManagerAddress.call( abi.encodeWithSelector(0xfc6f7865, params) ); // If decreaseLiquidity hasn't reverted if (success) { // Decode `(uint128, uint256, uint256)` from returned data (amount0, amount1) = abi.decode(data, (uint256, uint256)); } } function _thisIsToken0() internal view returns(bool) { return (address(this) < currentPoolData.quoteToken); } function _getTaxOrBurned( address from_, address to_, uint256 value_ ) internal virtual returns (uint256 tax, bool burned) { if ( msg.sender == initialMintRecipient || msg.sender == swapRouterAddress || from_ == address(this) || to_ == address(currentPoolData.poolAddress) ) { return (0, false); } // get token tick currentTick = _getCurrentTokenTick(); if (_thisIsToken0()) { if (currentTick > tickThreshold) { tax = (value_ * taxPercent) / 1000000; } else if (currentTick < tickThreshold) { burned = true; } else { // do someting if getCurrentTokenTick failed } } else { if (currentTick < tickThreshold) { tax = (value_ * taxPercent) / 1000000; } else if (currentTick > tickThreshold) { burned = true; } else { // do someting if getCurrentTokenTick failed } } } function _transferWithTax( address from_, address to_, uint256 value_ ) public virtual returns (bool) { (uint256 tax, bool burned) = _getTaxOrBurned(from_, to_, value_); if (burned) { // burn from_ token, _transferERC20WithERC721(from_, address(0), value_); // refund the ETH value to the to_ address _refundETH(to_, value_); totalSupply -= value_; emit ERC20Burn(value_); } else if (tax > 0) { _transferERC20WithERC721(from_, to_, value_ - tax); _transferERC20WithERC721(from_, address(this), tax); totalTax += tax; emit ReceiveTax(tax); } else { // Transferring ERC-20s directly requires the _transfer function. _transferERC20WithERC721(from_, to_, value_); } return true; } function swapAndLiquify(uint256 amount) external virtual onlyOwner { require( amount <= ((balanceOf[address(this)] * 2) / 3), "amount is too large" ); // swap tokens for ETH uint256 quoteAmount = swapTokensForQuote(amount); if (quoteAmount > 0) { // add liquidity to uniswap addLiquidity(balanceOf[address(this)], quoteAmount / 2); } } function liquifyAndCollect(uint128 liquidity) external virtual onlyOwner { require( liquidity <= (currentPoolData.liquidity), "liquidity is too large" ); if (liquidity > 0) { subLiquidity(liquidity); } _collect(currentPoolData.positionId, initialMintRecipient); } function swapTokensForQuote(uint256 tokenAmount) private returns (uint256) { return _exactInputSingle( address(this), currentPoolData.quoteToken, address(this), tokenAmount ); } function addLiquidity(uint256 thisAmount, uint256 quoteAmount) private { (address token0, address token1) = ( address(this), currentPoolData.quoteToken ); (uint256 amount0, uint256 amount1) = (thisAmount, quoteAmount); if (token0 > token1) { (token0, token1) = (token1, token0); (amount0, amount1) = (amount1, amount0); } uint128 liquidity; (liquidity, amount0, amount1) = _increaseLiquidity( currentPoolData.positionId, amount0, amount1 ); if (liquidity > 0) { currentPoolData.liquidity += liquidity; } } function subLiquidity(uint128 liquidity) private { (uint256 amount0, uint256 amount1) = _decreaseLiquidity( currentPoolData.positionId, liquidity ); if (amount0 > 0 || amount1 > 0) { currentPoolData.liquidity -= liquidity; } } /// @notice Function for ERC-20 transfers. /// @dev This function assumes the operator is attempting to transfer as ERC-20 /// given this function is only supported on the ERC-20 interface function transfer( address to_, uint256 value_ ) public override returns (bool) { // Prevent burning tokens to 0x0. if (to_ == address(0)) { revert InvalidRecipient(); } return _transferWithTax(msg.sender, to_, value_); } /// @notice Function for mixed transfers from an operator that may be different than 'from'. /// @dev This function assumes the operator is attempting to transfer an ERC-721 /// if valueOrId is less than or equal to current max id. function transferFrom( address from_, address to_, uint256 valueOrId_ ) public override returns (bool) { // Prevent transferring tokens from 0x0. if (from_ == address(0)) { revert InvalidSender(); } // Prevent burning tokens to 0x0. if (to_ == address(0)) { revert InvalidRecipient(); } if (valueOrId_ <= _minted) { // Intention is to transfer as ERC-721 token (id). uint256 id = valueOrId_; if (from_ != _getOwnerOf(id)) { revert Unauthorized(); } // Check that the operator is either the sender or approved for the transfer. if ( msg.sender != from_ && !isApprovedForAll[from_][msg.sender] && msg.sender != getApproved[id] ) { revert Unauthorized(); } // Transfer 1 * units ERC-20 and 1 ERC-721 token. _transferERC20(from_, to_, units); _transferERC721(from_, to_, id); } else { // Intention is to transfer as ERC-20 token (value). uint256 value = valueOrId_; uint256 allowed = allowance[from_][msg.sender]; // Check that the operator has sufficient allowance. if (allowed != type(uint256).max) { allowance[from_][msg.sender] = allowed - value; } return _transferWithTax(from_, to_, value); } return true; } function _refundETH(address account, uint256 value) internal virtual { if (account == address(0)) { revert InvalidSender(); } // Call balanceOf // 0x70a08231: keccak256(balanceOf(address)) (bool success0, bytes memory data0) = currentPoolData .quoteToken .staticcall(abi.encodeWithSelector(0x70a08231, address(this))); if (!success0) { return; } // Decode `uint256` from returned data uint256 totalWETHAmount = abi.decode(data0, (uint256)); uint256 wethAmount = (value * totalWETHAmount) / totalSupply; // Call WETH transfer // 0xa9059cbb: keccak256(transfer(address,uint256)) (bool success, ) = currentPoolData.quoteToken.call( abi.encodeWithSelector(0xa9059cbb, account, wethAmount) ); // If transfer hasn't reverted if (success) { emit RefundETH(account, wethAmount); } } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC404} from "./interfaces/IERC404.sol"; import {ERC721Receiver} from "./lib/ERC721Receiver.sol"; import {DoubleEndedQueue} from "./lib/DoubleEndedQueue.sol"; import {IERC165} from "./lib/interfaces/IERC165.sol"; import {ERC721Events} from "./lib/ERC721Events.sol"; import {ERC20Events} from "./lib/ERC20Events.sol"; abstract contract ERC404 is IERC404 { using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque; /// @dev The queue of ERC-721 tokens stored in the contract. DoubleEndedQueue.Uint256Deque private _storedERC721Ids; /// @dev Token name string public name; /// @dev Token symbol string public symbol; /// @dev Decimals for ERC-20 representation uint8 public immutable decimals; /// @dev Units for ERC-20 representation uint256 public immutable units; /// @dev Total supply in ERC-20 representation uint256 public totalSupply; /// @dev Current mint counter which also represents the highest /// minted id, monotonically increasing to ensure accurate ownership uint256 internal _minted; /// @dev Initial chain id for EIP-2612 support uint256 internal immutable INITIAL_CHAIN_ID; /// @dev Initial domain separator for EIP-2612 support bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; /// @dev Balance of user in ERC-20 representation mapping(address => uint256) public balanceOf; /// @dev Allowance of user in ERC-20 representation mapping(address => mapping(address => uint256)) public allowance; /// @dev Approval in ERC-721 representaion mapping(uint256 => address) public getApproved; /// @dev Approval for all in ERC-721 representation mapping(address => mapping(address => bool)) public isApprovedForAll; /// @dev Packed representation of ownerOf and owned indices mapping(uint256 => uint256) internal _ownedData; /// @dev Array of owned ids in ERC-721 representation mapping(address => uint256[]) internal _owned; /// @dev Addresses that are exempt from ERC-721 transfer, typically for gas savings (pairs, routers, etc) mapping(address => bool) public erc721TransferExempt; /// @dev EIP-2612 nonces mapping(address => uint256) public nonces; /// @dev Address bitmask for packed ownership data uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; /// @dev Owned index bitmask for packed ownership data uint256 private constant _BITMASK_OWNED_INDEX = ((1 << 96) - 1) << 160; constructor( string memory name_, string memory symbol_, uint8 decimals_, uint8 ratio_ ) { name = name_; symbol = symbol_; if (decimals_ < 18) { revert DecimalsTooLow(); } decimals = decimals_; units = 10 ** decimals * ratio_; // EIP-2612 initialization INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator(); } /// @notice Function to find owner of a given ERC-721 token function ownerOf( uint256 id_ ) public view virtual returns (address erc721Owner) { erc721Owner = _getOwnerOf(id_); // If the id_ is beyond the range of minted tokens, is 0, or the token is not owned by anyone, revert. if (id_ > _minted || id_ == 0 || erc721Owner == address(0)) { revert NotFound(); } } function owned( address owner_ ) public view virtual returns (uint256[] memory) { return _owned[owner_]; } function erc721BalanceOf( address owner_ ) public view virtual returns (uint256) { return _owned[owner_].length; } function erc20BalanceOf( address owner_ ) public view virtual returns (uint256) { return balanceOf[owner_]; } function erc20TotalSupply() public view virtual returns (uint256) { return totalSupply; } function erc721TotalSupply() public view virtual returns (uint256) { return _minted; } function erc721TokensBankedInQueue() public view virtual returns (uint256) { return _storedERC721Ids.length(); } /// @notice tokenURI must be implemented by child contract function tokenURI(uint256 id_) public view virtual returns (string memory); /// @notice Function for token approvals /// @dev This function assumes the operator is attempting to approve an ERC-721 /// if valueOrId is less than the minted count. Note: Unlike setApprovalForAll, /// spender_ must be allowed to be 0x0 so that approval can be revoked. function approve( address spender_, uint256 valueOrId_ ) public virtual returns (bool) { // The ERC-721 tokens are 1-indexed, so 0 is not a valid id and indicates that // operator is attempting to set the ERC-20 allowance to 0. if (valueOrId_ <= _minted && valueOrId_ > 0) { // Intention is to approve as ERC-721 token (id). uint256 id = valueOrId_; address erc721Owner = _getOwnerOf(id); if ( msg.sender != erc721Owner && !isApprovedForAll[erc721Owner][msg.sender] ) { revert Unauthorized(); } getApproved[id] = spender_; emit ERC721Events.Approval(erc721Owner, spender_, id); } else { // Prevent granting 0x0 an ERC-20 allowance. if (spender_ == address(0)) { revert InvalidSpender(); } // Intention is to approve as ERC-20 token (value). uint256 value = valueOrId_; allowance[msg.sender][spender_] = value; emit ERC20Events.Approval(msg.sender, spender_, value); } return true; } /// @notice Function for ERC-721 approvals function setApprovalForAll( address operator_, bool approved_ ) public virtual { // Prevent approvals to 0x0. if (operator_ == address(0)) { revert InvalidOperator(); } isApprovedForAll[msg.sender][operator_] = approved_; emit ApprovalForAll(msg.sender, operator_, approved_); } /// @notice Function for mixed transfers from an operator that may be different than 'from'. /// @dev This function assumes the operator is attempting to transfer an ERC-721 /// if valueOrId is less than or equal to current max id. function transferFrom( address from_, address to_, uint256 valueOrId_ ) public virtual returns (bool) { // Prevent transferring tokens from 0x0. if (from_ == address(0)) { revert InvalidSender(); } // Prevent burning tokens to 0x0. if (to_ == address(0)) { revert InvalidRecipient(); } if (valueOrId_ <= _minted) { // Intention is to transfer as ERC-721 token (id). uint256 id = valueOrId_; if (from_ != _getOwnerOf(id)) { revert Unauthorized(); } // Check that the operator is either the sender or approved for the transfer. if ( msg.sender != from_ && !isApprovedForAll[from_][msg.sender] && msg.sender != getApproved[id] ) { revert Unauthorized(); } // Transfer 1 * units ERC-20 and 1 ERC-721 token. _transferERC20(from_, to_, units); _transferERC721(from_, to_, id); } else { // Intention is to transfer as ERC-20 token (value). uint256 value = valueOrId_; uint256 allowed = allowance[from_][msg.sender]; // Check that the operator has sufficient allowance. if (allowed != type(uint256).max) { allowance[from_][msg.sender] = allowed - value; } // Transferring ERC-20s directly requires the _transfer function. _transferERC20WithERC721(from_, to_, value); } return true; } /// @notice Function for ERC-20 transfers. /// @dev This function assumes the operator is attempting to transfer as ERC-20 /// given this function is only supported on the ERC-20 interface function transfer( address to_, uint256 value_ ) public virtual returns (bool) { // Prevent burning tokens to 0x0. if (to_ == address(0)) { revert InvalidRecipient(); } // Transferring ERC-20s directly requires the _transfer function. return _transferERC20WithERC721(msg.sender, to_, value_); } /// @notice Function for ERC-721 transfers with contract support. function safeTransferFrom( address from_, address to_, uint256 id_ ) public virtual { transferFrom(from_, to_, id_); if ( to_.code.length != 0 && ERC721Receiver(to_).onERC721Received(msg.sender, from_, id_, "") != ERC721Receiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } /// @notice Function for ERC-721 transfers with contract support and callback data. function safeTransferFrom( address from_, address to_, uint256 id_, bytes calldata data_ ) public virtual { transferFrom(from_, to_, id_); if ( to_.code.length != 0 && ERC721Receiver(to_).onERC721Received( msg.sender, from_, id_, data_ ) != ERC721Receiver.onERC721Received.selector ) { revert UnsafeRecipient(); } } /// @notice Function for EIP-2612 permits function permit( address owner_, address spender_, uint256 value_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_ ) public virtual { if (deadline_ < block.timestamp) { revert PermitDeadlineExpired(); } if (value_ <= _minted && value_ > 0) { revert InvalidApproval(); } if (spender_ == address(0)) { revert InvalidSpender(); } unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner_, spender_, value_, nonces[owner_]++, deadline_ ) ) ) ), v_, r_, s_ ); if (recoveredAddress == address(0) || recoveredAddress != owner_) { revert InvalidSigner(); } allowance[recoveredAddress][spender_] = value_; } emit ERC20Events.Approval(owner_, spender_, value_); } /// @notice Returns domain initial domain separator, or recomputes if chain id is not equal to initial chain id function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator(); } function supportsInterface( bytes4 interfaceId ) public view virtual returns (bool) { return interfaceId == type(IERC404).interfaceId || interfaceId == type(IERC165).interfaceId; } /// @notice Internal function to compute domain separator for EIP-2612 permits function _computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } function calculateERC721Transfers( address from_, uint256 value_ ) public view returns (uint256[] memory tokenIds) { //first check it's possible to send this value uint256 erc20BalanceOfSenderBefore = erc20BalanceOf(from_); if (!erc721TransferExempt[from_]) { uint256 nftsToTransfer = value_ / units; uint256 fractionalAmount = value_ % units; //account for fractional NFT removal if ( (erc20BalanceOfSenderBefore - fractionalAmount) / units < (erc20BalanceOfSenderBefore / units) ) { nftsToTransfer++; } if (nftsToTransfer > 0) { tokenIds = new uint256[](nftsToTransfer); for (uint256 i = 0; i < nftsToTransfer; i++) { // Pop from sender's ERC-721 stack and transfer them (LIFO) uint256 indexOfLastToken = _owned[from_].length - (1 + i); tokenIds[i] = _owned[from_][indexOfLastToken]; } } } } /// @notice This is the lowest level ERC-20 transfer function, which /// should be used for both normal ERC-20 transfers as well as minting. /// Note that this function allows transfers to and from 0x0. function _transferERC20( address from_, address to_, uint256 value_ ) internal virtual { // Minting is a special case for which we should not check the balance of // the sender, and we should increase the total supply. if (from_ == address(0)) { totalSupply += value_; } else { // Deduct value from sender's balance. balanceOf[from_] -= value_; } // Update the recipient's balance. // Can be unchecked because on mint, adding to totalSupply is checked, and on transfer balance deduction is checked. unchecked { balanceOf[to_] += value_; } emit ERC20Events.Transfer(from_, to_, value_); } /// @notice Consolidated record keeping function for transferring ERC-721s. /// @dev Assign the token to the new owner, and remove from the old owner. /// Note that this function allows transfers to and from 0x0. function _transferERC721( address from_, address to_, uint256 id_ ) internal virtual { // If this is not a mint, handle record keeping for transfer from previous owner. if (from_ != address(0)) { // On transfer of an NFT, any previous approval is reset. delete getApproved[id_]; uint256 updatedId = _owned[from_][_owned[from_].length - 1]; if (updatedId != id_) { uint256 updatedIndex = _getOwnedIndex(id_); // update _owned for sender _owned[from_][updatedIndex] = updatedId; // update index for the moved id _setOwnedIndex(updatedId, updatedIndex); } // pop _owned[from_].pop(); } if (to_ != address(0)) { // Update owner of the token to the new owner. _setOwnerOf(id_, to_); // Push token onto the new owner's stack. _owned[to_].push(id_); // Update index for new owner's stack. _setOwnedIndex(id_, _owned[to_].length - 1); } else { delete _ownedData[id_]; } emit ERC721Events.Transfer(from_, to_, id_); } /// @notice Internal function for ERC-20 transfers. Also handles any ERC-721 transfers that may be required. function _transferERC20WithERC721( address from_, address to_, uint256 value_ ) internal virtual returns (bool) { uint256 erc20BalanceOfSenderBefore = erc20BalanceOf(from_); uint256 erc20BalanceOfReceiverBefore = erc20BalanceOf(to_); _transferERC20(from_, to_, value_); // Preload for gas savings on branches bool isFromERC721TransferExempt = erc721TransferExempt[from_]; bool isToERC721TransferExempt = erc721TransferExempt[to_]; // Skip _withdrawAndStoreERC721 and/or _retrieveOrMintERC721 for ERC-721 transfer exempt addresses // 1) to save gas // 2) because ERC-721 transfer exempt addresses won't always have/need ERC-721s corresponding to their ERC20s. if (isFromERC721TransferExempt && isToERC721TransferExempt) { // Case 1) Both sender and recipient are ERC-721 transfer exempt. No ERC-721s need to be transferred. // NOOP. } else if (isFromERC721TransferExempt) { // Case 2) The sender is ERC-721 transfer exempt, but the recipient is not. Contract should not attempt // to transfer ERC-721s from the sender, but the recipient should receive ERC-721s // from the bank/minted for any whole number increase in their balance. // Only cares about whole number increments. uint256 tokensToRetrieveOrMint = (balanceOf[to_] / units) - (erc20BalanceOfReceiverBefore / units); for (uint256 i = 0; i < tokensToRetrieveOrMint; i++) { _retrieveOrMintERC721(to_); } } else if (isToERC721TransferExempt) { // Case 3) The sender is not ERC-721 transfer exempt, but the recipient is. Contract should attempt // to withdraw and store ERC-721s from the sender, but the recipient should not // receive ERC-721s from the bank/minted. // Only cares about whole number increments. uint256 tokensToWithdrawAndStore = (erc20BalanceOfSenderBefore / units) - (balanceOf[from_] / units); for (uint256 i = 0; i < tokensToWithdrawAndStore; i++) { _withdrawAndStoreERC721(from_); } } else { // Case 4) Neither the sender nor the recipient are ERC-721 transfer exempt. // Strategy: // 1. First deal with the whole tokens. These are easy and will just be transferred. // 2. Look at the fractional part of the value: // a) If it causes the sender to lose a whole token that was represented by an NFT due to a // fractional part being transferred, withdraw and store an additional NFT from the sender. // b) If it causes the receiver to gain a whole new token that should be represented by an NFT // due to receiving a fractional part that completes a whole token, retrieve or mint an NFT to the recevier. // Whole tokens worth of ERC-20s get transferred as ERC-721s without any burning/minting. uint256 nftsToTransfer = value_ / units; for (uint256 i = 0; i < nftsToTransfer; i++) { // Pop from sender's ERC-721 stack and transfer them (LIFO) uint256 indexOfLastToken = _owned[from_].length - 1; uint256 tokenId = _owned[from_][indexOfLastToken]; _transferERC721(from_, to_, tokenId); } // If the sender's transaction changes their holding from a fractional to a non-fractional // amount (or vice versa), adjust ERC-721s. // // Check if the send causes the sender to lose a whole token that was represented by an ERC-721 // due to a fractional part being transferred. // // To check this, look if subtracting the fractional amount from the balance causes the balance to // drop below the original balance % units, which represents the number of whole tokens they started with. uint256 fractionalAmount = value_ % units; if ( (erc20BalanceOfSenderBefore - fractionalAmount) / units < (erc20BalanceOfSenderBefore / units) ) { _withdrawAndStoreERC721(from_); } // Check if the receive causes the receiver to gain a whole new token that should be represented // by an NFT due to receiving a fractional part that completes a whole token. if ( (erc20BalanceOfReceiverBefore + fractionalAmount) / units > (erc20BalanceOfReceiverBefore / units) ) { _retrieveOrMintERC721(to_); } } return true; } /// @notice Internal function for ERC20 minting /// @dev This function will allow minting of new ERC20s. /// If mintCorrespondingERC721s_ is true, it will also mint the corresponding ERC721s. function _mintERC20( address to_, uint256 value_, bool mintCorrespondingERC721s_ ) internal virtual { /// You cannot mint to the zero address (you can't mint and immediately burn in the same transfer). if (to_ == address(0)) { revert InvalidRecipient(); } _transferERC20(address(0), to_, value_); // If mintCorrespondingERC721s_ is true, mint the corresponding ERC721s. if (mintCorrespondingERC721s_) { uint256 nftsToRetrieveOrMint = value_ / units; for (uint256 i = 0; i < nftsToRetrieveOrMint; i++) { _retrieveOrMintERC721(to_); } } } /// @notice Internal function for ERC-721 minting and retrieval from the bank. /// @dev This function will allow minting of new ERC-721s up to the total fractional supply. It will /// first try to pull from the bank, and if the bank is empty, it will mint a new token. function _retrieveOrMintERC721(address to_) internal virtual { if (to_ == address(0)) { revert InvalidRecipient(); } uint256 id; if (!DoubleEndedQueue.empty(_storedERC721Ids)) { // If there are any tokens in the bank, use those first. // Pop off the end of the queue (FIFO). id = _storedERC721Ids.popBack(); } else { // Otherwise, mint a new token, should not be able to go over the total fractional supply. _minted++; id = _minted; } address erc721Owner = _getOwnerOf(id); // The token should not already belong to anyone besides 0x0 or this contract. // If it does, something is wrong, as this should never happen. if (erc721Owner != address(0)) { revert AlreadyExists(); } // Transfer the token to the recipient, either transferring from the contract's bank or minting. _transferERC721(erc721Owner, to_, id); } /// @notice Internal function for ERC-721 deposits to bank (this contract). /// @dev This function will allow depositing of ERC-721s to the bank, which can be retrieved by future minters. function _withdrawAndStoreERC721(address from_) internal virtual { if (from_ == address(0)) { revert InvalidSender(); } // Retrieve the latest token added to the owner's stack (LIFO). uint256 id = _owned[from_][_owned[from_].length - 1]; // Transfer the token to the contract. _transferERC721(from_, address(0), id); // Record the token in the contract's bank queue. _storedERC721Ids.pushFront(id); } /// @notice Initialization function to set pairs / etc, saving gas by avoiding mint / burn on unnecessary targets function _setERC721TransferExempt( address target_, bool state_ ) internal virtual { // If the target has at least 1 full ERC-20 token, they should not be removed from the exempt list // because if they were and then they attempted to transfer, it would revert as they would not // necessarily have ehough ERC-721s to bank. if (erc20BalanceOf(target_) >= units && !state_) { revert CannotRemoveFromERC721TransferExempt(); } erc721TransferExempt[target_] = state_; } function _getOwnerOf( uint256 id_ ) internal view virtual returns (address ownerOf_) { uint256 data = _ownedData[id_]; assembly { ownerOf_ := and(data, _BITMASK_ADDRESS) } } function _setOwnerOf(uint256 id_, address owner_) internal virtual { uint256 data = _ownedData[id_]; assembly { data := add( and(data, _BITMASK_OWNED_INDEX), and(owner_, _BITMASK_ADDRESS) ) } _ownedData[id_] = data; } function _getOwnedIndex( uint256 id_ ) internal view virtual returns (uint256 ownedIndex_) { uint256 data = _ownedData[id_]; assembly { ownedIndex_ := shr(160, data) } } function _setOwnedIndex(uint256 id_, uint256 index_) internal virtual { uint256 data = _ownedData[id_]; if (index_ > _BITMASK_OWNED_INDEX >> 160) { revert OwnedIndexOverflow(); } assembly { data := add( and(data, _BITMASK_ADDRESS), and(shl(160, index_), _BITMASK_OWNED_INDEX) ) } _ownedData[id_] = data; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC165} from "../lib/interfaces/IERC165.sol"; interface IERC404 is IERC165 { // event Approval(address owner, address spender, uint256 value); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); event Approval( address indexed owner, address indexed spender, uint256 indexed id ); event Transfer(address indexed from, address indexed to, uint256 amount); // event ERC721Transfer( // address indexed from, // address indexed to, // uint256 indexed id // ); error NotFound(); error InvalidId(); error AlreadyExists(); error InvalidRecipient(); error InvalidSender(); error InvalidSpender(); error InvalidOperator(); error UnsafeRecipient(); error NotERC721TransferExempt(); error Unauthorized(); error InsufficientAllowance(); error DecimalsTooLow(); error CannotRemoveFromERC721TransferExempt(); error PermitDeadlineExpired(); error InvalidSigner(); error InvalidApproval(); error OwnedIndexOverflow(); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function erc20TotalSupply() external view returns (uint256); function erc721TotalSupply() external view returns (uint256); function balanceOf(address owner_) external view returns (uint256); function erc721BalanceOf(address owner_) external view returns (uint256); function erc20BalanceOf(address owner_) external view returns (uint256); function erc721TransferExempt( address account_ ) external view returns (bool); function isApprovedForAll( address owner_, address operator_ ) external view returns (bool); function allowance( address owner_, address spender_ ) external view returns (uint256); function owned(address owner_) external view returns (uint256[] memory); function ownerOf(uint256 id_) external view returns (address erc721Owner); function tokenURI(uint256 id_) external view returns (string memory); function approve( address spender_, uint256 valueOrId_ ) external returns (bool); function setApprovalForAll(address operator_, bool approved_) external; function transferFrom( address from_, address to_, uint256 valueOrId_ ) external returns (bool); function transfer(address to_, uint256 amount_) external returns (bool); function erc721TokensBankedInQueue() external view returns (uint256); function safeTransferFrom(address from_, address to_, uint256 id_) external; function safeTransferFrom( address from_, address to_, uint256 id_, bytes calldata data_ ) external; function DOMAIN_SEPARATOR() external view returns (bytes32); function permit( address owner_, address spender_, uint256 value_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_ ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/DoubleEndedQueue.sol) // Modified by Pandora Labs to support native uint256 operations pragma solidity ^0.8.20; /** * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that * the existing queue contents are left in storage. * * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be * used in storage, and not in memory. * ```solidity * DoubleEndedQueue.Bytes32Deque queue; * ``` */ library DoubleEndedQueue { /** * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty. */ error QueueEmpty(); /** * @dev A push operation couldn't be completed due to the queue being full. */ error QueueFull(); /** * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds. */ error QueueOutOfBounds(); /** * @dev Indices are 128 bits so begin and end are packed in a single storage slot for efficient access. * * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and * lead to unexpected behavior. * * The first item is at data[begin] and the last item is at data[end - 1]. This range can wrap around. */ struct Uint256Deque { uint128 _begin; uint128 _end; mapping(uint128 index => uint256) _data; } /** * @dev Inserts an item at the end of the queue. * * Reverts with {QueueFull} if the queue is full. */ function pushBack(Uint256Deque storage deque, uint256 value) internal { unchecked { uint128 backIndex = deque._end; if (backIndex + 1 == deque._begin) revert QueueFull(); deque._data[backIndex] = value; deque._end = backIndex + 1; } } /** * @dev Removes the item at the end of the queue and returns it. * * Reverts with {QueueEmpty} if the queue is empty. */ function popBack( Uint256Deque storage deque ) internal returns (uint256 value) { unchecked { uint128 backIndex = deque._end; if (backIndex == deque._begin) revert QueueEmpty(); --backIndex; value = deque._data[backIndex]; delete deque._data[backIndex]; deque._end = backIndex; } } /** * @dev Inserts an item at the beginning of the queue. * * Reverts with {QueueFull} if the queue is full. */ function pushFront(Uint256Deque storage deque, uint256 value) internal { unchecked { uint128 frontIndex = deque._begin - 1; if (frontIndex == deque._end) revert QueueFull(); deque._data[frontIndex] = value; deque._begin = frontIndex; } } /** * @dev Removes the item at the beginning of the queue and returns it. * * Reverts with `QueueEmpty` if the queue is empty. */ function popFront( Uint256Deque storage deque ) internal returns (uint256 value) { unchecked { uint128 frontIndex = deque._begin; if (frontIndex == deque._end) revert QueueEmpty(); value = deque._data[frontIndex]; delete deque._data[frontIndex]; deque._begin = frontIndex + 1; } } /** * @dev Returns the item at the beginning of the queue. * * Reverts with `QueueEmpty` if the queue is empty. */ function front( Uint256Deque storage deque ) internal view returns (uint256 value) { if (empty(deque)) revert QueueEmpty(); return deque._data[deque._begin]; } /** * @dev Returns the item at the end of the queue. * * Reverts with `QueueEmpty` if the queue is empty. */ function back( Uint256Deque storage deque ) internal view returns (uint256 value) { if (empty(deque)) revert QueueEmpty(); unchecked { return deque._data[deque._end - 1]; } } /** * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at * `length(deque) - 1`. * * Reverts with `QueueOutOfBounds` if the index is out of bounds. */ function at( Uint256Deque storage deque, uint256 index ) internal view returns (uint256 value) { if (index >= length(deque)) revert QueueOutOfBounds(); // By construction, length is a uint128, so the check above ensures that index can be safely downcast to uint128 unchecked { return deque._data[deque._begin + uint128(index)]; } } /** * @dev Resets the queue back to being empty. * * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses * out on potential gas refunds. */ function clear(Uint256Deque storage deque) internal { deque._begin = 0; deque._end = 0; } /** * @dev Returns the number of items in the queue. */ function length(Uint256Deque storage deque) internal view returns (uint256) { unchecked { return uint256(deque._end - deque._begin); } } /** * @dev Returns true if the queue is empty. */ function empty(Uint256Deque storage deque) internal view returns (bool) { return deque._end == deque._begin; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library ERC20Events { event Approval( address indexed owner, address indexed spender, uint256 value ); event Transfer(address indexed from, address indexed to, uint256 amount); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library ERC721Events { event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); event Approval( address indexed owner, address indexed spender, uint256 indexed id ); event Transfer( address indexed from, address indexed to, uint256 indexed id ); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.20; abstract contract ERC721Receiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721Receiver.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; struct PoolData { address poolAddress; address quoteToken; uint24 fee; uint256 positionId; uint160 sqrtPriceX96; int24 tickLower; int24 tickUpper; uint128 liquidity; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.9; struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. // EDIT for 0.8 compatibility: // see: https://ethereum.stackexchange.com/questions/96642/unary-operator-cannot-be-applied-to-type-uint256 uint256 twos = denominator & (~denominator + 1); // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title PoolAddress modified to have <0.8 POOL_INIT_CODE_HASH library PoolAddress { bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; /// @notice The identifying key of the pool struct PoolKey { address token0; address token1; uint24 fee; } /// @notice Returns PoolKey: the ordered tokens with the matched fee levels /// @param tokenA The first token of a pool, unsorted /// @param tokenB The second token of a pool, unsorted /// @param fee The fee level of the pool /// @return Poolkey The pool details with ordered token0 and token1 assignments function getPoolKey( address tokenA, address tokenB, uint24 fee ) internal pure returns (PoolKey memory) { if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); return PoolKey({ token0: tokenA, token1: tokenB, fee: fee }); } /// @notice Deterministically computes the pool address given the factory and PoolKey /// @param factory The Uniswap V3 factory contract address /// @param key The PoolKey /// @return pool The contract address of the V3 pool function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) { require(key.token0 < key.token1); pool = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256(abi.encode(key.token0, key.token1, key.fee)), POOL_INIT_CODE_HASH ) ) ) ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 int24 internal constant MAX_TICK = -MIN_TICK; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) /// at the given tick function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); // EDIT: 0.8 compatibility require(absTick <= uint256(int256(MAX_TICK)), "T"); uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; if (tick > 0) ratio = type(uint256).max / ratio; // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtRatio of the output price is always consistent sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); } /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) { // second inequality must be < because the price can never reach the price at the max tick require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, "R"); uint256 ratio = uint256(sqrtPriceX96) << 32; uint256 r = ratio; uint256 msb = 0; assembly { let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(5, gt(r, 0xFFFFFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(4, gt(r, 0xFFFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(3, gt(r, 0xFF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(2, gt(r, 0xF)) msb := or(msb, f) r := shr(f, r) } assembly { let f := shl(1, gt(r, 0x3)) msb := or(msb, f) r := shr(f, r) } assembly { let f := gt(r, 0x1) msb := or(msb, f) } if (msb >= 128) r = ratio >> (msb - 127); else r = ratio << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; } }
/* Attestation decode and validation */ /* AlphaWallet 2021 - 2022 */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IERC5169.sol"; abstract contract ERC5169 is IERC5169 { string[] private _scriptURI; function scriptURI() external view override returns (string[] memory) { return _scriptURI; } function setScriptURI(string[] memory newScriptURI) external override { _authorizeSetScripts(newScriptURI); _scriptURI = newScriptURI; emit ScriptUpdate(newScriptURI); } function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC5169).interfaceId; } /** * @dev Function that should revert when `msg.sender` is not authorized to set script URI. Called by * {setScriptURI}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeSetScripts(string[] memory) internal override onlyOwner {} * ``` */ function _authorizeSetScripts(string[] memory newScriptURI) internal virtual; }
/* Attestation decode and validation */ /* AlphaWallet 2021 - 2022 */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IERC5169 { /// @dev This event emits when the scriptURI is updated, /// so wallets implementing this interface can update a cached script event ScriptUpdate(string[]); /// @notice Get the scriptURI for the contract /// @return The scriptURI function scriptURI() external view returns (string[] memory); /// @notice Update the scriptURI /// emits event ScriptUpdate(string[]) function setScriptURI(string[] memory) external; }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"initialOwner_","type":"address"},{"internalType":"address","name":"initialMintRecipient_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"CannotRemoveFromERC721TransferExempt","type":"error"},{"inputs":[],"name":"DecimalsTooLow","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InvalidApproval","type":"error"},{"inputs":[],"name":"InvalidId","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"NotERC721TransferExempt","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnedIndexOverflow","type":"error"},{"inputs":[],"name":"PermitDeadlineExpired","type":"error"},{"inputs":[],"name":"QueueEmpty","type":"error"},{"inputs":[],"name":"QueueFull","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"BaseUriUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ERC20Burn","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"}],"indexed":false,"internalType":"struct PoolData","name":"poolData","type":"tuple"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ReceiveTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"RefundETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string[]","name":"","type":"string[]"}],"name":"ScriptUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"_transferWithTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"calculateERC721Transfers","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPoolData","outputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTick","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc721BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TokensBankedInQueue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"erc721TransferExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialMintRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"}],"name":"liquifyAndCollect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"owned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"erc721Owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"positionManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registerAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scriptURI","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"newScriptURI","type":"string[]"}],"name":"setScriptURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"swapAndLiquify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapRouterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxPercent","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tickThreshold","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"units","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101006040526127106010556011805462ffffff191662013880179055601e805460ff191690553480156200003357600080fd5b506040516200635c3803806200635c8339810160408190526200005691620008e5565b81816103e8620138806040518060400160405280600681526020016515d213cd0c0d60d21b8152506040518060400160405280600381526020016257484f60e81b81525060126064838383838b60006001600160a01b0316816001600160a01b031603620000df57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000ea8162000220565b506003620000f98582620009c1565b506004620001088482620009c1565b5060128260ff1610156200012f576040516398790fd560e01b815260040160405180910390fd5b60ff8083166080819052908216906200014a90600a62000ba2565b62000156919062000bba565b60a0524660c0526200016762000270565b60e052505050601087905550601180546001600160a01b0389166301000000026001600160b81b031990911662ffffff881617179055620001aa8760016200030c565b620001c98760a051601054620001c1919062000bba565b60006200037f565b50505050505050506040518060400160405280601a81526020017f68747470733a2f2f77686f3430342e7774662f6173736574732f000000000000815250601c9081620002179190620009c1565b50505062000ce9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6003604051620002a4919062000bd4565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60a0516001600160a01b0383166000908152600760205260409020541015801562000335575080155b156200035457604051630e422acf60e21b815260040160405180910390fd5b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b6001600160a01b038316620003a757604051634e46966960e11b815260040160405180910390fd5b620003b56000848462000404565b8015620003ff57600060a05183620003ce919062000c52565b905060005b81811015620003fc57620003e785620004b6565b80620003f38162000c75565b915050620003d3565b50505b505050565b6001600160a01b0383166200043357806005600082825462000427919062000c91565b90915550620004639050565b6001600160a01b038316600090815260076020526040812080548392906200045d90849062000ca7565b90915550505b6001600160a01b03808316600081815260076020526040908190208054850190555190918516906000805160206200633c83398151915290620004a99085815260200190565b60405180910390a3505050565b6001600160a01b038116620004de57604051634e46966960e11b815260040160405180910390fd5b6000620004ff600154600160801b81046001600160801b0390811691161490565b62000518576200051060016200057a565b905062000535565b600680549060006200052a8362000c75565b919050555060065490505b6000818152600b60205260409020546001600160a01b031680156200056d5760405163119b4fd360e11b815260040160405180910390fd5b620003ff818484620005eb565b80546000906001600160801b03600160801b8204811691168103620005b2576040516375e52f4f60e01b815260040160405180910390fd5b600019016001600160801b039081166000818152600185016020526040812080549190558454909216600160801b909102179092555090565b601e5460ff1615156001036200067d576000546001600160a01b0316331480620006265750601154630100000090046001600160a01b031633145b80620006415750336000908152601d602052604090205460ff165b6200067d5760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b6044820152606401620000d6565b620003ff8383836001600160a01b038316156200079e57600081815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c90915281208054620006d69060019062000ca7565b81548110620006e957620006e962000cbd565b906000526020600020015490508181146200075c576000828152600b602052604081205460a01c6001600160a01b0386166000908152600c60205260409020805491925083918390811062000742576200074262000cbd565b6000918252602090912001556200075a828262000860565b505b6001600160a01b0384166000908152600c6020526040902080548062000786576200078662000cd3565b60019003818190600052602060002001600090559055505b6001600160a01b038216156200081b576000818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c83529083208054600181810183558286529385200185905592529054620008159183916200080f919062000ca7565b62000860565b6200082b565b6000818152600b60205260408120555b80826001600160a01b0316846001600160a01b03166000805160206200633c83398151915260405160405180910390a4505050565b6000828152600b60205260409020546001600160601b038211156200089857604051633f2cd0e360e21b815260040160405180910390fd5b6000928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b80516001600160a01b0381168114620008e057600080fd5b919050565b60008060408385031215620008f957600080fd5b6200090483620008c8565b91506200091460208401620008c8565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200094857607f821691505b6020821081036200096957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620003ff57600081815260208120601f850160051c81016020861015620009985750805b601f850160051c820191505b81811015620009b957828155600101620009a4565b505050505050565b81516001600160401b03811115620009dd57620009dd6200091d565b620009f581620009ee845462000933565b846200096f565b602080601f83116001811462000a2d576000841562000a145750858301515b600019600386901b1c1916600185901b178555620009b9565b600085815260208120601f198616915b8281101562000a5e5788860151825594840194600190910190840162000a3d565b508582101562000a7d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000ae457816000190482111562000ac85762000ac862000a8d565b8085161562000ad657918102915b93841c939080029062000aa8565b509250929050565b60008262000afd5750600162000b9c565b8162000b0c5750600062000b9c565b816001811462000b25576002811462000b305762000b50565b600191505062000b9c565b60ff84111562000b445762000b4462000a8d565b50506001821b62000b9c565b5060208310610133831016604e8410600b841016171562000b75575081810a62000b9c565b62000b81838362000aa3565b806000190482111562000b985762000b9862000a8d565b0290505b92915050565b600062000bb360ff84168362000aec565b9392505050565b808202811582820484141762000b9c5762000b9c62000a8d565b600080835462000be48162000933565b6001828116801562000bff576001811462000c155762000c46565b60ff198416875282151583028701945062000c46565b8760005260208060002060005b8581101562000c3d5781548a82015290840190820162000c22565b50505082870194505b50929695505050505050565b60008262000c7057634e487b7160e01b600052601260045260246000fd5b500490565b60006001820162000c8a5762000c8a62000a8d565b5060010190565b8082018082111562000b9c5762000b9c62000a8d565b8181038181111562000b9c5762000b9c62000a8d565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e0516155b062000d8c60003960006110dc015260006110ac0152600081816108d001528181610ff601528181611db401528181611de201528181611e0e01528181611e3501528181612cc701528181612d0b01528181612d8e01528181612db801528181612e1601528181612ed101528181612efd01528181612f2401528181612f6b0152612f920152600061059a01526155b06000f3fe60806040526004361061031e5760003560e01c80637541f41c116101ab578063ab01b469116100f7578063d505accf11610095578063e985e9c51161006f578063e985e9c514610aa9578063f2fde38b14610ae4578063f31af75114610b04578063fe85b42b14610b2457600080fd5b8063d505accf14610a31578063dd62ed3e14610a51578063e3d61eb314610a8957600080fd5b8063b88d4fde116100d1578063b88d4fde146109b5578063c5ab3ba6146109d5578063c77cd5ac146109ea578063c87b56dd14610a1157600080fd5b8063ab01b46914610932578063b1ab931714610952578063b3f9ea341461097f57600080fd5b80638da5cb5b1161016457806395d89b411161013e57806395d89b41146108a9578063976a8435146108be578063a22cb465146108f2578063a9059cbb1461091257600080fd5b80638da5cb5b1461085657806390fcdb3614610874578063933ab7a41461089457600080fd5b80637541f41c1461079c5780637a8a1113146107cc5780637ecebe00146107ec5780638129fc1c14610819578063857242de1461082157806389fb4c661461084157600080fd5b80631bc392ae1161026a57806349fa7fd8116102235780636352211e116101fd5780636352211e146107255780636c0360eb1461074557806370a082311461075a578063715018a61461078757600080fd5b806349fa7fd81461061d5780634bb309121461063d5780635eed923e1461065f57600080fd5b80631bc392ae1461055257806323b872dd14610568578063313ce567146105885780633644e515146105ce57806342842e0e146105e35780634524c4ab1461060357600080fd5b8063095ea7b3116102d757806313e7c9d8116102b157806313e7c9d8146104cb578063158ef93e146104fb578063173865ad1461051c57806318160ddd1461053c57600080fd5b8063095ea7b31461046657806309d890d51461048657806309f0ef651461049b57600080fd5b806301ffc9a71461033357806302519da314610368578063045b7dca146103ac578063065e5360146103c257806306fdde03146103f6578063081812fc1461041857600080fd5b3661032e5761032c34610b3a565b005b600080fd5b34801561033f57600080fd5b5061035361034e36600461456d565b610bd7565b60405190151581526020015b60405180910390f35b34801561037457600080fd5b5061039e61038336600461459f565b6001600160a01b031660009081526007602052604090205490565b60405190815260200161035f565b3480156103b857600080fd5b5061039e60105481565b3480156103ce57600080fd5b506017546103e3906301000000900460020b81565b60405160029190910b815260200161035f565b34801561040257600080fd5b5061040b610c02565b60405161035f919061460c565b34801561042457600080fd5b5061044e61043336600461461f565b6009602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161035f565b34801561047257600080fd5b50610353610481366004614638565b610c90565b34801561049257600080fd5b5061039e610dff565b3480156104a757600080fd5b506103536104b636600461459f565b600d6020526000908152604090205460ff1681565b3480156104d757600080fd5b506103536104e636600461459f565b601d6020526000908152604090205460ff1681565b34801561050757600080fd5b5060115461035390600160b81b900460ff1681565b34801561052857600080fd5b5061032c61053736600461461f565b610e29565b34801561054857600080fd5b5061039e60055481565b34801561055e57600080fd5b5061039e60185481565b34801561057457600080fd5b50610353610583366004614664565b610ede565b34801561059457600080fd5b506105bc7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff909116815260200161035f565b3480156105da57600080fd5b5061039e6110a8565b3480156105ef57600080fd5b5061032c6105fe366004614664565b6110fe565b34801561060f57600080fd5b506017546103e39060020b81565b34801561062957600080fd5b5061032c6106383660046146ba565b6111d9565b34801561064957600080fd5b50610652611271565b60405161035f91906146d7565b34801561066b57600080fd5b506012546013546014546015546016546106c4946001600160a01b03908116948082169462ffffff600160a01b928390041694909392811692918104600290810b92600160b81b909204900b906001600160801b031688565b604080516001600160a01b03998a168152978916602089015262ffffff90961695870195909552606086019390935294166080840152600293840b60a084015290920b60c08201526001600160801b0390911660e08201526101000161035f565b34801561073157600080fd5b5061044e61074036600461461f565b61134a565b34801561075157600080fd5b5061040b6113a7565b34801561076657600080fd5b5061039e61077536600461459f565b60076020526000908152604090205481565b34801561079357600080fd5b5061032c6113b4565b3480156107a857600080fd5b506011546107b89062ffffff1681565b60405162ffffff909116815260200161035f565b3480156107d857600080fd5b50601a5461044e906001600160a01b031681565b3480156107f857600080fd5b5061039e61080736600461459f565b600e6020526000908152604090205481565b61032c6113c8565b34801561082d57600080fd5b5061035361083c366004614664565b6114e9565b34801561084d57600080fd5b5060055461039e565b34801561086257600080fd5b506000546001600160a01b031661044e565b34801561088057600080fd5b50601b5461044e906001600160a01b031681565b3480156108a057600080fd5b5061032c6115f1565b3480156108b557600080fd5b5061040b6116a6565b3480156108ca57600080fd5b5061039e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156108fe57600080fd5b5061032c61090d366004614747565b6116b3565b34801561091e57600080fd5b5061035361092d366004614638565b611746565b34801561093e57600080fd5b5061032c61094d366004614747565b61177a565b34801561095e57600080fd5b5061097261096d36600461459f565b6117ad565b60405161035f9190614780565b34801561098b57600080fd5b5061039e61099a36600461459f565b6001600160a01b03166000908152600c602052604090205490565b3480156109c157600080fd5b5061032c6109d03660046147c4565b611819565b3480156109e157600080fd5b5060065461039e565b3480156109f657600080fd5b5060115461044e90630100000090046001600160a01b031681565b348015610a1d57600080fd5b5061040b610a2c36600461461f565b6118dd565b348015610a3d57600080fd5b5061032c610a4c366004614872565b611a86565b348015610a5d57600080fd5b5061039e610a6c3660046148e3565b600860209081526000928352604080842090915290825290205481565b348015610a9557600080fd5b5061032c610aa436600461497c565b611cd2565b348015610ab557600080fd5b50610353610ac43660046148e3565b600a60209081526000928352604080842090915290825290205460ff1681565b348015610af057600080fd5b5061032c610aff36600461459f565b611d29565b348015610b1057600080fd5b50610972610b1f366004614638565b611d67565b348015610b3057600080fd5b5061039e60195481565b60408051600481526024810182526020810180516001600160e01b0316630d0e30db60e41b1790529051600091829173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2918591610b8b9190614aa4565b60006040518083038185875af1925050503d8060008114610bc8576040519150601f19603f3d011682016040523d82523d6000602084013e610bcd565b606091505b5090949350505050565b600063a86517a160e01b6001600160e01b031983161480610bfc5750610bfc82611f77565b92915050565b60038054610c0f90614ac0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3b90614ac0565b8015610c885780601f10610c5d57610100808354040283529160200191610c88565b820191906000526020600020905b815481529060010190602001808311610c6b57829003601f168201915b505050505081565b60006006548211158015610ca45750600082115b15610d72576000828152600b602052604090205482906001600160a01b0316338114801590610cf757506001600160a01b0381166000908152600a6020908152604080832033845290915290205460ff16155b15610d14576040516282b42960e81b815260040160405180910390fd5b60008281526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050610df6565b6001600160a01b038316610d9957604051635461585f60e01b815260040160405180910390fd5b3360008181526008602090815260408083206001600160a01b03881680855290835292819020869055518581528593917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b50600192915050565b6000610e246001546001600160801b03808216600160801b9092048116919091031690565b905090565b610e31611fad565b30600090815260076020526040902054600390610e4f906002614b0a565b610e599190614b37565b811115610ea35760405162461bcd60e51b8152602060048201526013602482015272616d6f756e7420697320746f6f206c6172676560681b60448201526064015b60405180910390fd5b6000610eae82611fda565b90508015610eda5730600090815260076020526040902054610eda90610ed5600284614b37565b611ff6565b5050565b60006001600160a01b038416610f0757604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b038316610f2e57604051634e46966960e11b815260040160405180910390fd5b600654821161102b576000828152600b602052604090205482906001600160a01b03868116911614610f72576040516282b42960e81b815260040160405180910390fd5b336001600160a01b03861614801590610faf57506001600160a01b0385166000908152600a6020908152604080832033845290915290205460ff16155b8015610fd257506000818152600960205260409020546001600160a01b03163314155b15610fef576040516282b42960e81b815260040160405180910390fd5b61101a85857f0000000000000000000000000000000000000000000000000000000000000000612087565b611025858583612143565b5061109d565b6001600160a01b038416600090815260086020908152604080832033845290915290205482906000198114611089576110648282614b4b565b6001600160a01b03871660009081526008602090815260408083203384529091529020555b6110948686846114e9565b925050506110a1565b5060015b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146110d957610e246121db565b507f000000000000000000000000000000000000000000000000000000000000000090565b611109838383610ede565b506001600160a01b0382163b158015906111b65750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a99190614b5e565b6001600160e01b03191614155b156111d457604051633da6393160e01b815260040160405180910390fd5b505050565b6111e1611fad565b6016546001600160801b0390811690821611156112395760405162461bcd60e51b81526020600482015260166024820152756c697175696469747920697320746f6f206c6172676560501b6044820152606401610e9a565b6001600160801b038116156112515761125181612275565b6014546011546111d49190630100000090046001600160a01b03166122e6565b6060600f805480602002602001604051908101604052809291908181526020016000905b828210156113415783829060005260206000200180546112b490614ac0565b80601f01602080910402602001604051908101604052809291908181526020018280546112e090614ac0565b801561132d5780601f106113025761010080835404028352916020019161132d565b820191906000526020600020905b81548152906001019060200180831161131057829003601f168201915b505050505081526020019060010190611295565b50505050905090565b6000818152600b60205260408120546001600160a01b03169050600654821180611372575081155b8061138457506001600160a01b038116155b156113a25760405163c5723b5160e01b815260040160405180910390fd5b919050565b601c8054610c0f90614ac0565b6113bc611fad565b6113c66000612401565b565b6113d0611fad565b73c36442b4a4522e871399cd717abdd847ab11fe8873e592427a0aece92de3edee1f18e0157c05861564341561140b5761140934610b3a565b505b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2301061143b576c39bc2ab9629fb8000000000000611449565b6b046f1de7bc353a00000000005b6cffffffffffffffffffffffffff169050600061146582612451565b9050600061147161253e565b9050818110156114bc5760405162461bcd60e51b81526020600482015260166024820152757765746820616d6f756e7420697320746f6f206c6f7760501b6044820152606401610e9a565b6114e283610bb873c02aaa39b223fe8d0a0e5c4f27ead9083c756cc285603c8a8a612607565b5050505050565b60008060006114f9868686612aef565b91509150801561156a5761150f86600086612c51565b5061151a8585612fe5565b836005600082825461152c9190614b4b565b90915550506040518481527f77dd5e627769f9468b3e9ef3f0d14fdf2cca856af36dd6aa591989bdf3957685906020015b60405180910390a16115e5565b81156115d857611584868661157f8588614b4b565b612c51565b50611590863084612c51565b5081601960008282546115a39190614b7b565b90915550506040518281527fed9d4923888165f7fbf184c0010cb4a535efc8f5ac2b5ec687473e90399715529060200161155d565b6115e3868686612c51565b505b50600195945050505050565b6115f9611fad565b601d6020527f702cd3c0838130d667938bb2b71b963651fdfee2c3f214726373ed0ce96d20198054600160ff1991821681179092557f6bee7e1db5ac34d873578a26025b34efebb8b360efb97ecffdd8274ce6bcaba28054821683179055735b93a825829f4b7b5177c259edc22b63d6e4e3806000527f4f1a6c0e8779a034cf6fcf5f7fb07fc8951643aa66e5a8eee0ceda369b17f0958054821683179055601e80549091169091179055565b60048054610c0f90614ac0565b6001600160a01b0382166116da5760405163ccea9e6f60e01b815260040160405180910390fd5b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60006001600160a01b03831661176f57604051634e46966960e11b815260040160405180910390fd5b6110a13384846114e9565b611782611fad565b6001600160a01b03919091166000908152601d60205260409020805460ff1916911515919091179055565b6001600160a01b0381166000908152600c602090815260409182902080548351818402810184019094528084526060939283018282801561180d57602002820191906000526020600020905b8154815260200190600101908083116117f9575b50505050509050919050565b611824858585610ede565b506001600160a01b0384163b158015906118bf5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061186f9033908a90899089908990600401614b8e565b6020604051808303816000875af115801561188e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b29190614b5e565b6001600160e01b03191614155b156114e257604051633da6393160e01b815260040160405180910390fd5b60606000826040516020016118f491815260200190565b6040516020818303038152906040528051906020012060f81c905060608060408360ff16116119605760405180604001604052806005815260200164302e706e6760d81b81525091506040518060400160405280600381526020016214995960ea1b8152509050611a41565b60808360ff16116119af5760405180604001604052806005815260200164312e706e6760d81b815250915060405180604001604052806004815260200163426c756560e01b8152509050611a41565b60c08360ff16116119ff5760405180604001604052806005815260200164322e706e6760d81b81525091506040518060400160405280600581526020016423b932b2b760d91b8152509050611a41565b60405180604001604052806005815260200164332e706e6760d81b815250915060405180604001604052806006815260200165507572706c6560d01b81525090505b611a4a856131df565b611a556010546131df565b601c8484604051602001611a6d959493929190614c52565b6040516020818303038152906040529350505050919050565b42841015611aa7576040516305787bdf60e01b815260040160405180910390fd5b6006548511158015611ab95750600085115b15611ad7576040516303e7c1bd60e31b815260040160405180910390fd5b6001600160a01b038616611afe57604051635461585f60e01b815260040160405180910390fd5b60006001611b0a6110a8565b6001600160a01b038a81166000818152600e602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611c16573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580611c4b5750876001600160a01b0316816001600160a01b031614155b15611c6957604051632057875960e21b815260040160405180910390fd5b6001600160a01b0390811660009081526008602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b611cdb81613272565b8051611cee90600f90602084019061449a565b507f9538911740e5519a40db77fb5f637de0d56cdd804318d81ae270cc24fbd8479e81604051611d1e91906146d7565b60405180910390a150565b611d31611fad565b6001600160a01b038116611d5b57604051631e4fbdf760e01b815260006004820152602401610e9a565b611d6481612401565b50565b60606000611d8a846001600160a01b031660009081526007602052604090205490565b6001600160a01b0385166000908152600d602052604090205490915060ff16611f70576000611dd97f000000000000000000000000000000000000000000000000000000000000000085614b37565b90506000611e077f000000000000000000000000000000000000000000000000000000000000000086614e02565b9050611e337f000000000000000000000000000000000000000000000000000000000000000084614b37565b7f0000000000000000000000000000000000000000000000000000000000000000611e5e8386614b4b565b611e689190614b37565b1015611e7c5781611e7881614e16565b9250505b8115611f6d578167ffffffffffffffff811115611e9b57611e9b614911565b604051908082528060200260200182016040528015611ec4578160200160208202803683370190505b50935060005b82811015611f6b576000611edf826001614b7b565b6001600160a01b0389166000908152600c6020526040902054611f029190614b4b565b6001600160a01b0389166000908152600c6020526040902080549192509082908110611f3057611f30614e2f565b9060005260206000200154868381518110611f4d57611f4d614e2f565b60209081029190910101525080611f6381614e16565b915050611eca565b505b50505b5092915050565b60006001600160e01b0319821663219d65bb60e01b1480610bfc57506001600160e01b031982166301ffc9a760e01b1492915050565b6000546001600160a01b031633146113c65760405163118cdaa760e01b8152336004820152602401610e9a565b601354600090610bfc9030906001600160a01b0316818561327a565b60135430906001600160a01b031683838284111561201357919291905b600061202560126002015484846133d4565b909450925090506001600160801b0381161561207e57601680548291906000906120599084906001600160801b0316614e45565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b50505050505050565b6001600160a01b0383166120b25780600560008282546120a79190614b7b565b909155506120e09050565b6001600160a01b038316600090815260076020526040812080548392906120da908490614b4b565b90915550505b6001600160a01b03808316600081815260076020526040908190208054850190555190918516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906121369085815260200190565b60405180910390a3505050565b601e5460ff1615156001036121d0576000546001600160a01b031633148061217c5750601154630100000090046001600160a01b031633145b806121965750336000908152601d602052604090205460ff165b6121d05760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b6044820152606401610e9a565b6111d48383836134fa565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600360405161220d9190614e65565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600080612287601260020154846136d2565b91509150600082118061229a5750600081115b156111d457601680548491906000906122bd9084906001600160801b0316614e71565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b604080516080810182528381526001600160a01b03838116602083019081526001600160801b0383850181815260608501828152601a549651602481018a905293518516604485015290518216606484015251166084820152600093849392849283929091169063fc6f78659060a4015b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516123909190614aa4565b6000604051808303816000865af19150503d80600081146123cd576040519150601f19603f3d011682016040523d82523d6000602084013e6123d2565b606091505b509150915081156123f757808060200190518101906123f19190614e91565b90955093505b5050509250929050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b306000908152600760205260408120546001600160801b036001600160a01b038416116124d557600061248d6001600160a01b03851680614b0a565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc230106124be576124b9600160c01b8383613755565b6124cd565b6124cd8183600160c01b613755565b925050612538565b60006124f46001600160a01b0385168068010000000000000000613755565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2301061252557612520600160801b8383613755565b612534565b6125348183600160801b613755565b9250505b50919050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17905290516000918291829173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2916125a09190614aa4565b600060405180830381855afa9150503d80600081146125db576040519150601f19603f3d011682016040523d82523d6000602084013e6125e0565b606091505b5091509150811561260257808060200190518101906125ff9190614eb5565b92505b505090565b61260f611fad565b601154600160b81b900460ff161561265b5760405162461bcd60e51b815260206004820152600f60248201526e1a185cc81a5b9a5d1a585b1a5e9959608a1b6044820152606401610e9a565b601a80546001600160a01b03199081166001600160a01b0385811691909117909255601b80548216848416179055601380548884166001600160b81b03199091168117600160a01b62ffffff8c16021790915560158054909216928a1692909217905530600081815260076020526040902054909187919087908411156126e157919291905b6126ed84600019613803565b506126fa83600019613803565b50600061270985858d8f6139bc565b6017805462ffffff90931663010000000265ffffff0000001990931692909217909155601280546001600160a01b039093166001600160a01b03199093168317905591501580159061275f57508060020b600014155b6127a45760405162461bcd60e51b81526020600482015260166024820152751a5b9a5d1a585b1a5e99481c1bdbdb0819985a5b195960521b6044820152606401610e9a565b6017805462ffffff198116630100000090910462ffffff161790556013546001600160a01b03163010156128ad5760175481906127e590829060020b614ece565b6127ef9190614f08565b6015805462ffffff92909216600160a01b0262ffffff60a01b19909216919091179055601754600060029190910b12156128625760158054829190601490612842908490600160a01b900460020b614f28565b92506101000a81548162ffffff021916908360020b62ffffff1602179055505b8080612871620d89e719614f4d565b61287b9190614ece565b6128859190614f08565b6015805462ffffff92909216600160b81b0262ffffff60b81b1990921691909117905561297a565b60175481906128c090829060020b614ece565b6128ca9190614f08565b6015805462ffffff92909216600160b81b0262ffffff60b81b19909216919091179055601754600060029190910b131561293d576015805482919060179061291d908490600160b81b900460020b614f6f565b92506101000a81548162ffffff021916908360020b62ffffff1602179055505b8061294c81620d89e719614ece565b6129569190614f08565b6015805462ffffff92909216600160a01b0262ffffff60a01b199092169190911790555b61ffff8816156129ee5760125460009061299d906001600160a01b03168a613c39565b9050806129ec5760405162461bcd60e51b815260206004820152601e60248201527f696e697469616c697a65206f62736572766174696f6e73206661696c656400006044820152606401610e9a565b505b601554612a1b90869086908e9087908790600160a01b8104600290810b91600160b81b9004900b30613cde565b5050601680546001600160801b0319166001600160801b03929092169190911790556014819055600003612a915760405162461bcd60e51b815260206004820152601b60248201527f696e697469616c697a65206c6971756964697479206661696c656400000000006044820152606401610e9a565b426018556011805460ff60b81b1916600160b81b1790556040517fc6cb858e754b4efdad8980cee030a8e8725c4e6e690d9b77733a89b5dd5601a190612ad990601290614f94565b60405180910390a1505050505050505050505050565b6011546000908190630100000090046001600160a01b0316331480612b1e5750601b546001600160a01b031633145b80612b3157506001600160a01b03851630145b80612b4957506012546001600160a01b038581169116145b15612b5957506000905080612c49565b612b61613e4b565b6017805462ffffff9290921663010000000265ffffff00000019909216919091179055612b986013546001600160a01b0316301090565b15612bfe57601754600281810b6301000000909204900b1315612bdd57601154620f424090612bcc9062ffffff1685614b0a565b612bd69190614b37565b9150612c49565b601754600281810b6301000000909204900b1215612bf9575060015b612c49565b601754600281810b6301000000909204900b1215612c2d57601154620f424090612bcc9062ffffff1685614b0a565b601754600281810b6301000000909204900b1315612c49575060015b935093915050565b6001600160a01b03838116600090815260076020526040808220549285168252812054909190612c82868686612087565b6001600160a01b038087166000908152600d602052604080822054928816825290205460ff9182169116818015612cb65750805b612fd7578115612d69576000612cec7f000000000000000000000000000000000000000000000000000000000000000085614b37565b6001600160a01b038916600090815260076020526040902054612d30907f000000000000000000000000000000000000000000000000000000000000000090614b37565b612d3a9190614b4b565b905060005b81811015612d6257612d5089614142565b80612d5a81614e16565b915050612d3f565b5050612fd7565b8015612e0f576001600160a01b038816600090815260076020526040812054612db3907f000000000000000000000000000000000000000000000000000000000000000090614b37565b612ddd7f000000000000000000000000000000000000000000000000000000000000000087614b37565b612de79190614b4b565b905060005b81811015612d6257612dfd8a6141fb565b80612e0781614e16565b915050612dec565b6000612e3b7f000000000000000000000000000000000000000000000000000000000000000088614b37565b905060005b81811015612ec9576001600160a01b038a166000908152600c6020526040812054612e6d90600190614b4b565b6001600160a01b038c166000908152600c602052604081208054929350909183908110612e9c57612e9c614e2f565b90600052602060002001549050612eb48c8c83612143565b50508080612ec190614e16565b915050612e40565b506000612ef67f000000000000000000000000000000000000000000000000000000000000000089614e02565b9050612f227f000000000000000000000000000000000000000000000000000000000000000087614b37565b7f0000000000000000000000000000000000000000000000000000000000000000612f4d8389614b4b565b612f579190614b37565b1015612f6657612f668a6141fb565b612f907f000000000000000000000000000000000000000000000000000000000000000086614b37565b7f0000000000000000000000000000000000000000000000000000000000000000612fbb8388614b7b565b612fc59190614b37565b1115612fd457612fd489614142565b50505b506001979650505050505050565b6001600160a01b03821661300c57604051636edaef2f60e11b815260040160405180910390fd5b601354604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b179052905160009283926001600160a01b03909116916130659190614aa4565b600060405180830381855afa9150503d80600081146130a0576040519150601f19603f3d011682016040523d82523d6000602084013e6130a5565b606091505b5091509150816130b55750505050565b6000818060200190518101906130cb9190614eb5565b9050600060055482866130de9190614b0a565b6130e89190614b37565b601354604080516001600160a01b038a81166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151939450600093919092169161314891614aa4565b6000604051808303816000865af19150503d8060008114613185576040519150601f19603f3d011682016040523d82523d6000602084013e61318a565b606091505b50509050801561207e57604080516001600160a01b0389168152602081018490527f289360176646a5f99cb4b6300628426dca46b723f40db3c04449d6ed1745a0e7910160405180910390a150505050505050565b606060006131ec8361427c565b600101905060008167ffffffffffffffff81111561320c5761320c614911565b6040519080825280601f01601f191660200182016040528015613236576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461324057509392505050565b611d64611fad565b60408051610100810182526001600160a01b03868116808352868216602080850191825260135462ffffff600160a01b909104811686880190815289861660608801908152426080890190815260a089018b8152600060c08b0181815260e08c01828152601b548e51602481019c909c5299518c1660448c0152955190961660648a0152925189166084890152905160a48801525160c4870152915160e48601525185166101048086019190915287518086039091018152610124909401875290830180516001600160e01b031663414bf38960e01b17905294518593849392169161336591614aa4565b6000604051808303816000865af19150503d80600081146133a2576040519150601f19603f3d011682016040523d82523d6000602084013e6133a7565b606091505b509150915081156133c957808060200190518101906133c69190614eb5565b93505b505050949350505050565b6040805160c0810182528481526020808201858152828401858152600060608501818152608086018281524260a08801908152601a548951602481018e90529651604488015294516064870152915160848601525160a48501525160c4808501919091528651808503909101815260e4909301865292820180516001600160e01b031663219f5d1760e01b17905293519193849384939092849283926001600160a01b039091169161348591614aa4565b6000604051808303816000865af19150503d80600081146134c2576040519150601f19603f3d011682016040523d82523d6000602084013e6134c7565b606091505b509150915081156134ee57808060200190518101906134e69190615012565b919750955093505b50505093509350939050565b6001600160a01b0383161561360557600081815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c9091528120805461354990600190614b4b565b8154811061355957613559614e2f565b906000526020600020015490508181146135c6576000828152600b602052604081205460a01c6001600160a01b0386166000908152600c6020526040902080549192508391839081106135ae576135ae614e2f565b6000918252602090912001556135c48282614354565b505b6001600160a01b0384166000908152600c602052604090208054806135ed576135ed615049565b60019003818190600052602060002001600090559055505b6001600160a01b0382161561367c576000818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c835290832080546001818101835582865293852001859055925290546136779183916136729190614b4b565b614354565b61368c565b6000818152600b60205260408120555b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6040805160a0810182528381526001600160801b03838116602083019081526000838501818152606085018281524260808701908152601a549751602481018b90529451909516604485015290516064840152516084830152915160a48201529092839291839182916001600160a01b0390911690630c49ccbe9060c401612357565b600080806000198587098587029250828110838203039150508060000361378e576000841161378357600080fd5b5082900490506110a1565b80841161379a57600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008160000361381557506001610bfc565b306001600160a01b038416036138645750306000908152600860209081526040808320601a546001600160a01b0390811685529252808320849055601b54909116825290208190556001610bfc565b601a54604080516001600160a01b039283166024820152604480820186905282518083039091018152606490910182526020810180516001600160e01b031663095ea7b360e01b17905290516000928616916138bf91614aa4565b6000604051808303816000865af19150503d80600081146138fc576040519150601f19603f3d011682016040523d82523d6000602084013e613901565b606091505b5050601b54604080516001600160a01b039283166024820152604480820188905282518083039091018152606490910182526020810180516001600160e01b031663095ea7b360e01b1790529051929350600092918716916139639190614aa4565b6000604051808303816000865af19150503d80600081146139a0576040519150601f19603f3d011682016040523d82523d6000602084013e6139a5565b606091505b505090508180156139b35750805b95945050505050565b601a54604080516001600160a01b038781166024830152868116604483015262ffffff861660648301528481166084808401919091528351808403909101815260a490920183526020820180516001600160e01b03166309f56ab160e11b179052915160009384938493849384939290921691613a399190614aa4565b6000604051808303816000865af19150503d8060008114613a76576040519150601f19603f3d011682016040523d82523d6000602084013e613a7b565b606091505b509150915081613a975760008060009450945094505050613c2f565b80806020019051810190613aab919061505f565b60408051600481526024810182526020810180516001600160e01b0316633850c7bd60e01b179052905191965060009182916001600160a01b03891691613af29190614aa4565b600060405180830381855afa9150503d8060008114613b2d576040519150601f19603f3d011682016040523d82523d6000602084013e613b32565b606091505b509150915081613b5057600080600096509650965050505050613c2f565b80806020019051810190613b6491906150a0565b505060408051600481526024810182526020810180516001600160e01b03166334324e9f60e21b1790529051949b506000955085946001600160a01b038e169450613bb29350909150614aa4565b600060405180830381855afa9150503d8060008114613bed576040519150601f19603f3d011682016040523d82523d6000602084013e613bf2565b606091505b509150915081613c12576000806000985098509850505050505050613c2f565b80806020019051810190613c26919061512f565b96505050505050505b9450945094915050565b6040805161ffff831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166332148f6760e01b179052905160009182916001600160a01b03861691613c9191614aa4565b6000604051808303816000865af19150503d8060008114613cce576040519150601f19603f3d011682016040523d82523d6000602084013e613cd3565b606091505b509095945050505050565b60008060008060006040518061016001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c62ffffff1681526020018960020b81526020018860020b81526020018b81526020018a81526020016000815260200160008152602001876001600160a01b03168152602001428152509050600080601a60009054906101000a90046001600160a01b03166001600160a01b0316638831645684604051602401613d94919061514a565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051613dcd9190614aa4565b6000604051808303816000865af19150503d8060008114613e0a576040519150601f19603f3d011682016040523d82523d6000602084013e613e0f565b606091505b50915091508115613e395780806020019051810190613e2e919061520e565b929950909750955093505b50505098509850985098945050505050565b601154600090600160b81b900460ff16613e69575060175460020b90565b60125460408051600481526024810182526020810180516001600160e01b0316633850c7bd60e01b179052905160009283926001600160a01b0390911691613eb19190614aa4565b600060405180830381855afa9150503d8060008114613eec576040519150601f19603f3d011682016040523d82523d6000602084013e613ef1565b606091505b509150915081613f0857505060175460020b919050565b600080600083806020019051810190613f2191906150a0565b5050601854939750919550935061070892508291613f40915042614b4b565b63ffffffff161015613f5757509195945050505050565b6040805160028082526060820183526000926020830190803683370190505090508181600081518110613f8c57613f8c614e2f565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110613fbb57613fbb614e2f565b63ffffffff9092166020928302919091019091015260125460405160009182916001600160a01b039091169063883bdbfd90613ffb90869060240161524c565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516140349190614aa4565b600060405180830381855afa9150503d806000811461406f576040519150601f19603f3d011682016040523d82523d6000602084013e614074565b606091505b50915091508161408c57509498975050505050505050565b6000818060200190518101906140a291906152f9565b5090506000816000815181106140ba576140ba614e2f565b6020026020010151826001815181106140d5576140d5614e2f565b60200260200101516140e791906153c5565b90506140f963ffffffff8716826153f2565b985060008160060b12801561411f575061411963ffffffff871682615427565b60060b15155b15614132578861412e81615449565b9950505b50969a9950505050505050505050565b6001600160a01b03811661416957604051634e46966960e11b815260040160405180910390fd5b6000614189600154600160801b81046001600160801b0390811691161490565b61419e5761419760016143c0565b90506141b9565b600680549060006141ae83614e16565b919050555060065490505b6000818152600b60205260409020546001600160a01b031680156141f05760405163119b4fd360e11b815260040160405180910390fd5b6111d4818484612143565b6001600160a01b03811661422257604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0381166000908152600c60205260408120805461424890600190614b4b565b8154811061425857614258614e2f565b9060005260206000200154905061427182600083612143565b610eda600182614430565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106142bb5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106142e7576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061430557662386f26fc10000830492506010015b6305f5e100831061431d576305f5e100830492506008015b612710831061433157612710830492506004015b60648310614343576064830492506002015b600a8310610bfc5760010192915050565b6000828152600b60205260409020546bffffffffffffffffffffffff82111561439057604051633f2cd0e360e21b815260040160405180910390fd5b6000928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b80546000906001600160801b03600160801b82048116911681036143f7576040516375e52f4f60e01b815260040160405180910390fd5b600019016001600160801b039081166000818152600185016020526040812080549190558454909216600160801b909102179092555090565b81546001600160801b038082166000190191600160801b900481169082160361446c57604051638acb5f2760e01b815260040160405180910390fd5b6001600160801b0316600081815260018401602052604090209190915581546001600160801b031916179055565b8280548282559060005260206000209081019282156144e0579160200282015b828111156144e057825182906144d090826154ba565b50916020019190600101906144ba565b506144ec9291506144f0565b5090565b808211156144ec576000614504828261450d565b506001016144f0565b50805461451990614ac0565b6000825580601f10614529575050565b601f016020900490600052602060002090810190611d6491905b808211156144ec5760008155600101614543565b6001600160e01b031981168114611d6457600080fd5b60006020828403121561457f57600080fd5b81356110a181614557565b6001600160a01b0381168114611d6457600080fd5b6000602082840312156145b157600080fd5b81356110a18161458a565b60005b838110156145d75781810151838201526020016145bf565b50506000910152565b600081518084526145f88160208601602086016145bc565b601f01601f19169290920160200192915050565b6020815260006110a160208301846145e0565b60006020828403121561463157600080fd5b5035919050565b6000806040838503121561464b57600080fd5b82356146568161458a565b946020939093013593505050565b60008060006060848603121561467957600080fd5b83356146848161458a565b925060208401356146948161458a565b929592945050506040919091013590565b6001600160801b0381168114611d6457600080fd5b6000602082840312156146cc57600080fd5b81356110a1816146a5565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561472c57603f1988860301845261471a8583516145e0565b945092850192908501906001016146fe565b5092979650505050505050565b8015158114611d6457600080fd5b6000806040838503121561475a57600080fd5b82356147658161458a565b9150602083013561477581614739565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156147b85783518352928401929184019160010161479c565b50909695505050505050565b6000806000806000608086880312156147dc57600080fd5b85356147e78161458a565b945060208601356147f78161458a565b935060408601359250606086013567ffffffffffffffff8082111561481b57600080fd5b818801915088601f83011261482f57600080fd5b81358181111561483e57600080fd5b89602082850101111561485057600080fd5b9699959850939650602001949392505050565b60ff81168114611d6457600080fd5b600080600080600080600060e0888a03121561488d57600080fd5b87356148988161458a565b965060208801356148a88161458a565b9550604088013594506060880135935060808801356148c681614863565b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156148f657600080fd5b82356149018161458a565b915060208301356147758161458a565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561495057614950614911565b604052919050565b600067ffffffffffffffff82111561497257614972614911565b5060051b60200190565b6000602080838503121561498f57600080fd5b823567ffffffffffffffff808211156149a757600080fd5b8185019150601f86818401126149bc57600080fd5b82356149cf6149ca82614958565b614927565b81815260059190911b840185019085810190898311156149ee57600080fd5b8686015b83811015614a7a57803586811115614a0a5760008081fd5b8701603f81018c13614a1c5760008081fd5b88810135604088821115614a3257614a32614911565b614a43828901601f19168c01614927565b8281528e82848601011115614a585760008081fd5b828285018d83013760009281018c0192909252508452509187019187016149f2565b509998505050505050505050565b60008151614a9a8185602086016145bc565b9290920192915050565b60008251614ab68184602087016145bc565b9190910192915050565b600181811c90821680614ad457607f821691505b60208210810361253857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610bfc57610bfc614af4565b634e487b7160e01b600052601260045260246000fd5b600082614b4657614b46614b21565b500490565b81810381811115610bfc57610bfc614af4565b600060208284031215614b7057600080fd5b81516110a181614557565b80820180821115610bfc57610bfc614af4565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60008154614bef81614ac0565b60018281168015614c075760018114614c1c57611f6b565b60ff1984168752821515830287019450611f6b565b8560005260208060002060005b85811015614c425781548a820152908401908201614c29565b5050509590910195945050505050565b747b226e616d65223a202257484f343034204e46542360581b81528551600090614c83816015850160208b016145bc565b7f222c226465736372697074696f6e223a224120636f6c6c656374696f6e206f66601591840191820152600160fd1b60358201528651614cca816036840160208b016145bc565b7f20706f7473206f66206c6971756964697479207468617420746f6b656e697a65603692909101918201527f7320646563656e7472616c697a656420726573657276652063757272656e637960568201527f206964656120666f722074686520495135302c20234552433333332e0000000060768201527f222c2265787465726e616c5f75726c223a2268747470733a2f2f77686f34303460928201526f173bba331791161134b6b0b3b2911d1160811b60b2820152614df6614de6614de0614d9f614d9960c286018b614be2565b89614a88565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a224381526e37b637b91116113b30b63ab2911d1160891b6020820152602f0190565b86614a88565b63227d5d7d60e01b815260040190565b98975050505050505050565b600082614e1157614e11614b21565b500690565b600060018201614e2857614e28614af4565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6001600160801b03818116838216019080821115611f7057611f70614af4565b60006110a18284614be2565b6001600160801b03828116828216039080821115611f7057611f70614af4565b60008060408385031215614ea457600080fd5b505080516020909101519092909150565b600060208284031215614ec757600080fd5b5051919050565b60008160020b8360020b80614ee557614ee5614b21565b627fffff19821460001982141615614eff57614eff614af4565b90059392505050565b60008260020b8260020b028060020b9150808214611f7057611f70614af4565b600282810b9082900b03627fffff198112627fffff82131715610bfc57610bfc614af4565b60008160020b627fffff198103614f6657614f66614af4565b60000392915050565b600281810b9083900b01627fffff8113627fffff1982121715610bfc57610bfc614af4565b81546001600160a01b03168152610100810160018301546001600160a01b03808216602085015262ffffff60a092831c16604085015260028086015460608601526003860154918216608086015281831c810b9285019290925260b81c900b60c083015260048301546001600160801b031660e08301819052611f70565b60008060006060848603121561502757600080fd5b8351615032816146a5565b602085015160409095015190969495509392505050565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561507157600080fd5b81516110a18161458a565b8051600281900b81146113a257600080fd5b805161ffff811681146113a257600080fd5b600080600080600080600060e0888a0312156150bb57600080fd5b87516150c68161458a565b96506150d46020890161507c565b95506150e26040890161508e565b94506150f06060890161508e565b93506150fe6080890161508e565b925060a088015161510e81614863565b60c089015190925061511f81614739565b8091505092959891949750929550565b60006020828403121561514157600080fd5b6110a18261507c565b81516001600160a01b031681526101608101602083015161517660208401826001600160a01b03169052565b50604083015161518d604084018262ffffff169052565b5060608301516151a2606084018260020b9052565b5060808301516151b7608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516151fd828501826001600160a01b03169052565b505061014092830151919092015290565b6000806000806080858703121561522457600080fd5b845193506020850151615236816146a5565b6040860151606090960151949790965092505050565b6020808252825182820181905260009190848201906040850190845b818110156147b857835163ffffffff1683529284019291840191600101615268565b600082601f83011261529b57600080fd5b815160206152ab6149ca83614958565b82815260059290921b840181019181810190868411156152ca57600080fd5b8286015b848110156152ee5780516152e18161458a565b83529183019183016152ce565b509695505050505050565b6000806040838503121561530c57600080fd5b825167ffffffffffffffff8082111561532457600080fd5b818501915085601f83011261533857600080fd5b815160206153486149ca83614958565b82815260059290921b8401810191818101908984111561536757600080fd5b948201945b838610156153955785518060060b81146153865760008081fd5b8252948201949082019061536c565b918801519196509093505050808211156153ae57600080fd5b506153bb8582860161528a565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff82131715610bfc57610bfc614af4565b60008160060b8360060b8061540957615409614b21565b667fffffffffffff19821460001982141615614eff57614eff614af4565b60008260060b8061543a5761543a614b21565b808360060b0791505092915050565b60008160020b627fffff19810361546257615462614af4565b6000190192915050565b601f8211156111d457600081815260208120601f850160051c810160208610156154935750805b601f850160051c820191505b818110156154b25782815560010161549f565b505050505050565b815167ffffffffffffffff8111156154d4576154d4614911565b6154e8816154e28454614ac0565b8461546c565b602080601f83116001811461551d57600084156155055750858301515b600019600386901b1c1916600185901b1785556154b2565b600085815260208120601f198616915b8281101561554c5788860151825594840194600190910190840161552d565b508582101561556a5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220bbae53dc555fe3b383ecbd466605053207fb1aa5f5075b539d8dda65c4a3137964736f6c63430008140033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef000000000000000000000000cdf74bff7c62c72775a2cdb83dbc0a1d4866703a000000000000000000000000a6afd4d1226169db19432cf6f26f66a219b9b159
Deployed Bytecode
0x60806040526004361061031e5760003560e01c80637541f41c116101ab578063ab01b469116100f7578063d505accf11610095578063e985e9c51161006f578063e985e9c514610aa9578063f2fde38b14610ae4578063f31af75114610b04578063fe85b42b14610b2457600080fd5b8063d505accf14610a31578063dd62ed3e14610a51578063e3d61eb314610a8957600080fd5b8063b88d4fde116100d1578063b88d4fde146109b5578063c5ab3ba6146109d5578063c77cd5ac146109ea578063c87b56dd14610a1157600080fd5b8063ab01b46914610932578063b1ab931714610952578063b3f9ea341461097f57600080fd5b80638da5cb5b1161016457806395d89b411161013e57806395d89b41146108a9578063976a8435146108be578063a22cb465146108f2578063a9059cbb1461091257600080fd5b80638da5cb5b1461085657806390fcdb3614610874578063933ab7a41461089457600080fd5b80637541f41c1461079c5780637a8a1113146107cc5780637ecebe00146107ec5780638129fc1c14610819578063857242de1461082157806389fb4c661461084157600080fd5b80631bc392ae1161026a57806349fa7fd8116102235780636352211e116101fd5780636352211e146107255780636c0360eb1461074557806370a082311461075a578063715018a61461078757600080fd5b806349fa7fd81461061d5780634bb309121461063d5780635eed923e1461065f57600080fd5b80631bc392ae1461055257806323b872dd14610568578063313ce567146105885780633644e515146105ce57806342842e0e146105e35780634524c4ab1461060357600080fd5b8063095ea7b3116102d757806313e7c9d8116102b157806313e7c9d8146104cb578063158ef93e146104fb578063173865ad1461051c57806318160ddd1461053c57600080fd5b8063095ea7b31461046657806309d890d51461048657806309f0ef651461049b57600080fd5b806301ffc9a71461033357806302519da314610368578063045b7dca146103ac578063065e5360146103c257806306fdde03146103f6578063081812fc1461041857600080fd5b3661032e5761032c34610b3a565b005b600080fd5b34801561033f57600080fd5b5061035361034e36600461456d565b610bd7565b60405190151581526020015b60405180910390f35b34801561037457600080fd5b5061039e61038336600461459f565b6001600160a01b031660009081526007602052604090205490565b60405190815260200161035f565b3480156103b857600080fd5b5061039e60105481565b3480156103ce57600080fd5b506017546103e3906301000000900460020b81565b60405160029190910b815260200161035f565b34801561040257600080fd5b5061040b610c02565b60405161035f919061460c565b34801561042457600080fd5b5061044e61043336600461461f565b6009602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161035f565b34801561047257600080fd5b50610353610481366004614638565b610c90565b34801561049257600080fd5b5061039e610dff565b3480156104a757600080fd5b506103536104b636600461459f565b600d6020526000908152604090205460ff1681565b3480156104d757600080fd5b506103536104e636600461459f565b601d6020526000908152604090205460ff1681565b34801561050757600080fd5b5060115461035390600160b81b900460ff1681565b34801561052857600080fd5b5061032c61053736600461461f565b610e29565b34801561054857600080fd5b5061039e60055481565b34801561055e57600080fd5b5061039e60185481565b34801561057457600080fd5b50610353610583366004614664565b610ede565b34801561059457600080fd5b506105bc7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff909116815260200161035f565b3480156105da57600080fd5b5061039e6110a8565b3480156105ef57600080fd5b5061032c6105fe366004614664565b6110fe565b34801561060f57600080fd5b506017546103e39060020b81565b34801561062957600080fd5b5061032c6106383660046146ba565b6111d9565b34801561064957600080fd5b50610652611271565b60405161035f91906146d7565b34801561066b57600080fd5b506012546013546014546015546016546106c4946001600160a01b03908116948082169462ffffff600160a01b928390041694909392811692918104600290810b92600160b81b909204900b906001600160801b031688565b604080516001600160a01b03998a168152978916602089015262ffffff90961695870195909552606086019390935294166080840152600293840b60a084015290920b60c08201526001600160801b0390911660e08201526101000161035f565b34801561073157600080fd5b5061044e61074036600461461f565b61134a565b34801561075157600080fd5b5061040b6113a7565b34801561076657600080fd5b5061039e61077536600461459f565b60076020526000908152604090205481565b34801561079357600080fd5b5061032c6113b4565b3480156107a857600080fd5b506011546107b89062ffffff1681565b60405162ffffff909116815260200161035f565b3480156107d857600080fd5b50601a5461044e906001600160a01b031681565b3480156107f857600080fd5b5061039e61080736600461459f565b600e6020526000908152604090205481565b61032c6113c8565b34801561082d57600080fd5b5061035361083c366004614664565b6114e9565b34801561084d57600080fd5b5060055461039e565b34801561086257600080fd5b506000546001600160a01b031661044e565b34801561088057600080fd5b50601b5461044e906001600160a01b031681565b3480156108a057600080fd5b5061032c6115f1565b3480156108b557600080fd5b5061040b6116a6565b3480156108ca57600080fd5b5061039e7f0000000000000000000000000000000000000000000000056bc75e2d6310000081565b3480156108fe57600080fd5b5061032c61090d366004614747565b6116b3565b34801561091e57600080fd5b5061035361092d366004614638565b611746565b34801561093e57600080fd5b5061032c61094d366004614747565b61177a565b34801561095e57600080fd5b5061097261096d36600461459f565b6117ad565b60405161035f9190614780565b34801561098b57600080fd5b5061039e61099a36600461459f565b6001600160a01b03166000908152600c602052604090205490565b3480156109c157600080fd5b5061032c6109d03660046147c4565b611819565b3480156109e157600080fd5b5060065461039e565b3480156109f657600080fd5b5060115461044e90630100000090046001600160a01b031681565b348015610a1d57600080fd5b5061040b610a2c36600461461f565b6118dd565b348015610a3d57600080fd5b5061032c610a4c366004614872565b611a86565b348015610a5d57600080fd5b5061039e610a6c3660046148e3565b600860209081526000928352604080842090915290825290205481565b348015610a9557600080fd5b5061032c610aa436600461497c565b611cd2565b348015610ab557600080fd5b50610353610ac43660046148e3565b600a60209081526000928352604080842090915290825290205460ff1681565b348015610af057600080fd5b5061032c610aff36600461459f565b611d29565b348015610b1057600080fd5b50610972610b1f366004614638565b611d67565b348015610b3057600080fd5b5061039e60195481565b60408051600481526024810182526020810180516001600160e01b0316630d0e30db60e41b1790529051600091829173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2918591610b8b9190614aa4565b60006040518083038185875af1925050503d8060008114610bc8576040519150601f19603f3d011682016040523d82523d6000602084013e610bcd565b606091505b5090949350505050565b600063a86517a160e01b6001600160e01b031983161480610bfc5750610bfc82611f77565b92915050565b60038054610c0f90614ac0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3b90614ac0565b8015610c885780601f10610c5d57610100808354040283529160200191610c88565b820191906000526020600020905b815481529060010190602001808311610c6b57829003601f168201915b505050505081565b60006006548211158015610ca45750600082115b15610d72576000828152600b602052604090205482906001600160a01b0316338114801590610cf757506001600160a01b0381166000908152600a6020908152604080832033845290915290205460ff16155b15610d14576040516282b42960e81b815260040160405180910390fd5b60008281526009602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a45050610df6565b6001600160a01b038316610d9957604051635461585f60e01b815260040160405180910390fd5b3360008181526008602090815260408083206001600160a01b03881680855290835292819020869055518581528593917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b50600192915050565b6000610e246001546001600160801b03808216600160801b9092048116919091031690565b905090565b610e31611fad565b30600090815260076020526040902054600390610e4f906002614b0a565b610e599190614b37565b811115610ea35760405162461bcd60e51b8152602060048201526013602482015272616d6f756e7420697320746f6f206c6172676560681b60448201526064015b60405180910390fd5b6000610eae82611fda565b90508015610eda5730600090815260076020526040902054610eda90610ed5600284614b37565b611ff6565b5050565b60006001600160a01b038416610f0757604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b038316610f2e57604051634e46966960e11b815260040160405180910390fd5b600654821161102b576000828152600b602052604090205482906001600160a01b03868116911614610f72576040516282b42960e81b815260040160405180910390fd5b336001600160a01b03861614801590610faf57506001600160a01b0385166000908152600a6020908152604080832033845290915290205460ff16155b8015610fd257506000818152600960205260409020546001600160a01b03163314155b15610fef576040516282b42960e81b815260040160405180910390fd5b61101a85857f0000000000000000000000000000000000000000000000056bc75e2d63100000612087565b611025858583612143565b5061109d565b6001600160a01b038416600090815260086020908152604080832033845290915290205482906000198114611089576110648282614b4b565b6001600160a01b03871660009081526008602090815260408083203384529091529020555b6110948686846114e9565b925050506110a1565b5060015b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000146146110d957610e246121db565b507f4cb0274b43fdd81f63b1cb06db334c270a7f1af77036aff621cb6e8af21c099b90565b611109838383610ede565b506001600160a01b0382163b158015906111b65750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a99190614b5e565b6001600160e01b03191614155b156111d457604051633da6393160e01b815260040160405180910390fd5b505050565b6111e1611fad565b6016546001600160801b0390811690821611156112395760405162461bcd60e51b81526020600482015260166024820152756c697175696469747920697320746f6f206c6172676560501b6044820152606401610e9a565b6001600160801b038116156112515761125181612275565b6014546011546111d49190630100000090046001600160a01b03166122e6565b6060600f805480602002602001604051908101604052809291908181526020016000905b828210156113415783829060005260206000200180546112b490614ac0565b80601f01602080910402602001604051908101604052809291908181526020018280546112e090614ac0565b801561132d5780601f106113025761010080835404028352916020019161132d565b820191906000526020600020905b81548152906001019060200180831161131057829003601f168201915b505050505081526020019060010190611295565b50505050905090565b6000818152600b60205260408120546001600160a01b03169050600654821180611372575081155b8061138457506001600160a01b038116155b156113a25760405163c5723b5160e01b815260040160405180910390fd5b919050565b601c8054610c0f90614ac0565b6113bc611fad565b6113c66000612401565b565b6113d0611fad565b73c36442b4a4522e871399cd717abdd847ab11fe8873e592427a0aece92de3edee1f18e0157c05861564341561140b5761140934610b3a565b505b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2301061143b576c39bc2ab9629fb8000000000000611449565b6b046f1de7bc353a00000000005b6cffffffffffffffffffffffffff169050600061146582612451565b9050600061147161253e565b9050818110156114bc5760405162461bcd60e51b81526020600482015260166024820152757765746820616d6f756e7420697320746f6f206c6f7760501b6044820152606401610e9a565b6114e283610bb873c02aaa39b223fe8d0a0e5c4f27ead9083c756cc285603c8a8a612607565b5050505050565b60008060006114f9868686612aef565b91509150801561156a5761150f86600086612c51565b5061151a8585612fe5565b836005600082825461152c9190614b4b565b90915550506040518481527f77dd5e627769f9468b3e9ef3f0d14fdf2cca856af36dd6aa591989bdf3957685906020015b60405180910390a16115e5565b81156115d857611584868661157f8588614b4b565b612c51565b50611590863084612c51565b5081601960008282546115a39190614b7b565b90915550506040518281527fed9d4923888165f7fbf184c0010cb4a535efc8f5ac2b5ec687473e90399715529060200161155d565b6115e3868686612c51565b505b50600195945050505050565b6115f9611fad565b601d6020527f702cd3c0838130d667938bb2b71b963651fdfee2c3f214726373ed0ce96d20198054600160ff1991821681179092557f6bee7e1db5ac34d873578a26025b34efebb8b360efb97ecffdd8274ce6bcaba28054821683179055735b93a825829f4b7b5177c259edc22b63d6e4e3806000527f4f1a6c0e8779a034cf6fcf5f7fb07fc8951643aa66e5a8eee0ceda369b17f0958054821683179055601e80549091169091179055565b60048054610c0f90614ac0565b6001600160a01b0382166116da5760405163ccea9e6f60e01b815260040160405180910390fd5b336000818152600a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60006001600160a01b03831661176f57604051634e46966960e11b815260040160405180910390fd5b6110a13384846114e9565b611782611fad565b6001600160a01b03919091166000908152601d60205260409020805460ff1916911515919091179055565b6001600160a01b0381166000908152600c602090815260409182902080548351818402810184019094528084526060939283018282801561180d57602002820191906000526020600020905b8154815260200190600101908083116117f9575b50505050509050919050565b611824858585610ede565b506001600160a01b0384163b158015906118bf5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061186f9033908a90899089908990600401614b8e565b6020604051808303816000875af115801561188e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b29190614b5e565b6001600160e01b03191614155b156114e257604051633da6393160e01b815260040160405180910390fd5b60606000826040516020016118f491815260200190565b6040516020818303038152906040528051906020012060f81c905060608060408360ff16116119605760405180604001604052806005815260200164302e706e6760d81b81525091506040518060400160405280600381526020016214995960ea1b8152509050611a41565b60808360ff16116119af5760405180604001604052806005815260200164312e706e6760d81b815250915060405180604001604052806004815260200163426c756560e01b8152509050611a41565b60c08360ff16116119ff5760405180604001604052806005815260200164322e706e6760d81b81525091506040518060400160405280600581526020016423b932b2b760d91b8152509050611a41565b60405180604001604052806005815260200164332e706e6760d81b815250915060405180604001604052806006815260200165507572706c6560d01b81525090505b611a4a856131df565b611a556010546131df565b601c8484604051602001611a6d959493929190614c52565b6040516020818303038152906040529350505050919050565b42841015611aa7576040516305787bdf60e01b815260040160405180910390fd5b6006548511158015611ab95750600085115b15611ad7576040516303e7c1bd60e31b815260040160405180910390fd5b6001600160a01b038616611afe57604051635461585f60e01b815260040160405180910390fd5b60006001611b0a6110a8565b6001600160a01b038a81166000818152600e602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611c16573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580611c4b5750876001600160a01b0316816001600160a01b031614155b15611c6957604051632057875960e21b815260040160405180910390fd5b6001600160a01b0390811660009081526008602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b611cdb81613272565b8051611cee90600f90602084019061449a565b507f9538911740e5519a40db77fb5f637de0d56cdd804318d81ae270cc24fbd8479e81604051611d1e91906146d7565b60405180910390a150565b611d31611fad565b6001600160a01b038116611d5b57604051631e4fbdf760e01b815260006004820152602401610e9a565b611d6481612401565b50565b60606000611d8a846001600160a01b031660009081526007602052604090205490565b6001600160a01b0385166000908152600d602052604090205490915060ff16611f70576000611dd97f0000000000000000000000000000000000000000000000056bc75e2d6310000085614b37565b90506000611e077f0000000000000000000000000000000000000000000000056bc75e2d6310000086614e02565b9050611e337f0000000000000000000000000000000000000000000000056bc75e2d6310000084614b37565b7f0000000000000000000000000000000000000000000000056bc75e2d63100000611e5e8386614b4b565b611e689190614b37565b1015611e7c5781611e7881614e16565b9250505b8115611f6d578167ffffffffffffffff811115611e9b57611e9b614911565b604051908082528060200260200182016040528015611ec4578160200160208202803683370190505b50935060005b82811015611f6b576000611edf826001614b7b565b6001600160a01b0389166000908152600c6020526040902054611f029190614b4b565b6001600160a01b0389166000908152600c6020526040902080549192509082908110611f3057611f30614e2f565b9060005260206000200154868381518110611f4d57611f4d614e2f565b60209081029190910101525080611f6381614e16565b915050611eca565b505b50505b5092915050565b60006001600160e01b0319821663219d65bb60e01b1480610bfc57506001600160e01b031982166301ffc9a760e01b1492915050565b6000546001600160a01b031633146113c65760405163118cdaa760e01b8152336004820152602401610e9a565b601354600090610bfc9030906001600160a01b0316818561327a565b60135430906001600160a01b031683838284111561201357919291905b600061202560126002015484846133d4565b909450925090506001600160801b0381161561207e57601680548291906000906120599084906001600160801b0316614e45565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b50505050505050565b6001600160a01b0383166120b25780600560008282546120a79190614b7b565b909155506120e09050565b6001600160a01b038316600090815260076020526040812080548392906120da908490614b4b565b90915550505b6001600160a01b03808316600081815260076020526040908190208054850190555190918516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906121369085815260200190565b60405180910390a3505050565b601e5460ff1615156001036121d0576000546001600160a01b031633148061217c5750601154630100000090046001600160a01b031633145b806121965750336000908152601d602052604090205460ff165b6121d05760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b6044820152606401610e9a565b6111d48383836134fa565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600360405161220d9190614e65565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600080612287601260020154846136d2565b91509150600082118061229a5750600081115b156111d457601680548491906000906122bd9084906001600160801b0316614e71565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b604080516080810182528381526001600160a01b03838116602083019081526001600160801b0383850181815260608501828152601a549651602481018a905293518516604485015290518216606484015251166084820152600093849392849283929091169063fc6f78659060a4015b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516123909190614aa4565b6000604051808303816000865af19150503d80600081146123cd576040519150601f19603f3d011682016040523d82523d6000602084013e6123d2565b606091505b509150915081156123f757808060200190518101906123f19190614e91565b90955093505b5050509250929050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b306000908152600760205260408120546001600160801b036001600160a01b038416116124d557600061248d6001600160a01b03851680614b0a565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc230106124be576124b9600160c01b8383613755565b6124cd565b6124cd8183600160c01b613755565b925050612538565b60006124f46001600160a01b0385168068010000000000000000613755565b905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2301061252557612520600160801b8383613755565b612534565b6125348183600160801b613755565b9250505b50919050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17905290516000918291829173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2916125a09190614aa4565b600060405180830381855afa9150503d80600081146125db576040519150601f19603f3d011682016040523d82523d6000602084013e6125e0565b606091505b5091509150811561260257808060200190518101906125ff9190614eb5565b92505b505090565b61260f611fad565b601154600160b81b900460ff161561265b5760405162461bcd60e51b815260206004820152600f60248201526e1a185cc81a5b9a5d1a585b1a5e9959608a1b6044820152606401610e9a565b601a80546001600160a01b03199081166001600160a01b0385811691909117909255601b80548216848416179055601380548884166001600160b81b03199091168117600160a01b62ffffff8c16021790915560158054909216928a1692909217905530600081815260076020526040902054909187919087908411156126e157919291905b6126ed84600019613803565b506126fa83600019613803565b50600061270985858d8f6139bc565b6017805462ffffff90931663010000000265ffffff0000001990931692909217909155601280546001600160a01b039093166001600160a01b03199093168317905591501580159061275f57508060020b600014155b6127a45760405162461bcd60e51b81526020600482015260166024820152751a5b9a5d1a585b1a5e99481c1bdbdb0819985a5b195960521b6044820152606401610e9a565b6017805462ffffff198116630100000090910462ffffff161790556013546001600160a01b03163010156128ad5760175481906127e590829060020b614ece565b6127ef9190614f08565b6015805462ffffff92909216600160a01b0262ffffff60a01b19909216919091179055601754600060029190910b12156128625760158054829190601490612842908490600160a01b900460020b614f28565b92506101000a81548162ffffff021916908360020b62ffffff1602179055505b8080612871620d89e719614f4d565b61287b9190614ece565b6128859190614f08565b6015805462ffffff92909216600160b81b0262ffffff60b81b1990921691909117905561297a565b60175481906128c090829060020b614ece565b6128ca9190614f08565b6015805462ffffff92909216600160b81b0262ffffff60b81b19909216919091179055601754600060029190910b131561293d576015805482919060179061291d908490600160b81b900460020b614f6f565b92506101000a81548162ffffff021916908360020b62ffffff1602179055505b8061294c81620d89e719614ece565b6129569190614f08565b6015805462ffffff92909216600160a01b0262ffffff60a01b199092169190911790555b61ffff8816156129ee5760125460009061299d906001600160a01b03168a613c39565b9050806129ec5760405162461bcd60e51b815260206004820152601e60248201527f696e697469616c697a65206f62736572766174696f6e73206661696c656400006044820152606401610e9a565b505b601554612a1b90869086908e9087908790600160a01b8104600290810b91600160b81b9004900b30613cde565b5050601680546001600160801b0319166001600160801b03929092169190911790556014819055600003612a915760405162461bcd60e51b815260206004820152601b60248201527f696e697469616c697a65206c6971756964697479206661696c656400000000006044820152606401610e9a565b426018556011805460ff60b81b1916600160b81b1790556040517fc6cb858e754b4efdad8980cee030a8e8725c4e6e690d9b77733a89b5dd5601a190612ad990601290614f94565b60405180910390a1505050505050505050505050565b6011546000908190630100000090046001600160a01b0316331480612b1e5750601b546001600160a01b031633145b80612b3157506001600160a01b03851630145b80612b4957506012546001600160a01b038581169116145b15612b5957506000905080612c49565b612b61613e4b565b6017805462ffffff9290921663010000000265ffffff00000019909216919091179055612b986013546001600160a01b0316301090565b15612bfe57601754600281810b6301000000909204900b1315612bdd57601154620f424090612bcc9062ffffff1685614b0a565b612bd69190614b37565b9150612c49565b601754600281810b6301000000909204900b1215612bf9575060015b612c49565b601754600281810b6301000000909204900b1215612c2d57601154620f424090612bcc9062ffffff1685614b0a565b601754600281810b6301000000909204900b1315612c49575060015b935093915050565b6001600160a01b03838116600090815260076020526040808220549285168252812054909190612c82868686612087565b6001600160a01b038087166000908152600d602052604080822054928816825290205460ff9182169116818015612cb65750805b612fd7578115612d69576000612cec7f0000000000000000000000000000000000000000000000056bc75e2d6310000085614b37565b6001600160a01b038916600090815260076020526040902054612d30907f0000000000000000000000000000000000000000000000056bc75e2d6310000090614b37565b612d3a9190614b4b565b905060005b81811015612d6257612d5089614142565b80612d5a81614e16565b915050612d3f565b5050612fd7565b8015612e0f576001600160a01b038816600090815260076020526040812054612db3907f0000000000000000000000000000000000000000000000056bc75e2d6310000090614b37565b612ddd7f0000000000000000000000000000000000000000000000056bc75e2d6310000087614b37565b612de79190614b4b565b905060005b81811015612d6257612dfd8a6141fb565b80612e0781614e16565b915050612dec565b6000612e3b7f0000000000000000000000000000000000000000000000056bc75e2d6310000088614b37565b905060005b81811015612ec9576001600160a01b038a166000908152600c6020526040812054612e6d90600190614b4b565b6001600160a01b038c166000908152600c602052604081208054929350909183908110612e9c57612e9c614e2f565b90600052602060002001549050612eb48c8c83612143565b50508080612ec190614e16565b915050612e40565b506000612ef67f0000000000000000000000000000000000000000000000056bc75e2d6310000089614e02565b9050612f227f0000000000000000000000000000000000000000000000056bc75e2d6310000087614b37565b7f0000000000000000000000000000000000000000000000056bc75e2d63100000612f4d8389614b4b565b612f579190614b37565b1015612f6657612f668a6141fb565b612f907f0000000000000000000000000000000000000000000000056bc75e2d6310000086614b37565b7f0000000000000000000000000000000000000000000000056bc75e2d63100000612fbb8388614b7b565b612fc59190614b37565b1115612fd457612fd489614142565b50505b506001979650505050505050565b6001600160a01b03821661300c57604051636edaef2f60e11b815260040160405180910390fd5b601354604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b179052905160009283926001600160a01b03909116916130659190614aa4565b600060405180830381855afa9150503d80600081146130a0576040519150601f19603f3d011682016040523d82523d6000602084013e6130a5565b606091505b5091509150816130b55750505050565b6000818060200190518101906130cb9190614eb5565b9050600060055482866130de9190614b0a565b6130e89190614b37565b601354604080516001600160a01b038a81166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151939450600093919092169161314891614aa4565b6000604051808303816000865af19150503d8060008114613185576040519150601f19603f3d011682016040523d82523d6000602084013e61318a565b606091505b50509050801561207e57604080516001600160a01b0389168152602081018490527f289360176646a5f99cb4b6300628426dca46b723f40db3c04449d6ed1745a0e7910160405180910390a150505050505050565b606060006131ec8361427c565b600101905060008167ffffffffffffffff81111561320c5761320c614911565b6040519080825280601f01601f191660200182016040528015613236576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461324057509392505050565b611d64611fad565b60408051610100810182526001600160a01b03868116808352868216602080850191825260135462ffffff600160a01b909104811686880190815289861660608801908152426080890190815260a089018b8152600060c08b0181815260e08c01828152601b548e51602481019c909c5299518c1660448c0152955190961660648a0152925189166084890152905160a48801525160c4870152915160e48601525185166101048086019190915287518086039091018152610124909401875290830180516001600160e01b031663414bf38960e01b17905294518593849392169161336591614aa4565b6000604051808303816000865af19150503d80600081146133a2576040519150601f19603f3d011682016040523d82523d6000602084013e6133a7565b606091505b509150915081156133c957808060200190518101906133c69190614eb5565b93505b505050949350505050565b6040805160c0810182528481526020808201858152828401858152600060608501818152608086018281524260a08801908152601a548951602481018e90529651604488015294516064870152915160848601525160a48501525160c4808501919091528651808503909101815260e4909301865292820180516001600160e01b031663219f5d1760e01b17905293519193849384939092849283926001600160a01b039091169161348591614aa4565b6000604051808303816000865af19150503d80600081146134c2576040519150601f19603f3d011682016040523d82523d6000602084013e6134c7565b606091505b509150915081156134ee57808060200190518101906134e69190615012565b919750955093505b50505093509350939050565b6001600160a01b0383161561360557600081815260096020908152604080832080546001600160a01b03191690556001600160a01b0386168352600c9091528120805461354990600190614b4b565b8154811061355957613559614e2f565b906000526020600020015490508181146135c6576000828152600b602052604081205460a01c6001600160a01b0386166000908152600c6020526040902080549192508391839081106135ae576135ae614e2f565b6000918252602090912001556135c48282614354565b505b6001600160a01b0384166000908152600c602052604090208054806135ed576135ed615049565b60019003818190600052602060002001600090559055505b6001600160a01b0382161561367c576000818152600b6020908152604080832080546001600160a01b0319166001600160a01b038716908101909155808452600c835290832080546001818101835582865293852001859055925290546136779183916136729190614b4b565b614354565b61368c565b6000818152600b60205260408120555b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6040805160a0810182528381526001600160801b03838116602083019081526000838501818152606085018281524260808701908152601a549751602481018b90529451909516604485015290516064840152516084830152915160a48201529092839291839182916001600160a01b0390911690630c49ccbe9060c401612357565b600080806000198587098587029250828110838203039150508060000361378e576000841161378357600080fd5b5082900490506110a1565b80841161379a57600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008160000361381557506001610bfc565b306001600160a01b038416036138645750306000908152600860209081526040808320601a546001600160a01b0390811685529252808320849055601b54909116825290208190556001610bfc565b601a54604080516001600160a01b039283166024820152604480820186905282518083039091018152606490910182526020810180516001600160e01b031663095ea7b360e01b17905290516000928616916138bf91614aa4565b6000604051808303816000865af19150503d80600081146138fc576040519150601f19603f3d011682016040523d82523d6000602084013e613901565b606091505b5050601b54604080516001600160a01b039283166024820152604480820188905282518083039091018152606490910182526020810180516001600160e01b031663095ea7b360e01b1790529051929350600092918716916139639190614aa4565b6000604051808303816000865af19150503d80600081146139a0576040519150601f19603f3d011682016040523d82523d6000602084013e6139a5565b606091505b505090508180156139b35750805b95945050505050565b601a54604080516001600160a01b038781166024830152868116604483015262ffffff861660648301528481166084808401919091528351808403909101815260a490920183526020820180516001600160e01b03166309f56ab160e11b179052915160009384938493849384939290921691613a399190614aa4565b6000604051808303816000865af19150503d8060008114613a76576040519150601f19603f3d011682016040523d82523d6000602084013e613a7b565b606091505b509150915081613a975760008060009450945094505050613c2f565b80806020019051810190613aab919061505f565b60408051600481526024810182526020810180516001600160e01b0316633850c7bd60e01b179052905191965060009182916001600160a01b03891691613af29190614aa4565b600060405180830381855afa9150503d8060008114613b2d576040519150601f19603f3d011682016040523d82523d6000602084013e613b32565b606091505b509150915081613b5057600080600096509650965050505050613c2f565b80806020019051810190613b6491906150a0565b505060408051600481526024810182526020810180516001600160e01b03166334324e9f60e21b1790529051949b506000955085946001600160a01b038e169450613bb29350909150614aa4565b600060405180830381855afa9150503d8060008114613bed576040519150601f19603f3d011682016040523d82523d6000602084013e613bf2565b606091505b509150915081613c12576000806000985098509850505050505050613c2f565b80806020019051810190613c26919061512f565b96505050505050505b9450945094915050565b6040805161ffff831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166332148f6760e01b179052905160009182916001600160a01b03861691613c9191614aa4565b6000604051808303816000865af19150503d8060008114613cce576040519150601f19603f3d011682016040523d82523d6000602084013e613cd3565b606091505b509095945050505050565b60008060008060006040518061016001604052808e6001600160a01b031681526020018d6001600160a01b031681526020018c62ffffff1681526020018960020b81526020018860020b81526020018b81526020018a81526020016000815260200160008152602001876001600160a01b03168152602001428152509050600080601a60009054906101000a90046001600160a01b03166001600160a01b0316638831645684604051602401613d94919061514a565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051613dcd9190614aa4565b6000604051808303816000865af19150503d8060008114613e0a576040519150601f19603f3d011682016040523d82523d6000602084013e613e0f565b606091505b50915091508115613e395780806020019051810190613e2e919061520e565b929950909750955093505b50505098509850985098945050505050565b601154600090600160b81b900460ff16613e69575060175460020b90565b60125460408051600481526024810182526020810180516001600160e01b0316633850c7bd60e01b179052905160009283926001600160a01b0390911691613eb19190614aa4565b600060405180830381855afa9150503d8060008114613eec576040519150601f19603f3d011682016040523d82523d6000602084013e613ef1565b606091505b509150915081613f0857505060175460020b919050565b600080600083806020019051810190613f2191906150a0565b5050601854939750919550935061070892508291613f40915042614b4b565b63ffffffff161015613f5757509195945050505050565b6040805160028082526060820183526000926020830190803683370190505090508181600081518110613f8c57613f8c614e2f565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110613fbb57613fbb614e2f565b63ffffffff9092166020928302919091019091015260125460405160009182916001600160a01b039091169063883bdbfd90613ffb90869060240161524c565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516140349190614aa4565b600060405180830381855afa9150503d806000811461406f576040519150601f19603f3d011682016040523d82523d6000602084013e614074565b606091505b50915091508161408c57509498975050505050505050565b6000818060200190518101906140a291906152f9565b5090506000816000815181106140ba576140ba614e2f565b6020026020010151826001815181106140d5576140d5614e2f565b60200260200101516140e791906153c5565b90506140f963ffffffff8716826153f2565b985060008160060b12801561411f575061411963ffffffff871682615427565b60060b15155b15614132578861412e81615449565b9950505b50969a9950505050505050505050565b6001600160a01b03811661416957604051634e46966960e11b815260040160405180910390fd5b6000614189600154600160801b81046001600160801b0390811691161490565b61419e5761419760016143c0565b90506141b9565b600680549060006141ae83614e16565b919050555060065490505b6000818152600b60205260409020546001600160a01b031680156141f05760405163119b4fd360e11b815260040160405180910390fd5b6111d4818484612143565b6001600160a01b03811661422257604051636edaef2f60e11b815260040160405180910390fd5b6001600160a01b0381166000908152600c60205260408120805461424890600190614b4b565b8154811061425857614258614e2f565b9060005260206000200154905061427182600083612143565b610eda600182614430565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106142bb5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106142e7576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061430557662386f26fc10000830492506010015b6305f5e100831061431d576305f5e100830492506008015b612710831061433157612710830492506004015b60648310614343576064830492506002015b600a8310610bfc5760010192915050565b6000828152600b60205260409020546bffffffffffffffffffffffff82111561439057604051633f2cd0e360e21b815260040160405180910390fd5b6000928352600b60205260409092206001600160a01b039290921660a09190911b6001600160a01b031916019055565b80546000906001600160801b03600160801b82048116911681036143f7576040516375e52f4f60e01b815260040160405180910390fd5b600019016001600160801b039081166000818152600185016020526040812080549190558454909216600160801b909102179092555090565b81546001600160801b038082166000190191600160801b900481169082160361446c57604051638acb5f2760e01b815260040160405180910390fd5b6001600160801b0316600081815260018401602052604090209190915581546001600160801b031916179055565b8280548282559060005260206000209081019282156144e0579160200282015b828111156144e057825182906144d090826154ba565b50916020019190600101906144ba565b506144ec9291506144f0565b5090565b808211156144ec576000614504828261450d565b506001016144f0565b50805461451990614ac0565b6000825580601f10614529575050565b601f016020900490600052602060002090810190611d6491905b808211156144ec5760008155600101614543565b6001600160e01b031981168114611d6457600080fd5b60006020828403121561457f57600080fd5b81356110a181614557565b6001600160a01b0381168114611d6457600080fd5b6000602082840312156145b157600080fd5b81356110a18161458a565b60005b838110156145d75781810151838201526020016145bf565b50506000910152565b600081518084526145f88160208601602086016145bc565b601f01601f19169290920160200192915050565b6020815260006110a160208301846145e0565b60006020828403121561463157600080fd5b5035919050565b6000806040838503121561464b57600080fd5b82356146568161458a565b946020939093013593505050565b60008060006060848603121561467957600080fd5b83356146848161458a565b925060208401356146948161458a565b929592945050506040919091013590565b6001600160801b0381168114611d6457600080fd5b6000602082840312156146cc57600080fd5b81356110a1816146a5565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561472c57603f1988860301845261471a8583516145e0565b945092850192908501906001016146fe565b5092979650505050505050565b8015158114611d6457600080fd5b6000806040838503121561475a57600080fd5b82356147658161458a565b9150602083013561477581614739565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156147b85783518352928401929184019160010161479c565b50909695505050505050565b6000806000806000608086880312156147dc57600080fd5b85356147e78161458a565b945060208601356147f78161458a565b935060408601359250606086013567ffffffffffffffff8082111561481b57600080fd5b818801915088601f83011261482f57600080fd5b81358181111561483e57600080fd5b89602082850101111561485057600080fd5b9699959850939650602001949392505050565b60ff81168114611d6457600080fd5b600080600080600080600060e0888a03121561488d57600080fd5b87356148988161458a565b965060208801356148a88161458a565b9550604088013594506060880135935060808801356148c681614863565b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156148f657600080fd5b82356149018161458a565b915060208301356147758161458a565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561495057614950614911565b604052919050565b600067ffffffffffffffff82111561497257614972614911565b5060051b60200190565b6000602080838503121561498f57600080fd5b823567ffffffffffffffff808211156149a757600080fd5b8185019150601f86818401126149bc57600080fd5b82356149cf6149ca82614958565b614927565b81815260059190911b840185019085810190898311156149ee57600080fd5b8686015b83811015614a7a57803586811115614a0a5760008081fd5b8701603f81018c13614a1c5760008081fd5b88810135604088821115614a3257614a32614911565b614a43828901601f19168c01614927565b8281528e82848601011115614a585760008081fd5b828285018d83013760009281018c0192909252508452509187019187016149f2565b509998505050505050505050565b60008151614a9a8185602086016145bc565b9290920192915050565b60008251614ab68184602087016145bc565b9190910192915050565b600181811c90821680614ad457607f821691505b60208210810361253857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610bfc57610bfc614af4565b634e487b7160e01b600052601260045260246000fd5b600082614b4657614b46614b21565b500490565b81810381811115610bfc57610bfc614af4565b600060208284031215614b7057600080fd5b81516110a181614557565b80820180821115610bfc57610bfc614af4565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b60008154614bef81614ac0565b60018281168015614c075760018114614c1c57611f6b565b60ff1984168752821515830287019450611f6b565b8560005260208060002060005b85811015614c425781548a820152908401908201614c29565b5050509590910195945050505050565b747b226e616d65223a202257484f343034204e46542360581b81528551600090614c83816015850160208b016145bc565b7f222c226465736372697074696f6e223a224120636f6c6c656374696f6e206f66601591840191820152600160fd1b60358201528651614cca816036840160208b016145bc565b7f20706f7473206f66206c6971756964697479207468617420746f6b656e697a65603692909101918201527f7320646563656e7472616c697a656420726573657276652063757272656e637960568201527f206964656120666f722074686520495135302c20234552433333332e0000000060768201527f222c2265787465726e616c5f75726c223a2268747470733a2f2f77686f34303460928201526f173bba331791161134b6b0b3b2911d1160811b60b2820152614df6614de6614de0614d9f614d9960c286018b614be2565b89614a88565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a224381526e37b637b91116113b30b63ab2911d1160891b6020820152602f0190565b86614a88565b63227d5d7d60e01b815260040190565b98975050505050505050565b600082614e1157614e11614b21565b500690565b600060018201614e2857614e28614af4565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6001600160801b03818116838216019080821115611f7057611f70614af4565b60006110a18284614be2565b6001600160801b03828116828216039080821115611f7057611f70614af4565b60008060408385031215614ea457600080fd5b505080516020909101519092909150565b600060208284031215614ec757600080fd5b5051919050565b60008160020b8360020b80614ee557614ee5614b21565b627fffff19821460001982141615614eff57614eff614af4565b90059392505050565b60008260020b8260020b028060020b9150808214611f7057611f70614af4565b600282810b9082900b03627fffff198112627fffff82131715610bfc57610bfc614af4565b60008160020b627fffff198103614f6657614f66614af4565b60000392915050565b600281810b9083900b01627fffff8113627fffff1982121715610bfc57610bfc614af4565b81546001600160a01b03168152610100810160018301546001600160a01b03808216602085015262ffffff60a092831c16604085015260028086015460608601526003860154918216608086015281831c810b9285019290925260b81c900b60c083015260048301546001600160801b031660e08301819052611f70565b60008060006060848603121561502757600080fd5b8351615032816146a5565b602085015160409095015190969495509392505050565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561507157600080fd5b81516110a18161458a565b8051600281900b81146113a257600080fd5b805161ffff811681146113a257600080fd5b600080600080600080600060e0888a0312156150bb57600080fd5b87516150c68161458a565b96506150d46020890161507c565b95506150e26040890161508e565b94506150f06060890161508e565b93506150fe6080890161508e565b925060a088015161510e81614863565b60c089015190925061511f81614739565b8091505092959891949750929550565b60006020828403121561514157600080fd5b6110a18261507c565b81516001600160a01b031681526101608101602083015161517660208401826001600160a01b03169052565b50604083015161518d604084018262ffffff169052565b5060608301516151a2606084018260020b9052565b5060808301516151b7608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516151fd828501826001600160a01b03169052565b505061014092830151919092015290565b6000806000806080858703121561522457600080fd5b845193506020850151615236816146a5565b6040860151606090960151949790965092505050565b6020808252825182820181905260009190848201906040850190845b818110156147b857835163ffffffff1683529284019291840191600101615268565b600082601f83011261529b57600080fd5b815160206152ab6149ca83614958565b82815260059290921b840181019181810190868411156152ca57600080fd5b8286015b848110156152ee5780516152e18161458a565b83529183019183016152ce565b509695505050505050565b6000806040838503121561530c57600080fd5b825167ffffffffffffffff8082111561532457600080fd5b818501915085601f83011261533857600080fd5b815160206153486149ca83614958565b82815260059290921b8401810191818101908984111561536757600080fd5b948201945b838610156153955785518060060b81146153865760008081fd5b8252948201949082019061536c565b918801519196509093505050808211156153ae57600080fd5b506153bb8582860161528a565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff82131715610bfc57610bfc614af4565b60008160060b8360060b8061540957615409614b21565b667fffffffffffff19821460001982141615614eff57614eff614af4565b60008260060b8061543a5761543a614b21565b808360060b0791505092915050565b60008160020b627fffff19810361546257615462614af4565b6000190192915050565b601f8211156111d457600081815260208120601f850160051c810160208610156154935750805b601f850160051c820191505b818110156154b25782815560010161549f565b505050505050565b815167ffffffffffffffff8111156154d4576154d4614911565b6154e8816154e28454614ac0565b8461546c565b602080601f83116001811461551d57600084156155055750858301515b600019600386901b1c1916600185901b1785556154b2565b600085815260208120601f198616915b8281101561554c5788860151825594840194600190910190840161552d565b508582101561556a5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220bbae53dc555fe3b383ecbd466605053207fb1aa5f5075b539d8dda65c4a3137964736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cdf74bff7c62c72775a2cdb83dbc0a1d4866703a000000000000000000000000a6afd4d1226169db19432cf6f26f66a219b9b159
-----Decoded View---------------
Arg [0] : initialOwner_ (address): 0xCdF74BFF7C62c72775A2cdb83dBc0A1d4866703A
Arg [1] : initialMintRecipient_ (address): 0xA6AFd4D1226169db19432cf6F26f66a219b9b159
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000cdf74bff7c62c72775a2cdb83dbc0a1d4866703a
Arg [1] : 000000000000000000000000a6afd4d1226169db19432cf6f26f66a219b9b159
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $3,327.61 | 0.0808 | $268.87 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.