ERC-1155
Overview
Max Total Supply
8,527
Holders
1,421
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MMCNFTV2
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; contract MMCNFTV2 is ERC1155, Ownable, ERC1155Burnable, ERC1155Supply, IERC1155Receiver, ReentrancyGuard { using SafeERC20 for IERC20; using Strings for uint256; IUniswapV2Router02 public uniswapV2Router; IUniswapV2Factory public uniswapV2Factory; // Token information structure struct TokenInfo { uint256 price; uint8 tokenType; uint8 status; string uri; } // Mapping of Token ID to TokenInfo mapping(uint256 => TokenInfo) public tokenInfo; // Pool percentage, default 50% uint256 public poolPercentage = 50; // Withdrawable USDT balance uint256 public withdrawableUSDT; // Selling status uint8 public saleStatus; // Interface for USDT and MMC tokens IERC20 public usdtToken; IERC20 public mmcToken; // Constructor to initialize Uniswap router, factory and token address constructor(address _router, address _factory, address _usdtToken, address _mmcToken) ERC1155("") Ownable(msg.sender) { uniswapV2Router = IUniswapV2Router02(_router); uniswapV2Factory = IUniswapV2Factory(_factory); usdtToken = IERC20(_usdtToken); mmcToken = IERC20(_mmcToken); } // Add liquidity function uniAddLiquidity( address _tokenA, address _tokenB, uint256 _amountA, uint256 _amountB, uint256 _minAmountA, uint256 _minAmountB ) external onlyOwner { // Check if _tokenA is USDT and ensure not to use withdrawable USDT uint256 usdtBalance = usdtToken.balanceOf(address(this)) - withdrawableUSDT; if (_tokenA == address(usdtToken)) { require(_amountA <= usdtBalance, "Invalid request"); } // Check if _tokenB is USDT and ensure not to use withdrawable USDT if (_tokenB == address(usdtToken)) { require(_amountB <= usdtBalance, "Invalid request"); } // Safe increase allowance IERC20(_tokenA).safeIncreaseAllowance(address(uniswapV2Router), _amountA); IERC20(_tokenB).safeIncreaseAllowance(address(uniswapV2Router), _amountB); // Add liquidity uniswapV2Router.addLiquidity( _tokenA, _tokenB, _amountA, _amountB, _minAmountA, _minAmountB, address(this), block.timestamp + 15 minutes ); } // Remove Liquidity function uniRemoveLiquidity( address _tokenA, address _tokenB, uint256 _liquidity, uint256 _minAmountA, uint256 _minAmountB ) external onlyOwner { address pairAddress = uniswapV2Factory.getPair(_tokenA, _tokenB); require(pairAddress != address(0), "Invalid request"); IERC20(pairAddress).safeIncreaseAllowance(address(uniswapV2Router), _liquidity); // Remove Liquidity uniswapV2Router.removeLiquidity( _tokenA, _tokenB, _liquidity, _minAmountA, _minAmountB, address(this), block.timestamp + 15 minutes ); } // Exchange USDT <=> MMC function swapExchangeToken( uint amountIn, // The amount of USDT entered uint amountOutMin, // Minimum expected number of MMCs to receive uint8 swapType // 0: Buy 1: Sell ) external onlyOwner { address[] memory path = new address[](2); if (swapType == 0) { // USDT => MMC require(amountIn <= usdtToken.balanceOf(address(this)) - withdrawableUSDT, "Invalid request"); usdtToken.safeIncreaseAllowance(address(uniswapV2Router), amountIn); path[0] = address(usdtToken); path[1] = address(mmcToken); } else { // MMC => USDT mmcToken.safeIncreaseAllowance(address(uniswapV2Router), amountIn); path[0] = address(mmcToken); path[1] = address(usdtToken); } uniswapV2Router.swapExactTokensForTokens( amountIn, amountOutMin, path, address(this), block.timestamp + 15 minutes ); } // Set base URI function setBaseURI(string memory newUri) external onlyOwner { _setURI(newUri); } // Implementing the ERC1155 receiver interface function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external override returns(bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external override returns(bytes4) { return this.onERC1155BatchReceived.selector; } // Set Token URI in batches function setTokenURIBatch(uint256[] memory tokenIds, string[] memory newUris) external onlyOwner { require(tokenIds.length == newUris.length, "Invalid request"); for (uint256 i = 0; i < tokenIds.length; i++) { tokenInfo[tokenIds[i]].uri = newUris[i]; } } // Get Token URI function uri(uint256 tokenId) public view override returns (string memory) { string memory _uri = tokenInfo[tokenId].uri; string memory base = super.uri(tokenId); return bytes(_uri).length > 0 ? string(abi.encodePacked(base, _uri)) : string(abi.encodePacked(base, tokenId.toString())); } // Mint Tokens in batches and set URI, price, and type function mintBatchWithUri(address to, uint256[] memory ids, uint256[] memory amounts, string[] memory tokenUris, uint256[] memory prices, uint8[] memory types, uint8[] memory statuses, bytes memory data) public onlyOwner { require(ids.length == amounts.length && ids.length == tokenUris.length && ids.length == prices.length && ids.length == types.length && ids.length == statuses.length, "Invalid request"); for (uint256 i = 0; i < ids.length; i++) { require(!exists(ids[i]), "Token ID already exists"); // Check if the token already exists tokenInfo[ids[i]] = TokenInfo(prices[i], types[i], statuses[i], tokenUris[i]); } _mintBatch(to, ids, amounts, data); } // Secure transfer of tokens function safeTransfer(address to, uint256 tokenId, uint256 amount, bytes memory data) external onlyOwner { safeTransferFrom(msg.sender, to, tokenId, amount, data); } // Transfer token from contract function safeTransferContract(address to, uint256 tokenId, uint256 amount, bytes memory data) external onlyOwner { _safeTransferFrom(address(this), to, tokenId, amount, data); } // Destroy the NFT in the contract function destroyContractNFT(uint256 tokenId, uint256 amount) external onlyOwner { _burn(address(this), tokenId, amount); } // Update function, overrides the update function of the parent class function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal override(ERC1155, ERC1155Supply) { super._update(from, to, ids, values); } // Set the pool entry percentage, ranging from 50% to 100% function setPoolPercentage(uint256 _percentage) external onlyOwner { // 50 and 100 require(_percentage >= 50 && _percentage <= 100, "Invalid request"); poolPercentage = _percentage; } // Set sales status, global switch function setSaleStatus(uint8 _status) external onlyOwner { // 0 or 1 require(_status == 0 || _status == 1, "Invalid request"); saleStatus = _status; } // Set Token status function setTokenStatus(uint256 tokenId, uint8 status) external onlyOwner { require(status == 0 || status == 1, "Invalid request"); tokenInfo[tokenId].status = status; } // Purchase NFT tokenId: NFT ID quantity: NFT Number function buyNFT(address to, uint256 tokenId, uint256 quantity, bytes memory data) external nonReentrant { require(to != address(0) && quantity > 0 && saleStatus == 1 && tokenInfo[tokenId].status == 1, "Invalid request"); // Check if the contract has enough NFT balance uint256 totalAmount = tokenInfo[tokenId].price * quantity; require(balanceOf(address(this), tokenId) >= quantity && usdtToken.allowance(msg.sender, address(this)) >= totalAmount && usdtToken.balanceOf(msg.sender) >= totalAmount, "Invalid request"); usdtToken.safeTransferFrom(msg.sender, address(this), totalAmount); if (tokenInfo[tokenId].tokenType == 1) { withdrawableUSDT += totalAmount - ((totalAmount * poolPercentage) / 100); } _safeTransferFrom(address(this), to, tokenId, quantity, data); } // Withdraw your withdrawable USDT balance function withdrawUSDT(address to, uint256 amount) external onlyOwner nonReentrant { require(to != address(0) && amount <= withdrawableUSDT, "Invalid request"); // Update the state before transferring the tokens withdrawableUSDT -= amount; // Transfer USDT to the specified address usdtToken.safeTransfer(to, amount); } // Receive ERC20 tokens function receiveERC20(IERC20 _token, uint256 amount) external { _token.transferFrom(msg.sender, address(this), amount); } }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
pragma solidity >=0.5.0; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; }
// 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/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/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/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// 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 // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol) pragma solidity ^0.8.20; import {StorageSlot} from "./StorageSlot.sol"; import {Math} from "./math/Math.sol"; /** * @dev Collection of functions related to array types. */ library Arrays { using StorageSlot for bytes32; /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && unsafeAccess(array, low - 1).value == element) { return low - 1; } else { return low; } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getAddressSlot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getBytes32Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getUint256Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.20; import {IERC1155} from "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.20; import {ERC1155} from "../ERC1155.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. * * CAUTION: This extension should not be added in an upgrade to an already deployed contract. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 id => uint256) private _totalSupply; uint256 private _totalSupplyAll; /** * @dev Total value of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Total value of tokens. */ function totalSupply() public view virtual returns (uint256) { return _totalSupplyAll; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return totalSupply(id) > 0; } /** * @dev See {ERC1155-_update}. */ function _update( address from, address to, uint256[] memory ids, uint256[] memory values ) internal virtual override { super._update(from, to, ids, values); if (from == address(0)) { uint256 totalMintValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply[ids[i]] += value; totalMintValue += value; } // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows _totalSupplyAll += totalMintValue; } if (to == address(0)) { uint256 totalBurnValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; unchecked { // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) _totalSupply[ids[i]] -= value; // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll totalBurnValue += value; } } unchecked { // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll _totalSupplyAll -= totalBurnValue; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol) pragma solidity ^0.8.20; import {ERC1155} from "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. */ abstract contract ERC1155Burnable is ERC1155 { function burn(address account, uint256 id, uint256 value) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burn(account, id, value); } function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burnBatch(account, ids, values); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.20; import {IERC1155} from "./IERC1155.sol"; import {IERC1155Receiver} from "./IERC1155Receiver.sol"; import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol"; import {Context} from "../../utils/Context.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; import {Arrays} from "../../utils/Arrays.sol"; import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 */ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors { using Arrays for uint256[]; using Arrays for address[]; mapping(uint256 id => mapping(address account => uint256)) private _balances; mapping(address account => mapping(address operator => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256 /* id */) public view virtual returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual returns (uint256[] memory) { if (accounts.length != ids.length) { revert ERC1155InvalidArrayLength(ids.length, accounts.length); } uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i)); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeTransferFrom(from, to, id, value, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeBatchTransferFrom(from, to, ids, values, data); } /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` * (or `to`) is the zero address. * * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. * * Requirements: * * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. * - `ids` and `values` must have the same length. * * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. */ function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { if (ids.length != values.length) { revert ERC1155InvalidArrayLength(ids.length, values.length); } address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); uint256 value = values.unsafeMemoryAccess(i); if (from != address(0)) { uint256 fromBalance = _balances[id][from]; if (fromBalance < value) { revert ERC1155InsufficientBalance(from, fromBalance, value, id); } unchecked { // Overflow not possible: value <= fromBalance _balances[id][from] = fromBalance - value; } } if (to != address(0)) { _balances[id][to] += value; } } if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); emit TransferSingle(operator, from, to, id, value); } else { emit TransferBatch(operator, from, to, ids, values); } } /** * @dev Version of {_update} that performs the token acceptance check by calling * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it * contains code (eg. is a smart contract at the moment of execution). * * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any * update to the contract state after this function would break the check-effect-interaction pattern. Consider * overriding {_update} instead. */ function _updateWithAcceptanceCheck( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal virtual { _update(from, to, ids, values); if (to != address(0)) { address operator = _msgSender(); if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); _doSafeTransferAcceptanceCheck(operator, from, to, id, value, data); } else { _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data); } } } /** * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. * - `ids` and `values` must have the same length. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the values in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` must have the same length. * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev Destroys a `value` amount of tokens of type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. */ function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. * - `ids` and `values` must have the same length. */ function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address * if it contains code at the moment of execution. */ function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 value, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address * if it contains code at the moment of execution. */ function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Creates an array in memory with only one value for each of the elements provided. */ function _asSingletonArrays( uint256 element1, uint256 element2 ) private pure returns (uint256[] memory array1, uint256[] memory array2) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer array1 := mload(0x40) // Set array length to 1 mstore(array1, 1) // Store the single element at the next word after the length (where content starts) mstore(add(array1, 0x20), element1) // Repeat for next array locating it right after the first array array2 := add(array1, 0x40) mstore(array2, 1) mstore(add(array2, 0x20), element2) // Update the free memory pointer by pointing after the second array mstore(0x40, add(array2, 0x40)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// 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); } }
{ "remappings": [], "optimizer": { "enabled": false, "runs": 200 }, "evmVersion": "shanghai", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_usdtToken","type":"address"},{"internalType":"address","name":"_mmcToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[],"name":"FailedInnerCall","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":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"buyNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"destroyContractNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"string[]","name":"tokenUris","type":"string[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"},{"internalType":"uint8[]","name":"types","type":"uint8[]"},{"internalType":"uint8[]","name":"statuses","type":"uint8[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mintBatchWithUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mmcToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"receiveERC20","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":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferContract","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":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleStatus","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"newUri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setPoolPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_status","type":"uint8"}],"name":"setSaleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"}],"name":"setTokenStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"newUris","type":"string[]"}],"name":"setTokenURIBatch","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":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint8","name":"swapType","type":"uint8"}],"name":"swapExchangeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenInfo","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint8","name":"tokenType","type":"uint8"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"},{"internalType":"uint256","name":"_amountA","type":"uint256"},{"internalType":"uint256","name":"_amountB","type":"uint256"},{"internalType":"uint256","name":"_minAmountA","type":"uint256"},{"internalType":"uint256","name":"_minAmountB","type":"uint256"}],"name":"uniAddLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"},{"internalType":"uint256","name":"_liquidity","type":"uint256"},{"internalType":"uint256","name":"_minAmountA","type":"uint256"},{"internalType":"uint256","name":"_minAmountB","type":"uint256"}],"name":"uniRemoveLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Factory","outputs":[{"internalType":"contract IUniswapV2Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdtToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawUSDT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawableUSDT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040526032600a5534801562000015575f80fd5b50604051620066bd380380620066bd83398181016040528101906200003b919062000332565b3360405180602001604052805f8152506200005c81620001f560201b60201c565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000d0575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000c79190620003b2565b60405180910390fd5b620000e1816200020a60201b60201c565b5060016006819055508360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600c60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505062000715565b806002908162000206919062000631565b5050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002fc82620002d1565b9050919050565b6200030e81620002f0565b811462000319575f80fd5b50565b5f815190506200032c8162000303565b92915050565b5f805f80608085870312156200034d576200034c620002cd565b5b5f6200035c878288016200031c565b94505060206200036f878288016200031c565b935050604062000382878288016200031c565b925050606062000395878288016200031c565b91505092959194509250565b620003ac81620002f0565b82525050565b5f602082019050620003c75f830184620003a1565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200044957607f821691505b6020821081036200045f576200045e62000404565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004c37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000486565b620004cf868362000486565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f62000519620005136200050d84620004e7565b620004f0565b620004e7565b9050919050565b5f819050919050565b6200053483620004f9565b6200054c620005438262000520565b84845462000492565b825550505050565b5f90565b6200056262000554565b6200056f81848462000529565b505050565b5b8181101562000596576200058a5f8262000558565b60018101905062000575565b5050565b601f821115620005e557620005af8162000465565b620005ba8462000477565b81016020851015620005ca578190505b620005e2620005d98562000477565b83018262000574565b50505b505050565b5f82821c905092915050565b5f620006075f1984600802620005ea565b1980831691505092915050565b5f620006218383620005f6565b9150826002028217905092915050565b6200063c82620003cd565b67ffffffffffffffff811115620006585762000657620003d7565b5b62000664825462000431565b620006718282856200059a565b5f60209050601f831160018114620006a7575f841562000692578287015190505b6200069e858262000614565b8655506200070d565b601f198416620006b78662000465565b5f5b82811015620006e057848901518255600182019150602085019450602081019050620006b9565b86831015620007005784890151620006fc601f891682620005f6565b8355505b6001600288020188555050505b505050505050565b615f9a80620007235f395ff3fe608060405234801561000f575f80fd5b5060043610610250575f3560e01c8063715018a611610144578063bd85b039116100c1578063f23a6e6111610085578063f23a6e61146106dd578063f242432a1461070d578063f2fde38b14610729578063f5298aca14610745578063f807427d14610761578063f9020e331461077d57610250565b8063bd85b03914610612578063c4d32bf314610642578063cc33c8751461065e578063cf8ca74114610691578063e985e9c5146106ad57610250565b8063a8275ada11610108578063a8275ada14610570578063a98ad46c1461058c578063ae28b68c146105aa578063aed4aab6146105c6578063bc197c81146105e257610250565b8063715018a6146104f457806386f5c0d8146104fe5780638d8a818c1461051a5780638da5cb5b14610536578063a22cb4651461055457610250565b80633d54353a116101d25780634f558e79116101965780634f558e791461045257806355f804b31461048257806359d0f7131461049e5780636b20c454146104bc5780636b421a50146104d857610250565b80633d54353a146103ae5780633e7e30ba146103cc5780634891ad88146103ea5780634bb99351146104065780634e1273f41461042257610250565b80631694505e116102195780631694505e1461031c57806318160ddd1461033a5780632e6ceabe146103585780632eb2c2d61461037457806334b633ce1461039057610250565b8062fdd58e1461025457806301ffc9a7146102845780630e89341c146102b457806312d6f800146102e45780631481794e14610300575b5f80fd5b61026e60048036038101906102699190613e49565b61079b565b60405161027b9190613e96565b60405180910390f35b61029e60048036038101906102999190613f04565b6107f0565b6040516102ab9190613f49565b60405180910390f35b6102ce60048036038101906102c99190613f62565b6108d1565b6040516102db9190614017565b60405180910390f35b6102fe60048036038101906102f99190614499565b6109e0565b005b61031a60048036038101906103159190613e49565b610c14565b005b610324610d12565b6040516103319190614669565b60405180910390f35b610342610d37565b60405161034f9190613e96565b60405180910390f35b610372600480360381019061036d9190614682565b610d40565b005b61038e6004803603810190610389919061470b565b61107d565b005b610398611124565b6040516103a59190613e96565b60405180910390f35b6103b661112a565b6040516103c391906147f6565b60405180910390f35b6103d461114f565b6040516103e19190613e96565b60405180910390f35b61040460048036038101906103ff919061480f565b611155565b005b610420600480360381019061041b919061483a565b6111cd565b005b61043c60048036038101906104379190614970565b611292565b6040516104499190614a9d565b60405180910390f35b61046c60048036038101906104679190613f62565b61139f565b6040516104799190613f49565b60405180910390f35b61049c60048036038101906104979190614abd565b6113b2565b005b6104a66113c6565b6040516104b39190614b24565b60405180910390f35b6104d660048036038101906104d19190614b3d565b6113eb565b005b6104f260048036038101906104ed9190614bc5565b611497565b005b6104fc6116b3565b005b61051860048036038101906105139190614c3c565b6116c6565b005b610534600480360381019061052f9190614cbc565b611a22565b005b61053e611a39565b60405161054b9190614d09565b60405180910390f35b61056e60048036038101906105699190614d4c565b611a61565b005b61058a60048036038101906105859190613f62565b611a77565b005b610594611ada565b6040516105a191906147f6565b60405180910390f35b6105c460048036038101906105bf9190614c3c565b611b00565b005b6105e060048036038101906105db9190614dc5565b611b1b565b005b6105fc60048036038101906105f79190614eb1565b611b9d565b6040516106099190614f97565b60405180910390f35b61062c60048036038101906106279190613f62565b611bb4565b6040516106399190613e96565b60405180910390f35b61065c60048036038101906106579190614fb0565b611bce565b005b61067860048036038101906106739190613f62565b612070565b604051610688949392919061500f565b60405180910390f35b6106ab60048036038101906106a69190614c3c565b61213b565b005b6106c760048036038101906106c29190615059565b612156565b6040516106d49190613f49565b60405180910390f35b6106f760048036038101906106f29190615097565b6121e4565b6040516107049190614f97565b60405180910390f35b6107276004803603810190610722919061512d565b6121f9565b005b610743600480360381019061073e91906151c0565b6122a0565b005b61075f600480360381019061075a91906151eb565b612324565b005b61077b6004803603810190610776919061523b565b6123d0565b005b61078561245c565b6040516107929190615279565b60405180910390f35b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108ba57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108ca57506108c98261246e565b5b9050919050565b60605f60095f8481526020019081526020015f2060020180546108f3906152bf565b80601f016020809104026020016040519081016040528092919081815260200182805461091f906152bf565b801561096a5780601f106109415761010080835404028352916020019161096a565b820191905f5260205f20905b81548152906001019060200180831161094d57829003601f168201915b505050505090505f61097b846124d7565b90505f8251116109b4578061098f85612569565b6040516020016109a0929190615329565b6040516020818303038152906040526109d7565b80826040516020016109c7929190615329565b6040516020818303038152906040525b92505050919050565b6109e8612633565b855187511480156109fa575084518751145b8015610a07575083518751145b8015610a14575082518751145b8015610a21575081518751145b610a60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5790615396565b60405180910390fd5b5f5b8751811015610bfd57610a8e888281518110610a8157610a806153b4565b5b602002602001015161139f565b15610ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac59061542b565b60405180910390fd5b6040518060800160405280868381518110610aec57610aeb6153b4565b5b60200260200101518152602001858381518110610b0c57610b0b6153b4565b5b602002602001015160ff168152602001848381518110610b2f57610b2e6153b4565b5b602002602001015160ff168152602001878381518110610b5257610b516153b4565b5b602002602001015181525060095f8a8481518110610b7357610b726153b4565b5b602002602001015181526020019081526020015f205f820151815f01556020820151816001015f6101000a81548160ff021916908360ff16021790555060408201518160010160016101000a81548160ff021916908360ff1602179055506060820151816002019081610be691906155dd565b509050508080610bf5906156d9565b915050610a62565b50610c0a888888846126ba565b5050505050505050565b610c1c612633565b610c2461273d565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610c625750600b548111155b610ca1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9890615396565b60405180910390fd5b80600b5f828254610cb29190615720565b92505081905550610d068282600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127839092919063ffffffff16565b610d0e612802565b5050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600554905090565b610d48612633565b5f600b54600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610da79190614d09565b602060405180830381865afa158015610dc2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610de69190615767565b610df09190615720565b9050600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603610e8b5780851115610e8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8190615396565b60405180910390fd5b5b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610f245780841115610f23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f1a90615396565b60405180910390fd5b5b610f7060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868973ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b610fbc60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858873ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8e33700888888888888306103844261100e9190615792565b6040518963ffffffff1660e01b81526004016110319897969594939291906157c5565b6060604051808303815f875af115801561104d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110719190615841565b50505050505050505050565b5f6110866128a5565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141580156110cb57506110c98682612156565b155b1561110f5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611106929190615891565b60405180910390fd5b61111c86868686866128ac565b505050505050565b600b5481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a5481565b61115d612633565b5f8160ff161480611171575060018160ff16145b6111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a790615396565b60405180910390fd5b80600c5f6101000a81548160ff021916908360ff16021790555050565b6111d5612633565b8051825114611219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121090615396565b60405180910390fd5b5f5b825181101561128d57818181518110611237576112366153b4565b5b602002602001015160095f858481518110611255576112546153b4565b5b602002602001015181526020019081526020015f20600201908161127991906155dd565b508080611285906156d9565b91505061121b565b505050565b606081518351146112de57815183516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016112d59291906158b8565b60405180910390fd5b5f835167ffffffffffffffff8111156112fa576112f961403b565b5b6040519080825280602002602001820160405280156113285781602001602082028036833780820191505090505b5090505f5b84518110156113945761136461134c82876129a090919063ffffffff16565b61135f83876129b390919063ffffffff16565b61079b565b828281518110611377576113766153b4565b5b6020026020010181815250508061138d906156d9565b905061132d565b508091505092915050565b5f806113aa83611bb4565b119050919050565b6113ba612633565b6113c3816129c6565b50565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6113f36128a5565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561143c575061143a836114356128a5565b612156565b155b15611487576114496128a5565b836040517fe237d92200000000000000000000000000000000000000000000000000000000815260040161147e929190615891565b60405180910390fd5b6114928383836129d9565b505050565b61149f612633565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a4390587876040518363ffffffff1660e01b81526004016114fc929190615891565b602060405180830381865afa158015611517573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061153b91906158f3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290615396565b60405180910390fd5b6115f760075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858373ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663baa2abde878787878730610384426116489190615792565b6040518863ffffffff1660e01b815260040161166a979695949392919061591e565b60408051808303815f875af1158015611685573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116a9919061598b565b5050505050505050565b6116bb612633565b6116c45f612a69565b565b6116ce61273d565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561170957505f82115b801561172657506001600c5f9054906101000a900460ff1660ff16145b80156117565750600160095f8581526020019081526020015f2060010160019054906101000a900460ff1660ff16145b611795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178c90615396565b60405180910390fd5b5f8260095f8681526020019081526020015f205f01546117b591906159c9565b9050826117c2308661079b565b1015801561186b575080600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401611829929190615891565b602060405180830381865afa158015611844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118689190615767565b10155b8015611910575080600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016118ce9190614d09565b602060405180830381865afa1580156118e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061190d9190615767565b10155b61194f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194690615396565b60405180910390fd5b61199e333083600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b2c909392919063ffffffff16565b600160095f8681526020019081526020015f206001015f9054906101000a900460ff1660ff1603611a06576064600a54826119d991906159c9565b6119e39190615a37565b816119ee9190615720565b600b5f8282546119fe9190615792565b925050819055505b611a133086868686612bae565b50611a1c612802565b50505050565b611a2a612633565b611a35308383612cb4565b5050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611a73611a6c6128a5565b8383612d56565b5050565b611a7f612633565b60328110158015611a91575060648111155b611ad0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac790615396565b60405180910390fd5b80600a8190555050565b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611b08612633565b611b1533858585856121f9565b50505050565b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b8152600401611b5893929190615a67565b6020604051808303815f875af1158015611b74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b989190615ab0565b505050565b5f63bc197c8160e01b905098975050505050505050565b5f60045f8381526020019081526020015f20549050919050565b611bd6612633565b5f600267ffffffffffffffff811115611bf257611bf161403b565b5b604051908082528060200260200182016040528015611c205781602001602082028036833780820191505090505b5090505f8260ff1603611e6957600b54600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611c8b9190614d09565b602060405180830381865afa158015611ca6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cca9190615767565b611cd49190615720565b841115611d16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0d90615396565b60405180910390fd5b611d8460075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815f81518110611dba57611db96153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681600181518110611e2a57611e296153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611fb7565b611ed660075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815f81518110611f0b57611f0a6153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681600181518110611f7c57611f7b6153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173985858430610384426120069190615792565b6040518663ffffffff1660e01b8152600401612026959493929190615b92565b5f604051808303815f875af1158015612041573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906120699190615c7f565b5050505050565b6009602052805f5260405f205f91509050805f015490806001015f9054906101000a900460ff16908060010160019054906101000a900460ff16908060020180546120ba906152bf565b80601f01602080910402602001604051908101604052809291908181526020018280546120e6906152bf565b80156121315780601f1061210857610100808354040283529160200191612131565b820191905f5260205f20905b81548152906001019060200180831161211457829003601f168201915b5050505050905084565b612143612633565b6121503085858585612bae565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f63f23a6e6160e01b90509695505050505050565b5f6122026128a5565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415801561224757506122458682612156565b155b1561228b5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401612282929190615891565b60405180910390fd5b6122988686868686612bae565b505050505050565b6122a8612633565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612318575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161230f9190614d09565b60405180910390fd5b61232181612a69565b50565b61232c6128a5565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561237557506123738361236e6128a5565b612156565b155b156123c0576123826128a5565b836040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016123b7929190615891565b60405180910390fd5b6123cb838383612cb4565b505050565b6123d8612633565b5f8160ff1614806123ec575060018160ff16145b61242b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242290615396565b60405180910390fd5b8060095f8481526020019081526020015f2060010160016101000a81548160ff021916908360ff1602179055505050565b600c5f9054906101000a900460ff1681565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600280546124e6906152bf565b80601f0160208091040260200160405190810160405280929190818152602001828054612512906152bf565b801561255d5780601f106125345761010080835404028352916020019161255d565b820191905f5260205f20905b81548152906001019060200180831161254057829003601f168201915b50505050509050919050565b60605f600161257784612ebf565b0190505f8167ffffffffffffffff8111156125955761259461403b565b5b6040519080825280601f01601f1916602001820160405280156125c75781602001600182028036833780820191505090505b5090505f82602001820190505b600115612628578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161261d5761261c615a0a565b5b0494505f85036125d4575b819350505050919050565b61263b6128a5565b73ffffffffffffffffffffffffffffffffffffffff16612659611a39565b73ffffffffffffffffffffffffffffffffffffffff16146126b85761267c6128a5565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016126af9190614d09565b60405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361272a575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016127219190614d09565b60405180910390fd5b6127375f85858585613010565b50505050565b600260065403612779576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6127fd838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016127b6929190615cc6565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b505050565b6001600681905550565b5f8373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401612848929190615891565b602060405180830381865afa158015612863573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128879190615767565b905061289f8484848461289a9190615792565b613151565b50505050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361291c575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016129139190614d09565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361298c575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016129839190614d09565b60405180910390fd5b6129998585858585613010565b5050505050565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b80600290816129d591906155dd565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a49575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612a409190614d09565b60405180910390fd5b612a64835f848460405180602001604052805f815250613010565b505050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612ba8848573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401612b6193929190615a67565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c1e575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612c159190614d09565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c8e575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612c859190614d09565b60405180910390fd5b5f80612c9a858561325e565b91509150612cab8787848487613010565b50505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612d24575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612d1b9190614d09565b60405180910390fd5b5f80612d30848461325e565b91509150612d4f855f848460405180602001604052805f815250613010565b5050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612dc6575f6040517fced3e100000000000000000000000000000000000000000000000000000000008152600401612dbd9190614d09565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612eb29190613f49565b60405180910390a3505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f1b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f1157612f10615a0a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612f58576d04ee2d6d415b85acef81000000008381612f4e57612f4d615a0a565b5b0492506020810190505b662386f26fc100008310612f8757662386f26fc100008381612f7d57612f7c615a0a565b5b0492506010810190505b6305f5e1008310612fb0576305f5e1008381612fa657612fa5615a0a565b5b0492506008810190505b6127108310612fd5576127108381612fcb57612fca615a0a565b5b0492506004810190505b60648310612ff85760648381612fee57612fed615a0a565b5b0492506002810190505b600a8310613007576001810190505b80915050919050565b61301c8585858561328e565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146130b5575f6130586128a5565b905060018451036130a4575f6130775f866129b390919063ffffffff16565b90505f61308d5f866129b390919063ffffffff16565b905061309d8389898585896132a0565b50506130b3565b6130b281878787878761344f565b5b505b5050505050565b5f6130e6828473ffffffffffffffffffffffffffffffffffffffff166135fe90919063ffffffff16565b90505f81511415801561310a5750808060200190518101906131089190615ab0565b155b1561314c57826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016131439190614d09565b60405180910390fd5b505050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663095ea7b38484604051602401613181929190615cc6565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506131cf8482613613565b6132585761324d848573ffffffffffffffffffffffffffffffffffffffff1663095ea7b3865f604051602401613206929190615d26565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b61325784826130bc565b5b50505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b61329a848484846136d2565b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115613447578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401613300959493929190615d9f565b6020604051808303815f875af192505050801561333b57506040513d601f19601f820116820180604052508101906133389190615e0b565b60015b6133bc573d805f8114613369576040519150601f19603f3d011682016040523d82523d5f602084013e61336e565b606091505b505f8151036133b457846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016133ab9190614d09565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461344557846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161343c9190614d09565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156135f6578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016134af959493929190615e36565b6020604051808303815f875af19250505080156134ea57506040513d601f19601f820116820180604052508101906134e79190615e0b565b60015b61356b573d805f8114613518576040519150601f19603f3d011682016040523d82523d5f602084013e61351d565b606091505b505f81510361356357846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161355a9190614d09565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146135f457846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016135eb9190614d09565b60405180910390fd5b505b505050505050565b606061360b83835f61387b565b905092915050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff168460405161363b9190615ed6565b5f604051808303815f865af19150503d805f8114613674576040519150601f19603f3d011682016040523d82523d5f602084013e613679565b606091505b50915091508180156136a657505f815114806136a55750808060200190518101906136a49190615ab0565b5b5b80156136c857505f8573ffffffffffffffffffffffffffffffffffffffff163b115b9250505092915050565b6136de84848484613944565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036137b7575f805b835181101561379c575f838281518110613731576137306153b4565b5b602002602001015190508060045f878581518110613752576137516153b4565b5b602002602001015181526020019081526020015f205f8282546137759190615792565b9250508190555080836137889190615792565b92505080613795906156d9565b9050613714565b508060055f8282546137ae9190615792565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613875575f805b8351811015613863575f83828151811061380a576138096153b4565b5b602002602001015190508060045f87858151811061382b5761382a6153b4565b5b602002602001015181526020019081526020015f205f82825403925050819055508083019250508061385c906156d9565b90506137ed565b508060055f8282540392505081905550505b50505050565b6060814710156138c257306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016138b99190614d09565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516138ea9190615ed6565b5f6040518083038185875af1925050503d805f8114613924576040519150601f19603f3d011682016040523d82523d5f602084013e613929565b606091505b5091509150613939868383613cda565b925050509392505050565b805182511461398e57815181516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016139859291906158b8565b60405180910390fd5b5f6139976128a5565b90505f5b8351811015613b99575f6139b882866129b390919063ffffffff16565b90505f6139ce83866129b390919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614613af1575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015613a9d57888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401613a949493929190615eec565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613b8657805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b7e9190615792565b925050819055505b505080613b92906156d9565b905061399b565b506001835103613c54575f613bb75f856129b390919063ffffffff16565b90505f613bcd5f856129b390919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613c459291906158b8565b60405180910390a45050613cd3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613cca929190615f2f565b60405180910390a45b5050505050565b606082613cef57613cea82613d67565b613d5f565b5f8251148015613d1557505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15613d5757836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401613d4e9190614d09565b60405180910390fd5b819050613d60565b5b9392505050565b5f81511115613d795780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613de582613dbc565b9050919050565b613df581613ddb565b8114613dff575f80fd5b50565b5f81359050613e1081613dec565b92915050565b5f819050919050565b613e2881613e16565b8114613e32575f80fd5b50565b5f81359050613e4381613e1f565b92915050565b5f8060408385031215613e5f57613e5e613db4565b5b5f613e6c85828601613e02565b9250506020613e7d85828601613e35565b9150509250929050565b613e9081613e16565b82525050565b5f602082019050613ea95f830184613e87565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ee381613eaf565b8114613eed575f80fd5b50565b5f81359050613efe81613eda565b92915050565b5f60208284031215613f1957613f18613db4565b5b5f613f2684828501613ef0565b91505092915050565b5f8115159050919050565b613f4381613f2f565b82525050565b5f602082019050613f5c5f830184613f3a565b92915050565b5f60208284031215613f7757613f76613db4565b5b5f613f8484828501613e35565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613fc4578082015181840152602081019050613fa9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f613fe982613f8d565b613ff38185613f97565b9350614003818560208601613fa7565b61400c81613fcf565b840191505092915050565b5f6020820190508181035f83015261402f8184613fdf565b905092915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61407182613fcf565b810181811067ffffffffffffffff821117156140905761408f61403b565b5b80604052505050565b5f6140a2613dab565b90506140ae8282614068565b919050565b5f67ffffffffffffffff8211156140cd576140cc61403b565b5b602082029050602081019050919050565b5f80fd5b5f6140f46140ef846140b3565b614099565b90508083825260208201905060208402830185811115614117576141166140de565b5b835b81811015614140578061412c8882613e35565b845260208401935050602081019050614119565b5050509392505050565b5f82601f83011261415e5761415d614037565b5b813561416e8482602086016140e2565b91505092915050565b5f67ffffffffffffffff8211156141915761419061403b565b5b602082029050602081019050919050565b5f80fd5b5f67ffffffffffffffff8211156141c0576141bf61403b565b5b6141c982613fcf565b9050602081019050919050565b828183375f83830152505050565b5f6141f66141f1846141a6565b614099565b905082815260208101848484011115614212576142116141a2565b5b61421d8482856141d6565b509392505050565b5f82601f83011261423957614238614037565b5b81356142498482602086016141e4565b91505092915050565b5f61426461425f84614177565b614099565b90508083825260208201905060208402830185811115614287576142866140de565b5b835b818110156142ce57803567ffffffffffffffff8111156142ac576142ab614037565b5b8086016142b98982614225565b85526020850194505050602081019050614289565b5050509392505050565b5f82601f8301126142ec576142eb614037565b5b81356142fc848260208601614252565b91505092915050565b5f67ffffffffffffffff82111561431f5761431e61403b565b5b602082029050602081019050919050565b5f60ff82169050919050565b61434581614330565b811461434f575f80fd5b50565b5f813590506143608161433c565b92915050565b5f61437861437384614305565b614099565b9050808382526020820190506020840283018581111561439b5761439a6140de565b5b835b818110156143c457806143b08882614352565b84526020840193505060208101905061439d565b5050509392505050565b5f82601f8301126143e2576143e1614037565b5b81356143f2848260208601614366565b91505092915050565b5f67ffffffffffffffff8211156144155761441461403b565b5b61441e82613fcf565b9050602081019050919050565b5f61443d614438846143fb565b614099565b905082815260208101848484011115614459576144586141a2565b5b6144648482856141d6565b509392505050565b5f82601f8301126144805761447f614037565b5b813561449084826020860161442b565b91505092915050565b5f805f805f805f80610100898b0312156144b6576144b5613db4565b5b5f6144c38b828c01613e02565b985050602089013567ffffffffffffffff8111156144e4576144e3613db8565b5b6144f08b828c0161414a565b975050604089013567ffffffffffffffff81111561451157614510613db8565b5b61451d8b828c0161414a565b965050606089013567ffffffffffffffff81111561453e5761453d613db8565b5b61454a8b828c016142d8565b955050608089013567ffffffffffffffff81111561456b5761456a613db8565b5b6145778b828c0161414a565b94505060a089013567ffffffffffffffff81111561459857614597613db8565b5b6145a48b828c016143ce565b93505060c089013567ffffffffffffffff8111156145c5576145c4613db8565b5b6145d18b828c016143ce565b92505060e089013567ffffffffffffffff8111156145f2576145f1613db8565b5b6145fe8b828c0161446c565b9150509295985092959890939650565b5f819050919050565b5f61463161462c61462784613dbc565b61460e565b613dbc565b9050919050565b5f61464282614617565b9050919050565b5f61465382614638565b9050919050565b61466381614649565b82525050565b5f60208201905061467c5f83018461465a565b92915050565b5f805f805f8060c0878903121561469c5761469b613db4565b5b5f6146a989828a01613e02565b96505060206146ba89828a01613e02565b95505060406146cb89828a01613e35565b94505060606146dc89828a01613e35565b93505060806146ed89828a01613e35565b92505060a06146fe89828a01613e35565b9150509295509295509295565b5f805f805f60a0868803121561472457614723613db4565b5b5f61473188828901613e02565b955050602061474288828901613e02565b945050604086013567ffffffffffffffff81111561476357614762613db8565b5b61476f8882890161414a565b935050606086013567ffffffffffffffff8111156147905761478f613db8565b5b61479c8882890161414a565b925050608086013567ffffffffffffffff8111156147bd576147bc613db8565b5b6147c98882890161446c565b9150509295509295909350565b5f6147e082614638565b9050919050565b6147f0816147d6565b82525050565b5f6020820190506148095f8301846147e7565b92915050565b5f6020828403121561482457614823613db4565b5b5f61483184828501614352565b91505092915050565b5f80604083850312156148505761484f613db4565b5b5f83013567ffffffffffffffff81111561486d5761486c613db8565b5b6148798582860161414a565b925050602083013567ffffffffffffffff81111561489a57614899613db8565b5b6148a6858286016142d8565b9150509250929050565b5f67ffffffffffffffff8211156148ca576148c961403b565b5b602082029050602081019050919050565b5f6148ed6148e8846148b0565b614099565b905080838252602082019050602084028301858111156149105761490f6140de565b5b835b8181101561493957806149258882613e02565b845260208401935050602081019050614912565b5050509392505050565b5f82601f83011261495757614956614037565b5b81356149678482602086016148db565b91505092915050565b5f806040838503121561498657614985613db4565b5b5f83013567ffffffffffffffff8111156149a3576149a2613db8565b5b6149af85828601614943565b925050602083013567ffffffffffffffff8111156149d0576149cf613db8565b5b6149dc8582860161414a565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b614a1881613e16565b82525050565b5f614a298383614a0f565b60208301905092915050565b5f602082019050919050565b5f614a4b826149e6565b614a5581856149f0565b9350614a6083614a00565b805f5b83811015614a90578151614a778882614a1e565b9750614a8283614a35565b925050600181019050614a63565b5085935050505092915050565b5f6020820190508181035f830152614ab58184614a41565b905092915050565b5f60208284031215614ad257614ad1613db4565b5b5f82013567ffffffffffffffff811115614aef57614aee613db8565b5b614afb84828501614225565b91505092915050565b5f614b0e82614638565b9050919050565b614b1e81614b04565b82525050565b5f602082019050614b375f830184614b15565b92915050565b5f805f60608486031215614b5457614b53613db4565b5b5f614b6186828701613e02565b935050602084013567ffffffffffffffff811115614b8257614b81613db8565b5b614b8e8682870161414a565b925050604084013567ffffffffffffffff811115614baf57614bae613db8565b5b614bbb8682870161414a565b9150509250925092565b5f805f805f60a08688031215614bde57614bdd613db4565b5b5f614beb88828901613e02565b9550506020614bfc88828901613e02565b9450506040614c0d88828901613e35565b9350506060614c1e88828901613e35565b9250506080614c2f88828901613e35565b9150509295509295909350565b5f805f8060808587031215614c5457614c53613db4565b5b5f614c6187828801613e02565b9450506020614c7287828801613e35565b9350506040614c8387828801613e35565b925050606085013567ffffffffffffffff811115614ca457614ca3613db8565b5b614cb08782880161446c565b91505092959194509250565b5f8060408385031215614cd257614cd1613db4565b5b5f614cdf85828601613e35565b9250506020614cf085828601613e35565b9150509250929050565b614d0381613ddb565b82525050565b5f602082019050614d1c5f830184614cfa565b92915050565b614d2b81613f2f565b8114614d35575f80fd5b50565b5f81359050614d4681614d22565b92915050565b5f8060408385031215614d6257614d61613db4565b5b5f614d6f85828601613e02565b9250506020614d8085828601614d38565b9150509250929050565b5f614d9482613ddb565b9050919050565b614da481614d8a565b8114614dae575f80fd5b50565b5f81359050614dbf81614d9b565b92915050565b5f8060408385031215614ddb57614dda613db4565b5b5f614de885828601614db1565b9250506020614df985828601613e35565b9150509250929050565b5f80fd5b5f8083601f840112614e1c57614e1b614037565b5b8235905067ffffffffffffffff811115614e3957614e38614e03565b5b602083019150836020820283011115614e5557614e546140de565b5b9250929050565b5f8083601f840112614e7157614e70614037565b5b8235905067ffffffffffffffff811115614e8e57614e8d614e03565b5b602083019150836001820283011115614eaa57614ea96140de565b5b9250929050565b5f805f805f805f8060a0898b031215614ecd57614ecc613db4565b5b5f614eda8b828c01613e02565b9850506020614eeb8b828c01613e02565b975050604089013567ffffffffffffffff811115614f0c57614f0b613db8565b5b614f188b828c01614e07565b9650965050606089013567ffffffffffffffff811115614f3b57614f3a613db8565b5b614f478b828c01614e07565b9450945050608089013567ffffffffffffffff811115614f6a57614f69613db8565b5b614f768b828c01614e5c565b92509250509295985092959890939650565b614f9181613eaf565b82525050565b5f602082019050614faa5f830184614f88565b92915050565b5f805f60608486031215614fc757614fc6613db4565b5b5f614fd486828701613e35565b9350506020614fe586828701613e35565b9250506040614ff686828701614352565b9150509250925092565b61500981614330565b82525050565b5f6080820190506150225f830187613e87565b61502f6020830186615000565b61503c6040830185615000565b818103606083015261504e8184613fdf565b905095945050505050565b5f806040838503121561506f5761506e613db4565b5b5f61507c85828601613e02565b925050602061508d85828601613e02565b9150509250929050565b5f805f805f8060a087890312156150b1576150b0613db4565b5b5f6150be89828a01613e02565b96505060206150cf89828a01613e02565b95505060406150e089828a01613e35565b94505060606150f189828a01613e35565b935050608087013567ffffffffffffffff81111561511257615111613db8565b5b61511e89828a01614e5c565b92509250509295509295509295565b5f805f805f60a0868803121561514657615145613db4565b5b5f61515388828901613e02565b955050602061516488828901613e02565b945050604061517588828901613e35565b935050606061518688828901613e35565b925050608086013567ffffffffffffffff8111156151a7576151a6613db8565b5b6151b38882890161446c565b9150509295509295909350565b5f602082840312156151d5576151d4613db4565b5b5f6151e284828501613e02565b91505092915050565b5f805f6060848603121561520257615201613db4565b5b5f61520f86828701613e02565b935050602061522086828701613e35565b925050604061523186828701613e35565b9150509250925092565b5f806040838503121561525157615250613db4565b5b5f61525e85828601613e35565b925050602061526f85828601614352565b9150509250929050565b5f60208201905061528c5f830184615000565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806152d657607f821691505b6020821081036152e9576152e8615292565b5b50919050565b5f81905092915050565b5f61530382613f8d565b61530d81856152ef565b935061531d818560208601613fa7565b80840191505092915050565b5f61533482856152f9565b915061534082846152f9565b91508190509392505050565b7f496e76616c6964207265717565737400000000000000000000000000000000005f82015250565b5f615380600f83613f97565b915061538b8261534c565b602082019050919050565b5f6020820190508181035f8301526153ad81615374565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20494420616c7265616479206578697374730000000000000000005f82015250565b5f615415601783613f97565b9150615420826153e1565b602082019050919050565b5f6020820190508181035f83015261544281615409565b9050919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026154a57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261546a565b6154af868361546a565b95508019841693508086168417925050509392505050565b5f6154e16154dc6154d784613e16565b61460e565b613e16565b9050919050565b5f819050919050565b6154fa836154c7565b61550e615506826154e8565b848454615476565b825550505050565b5f90565b615522615516565b61552d8184846154f1565b505050565b5b81811015615550576155455f8261551a565b600181019050615533565b5050565b601f8211156155955761556681615449565b61556f8461545b565b8101602085101561557e578190505b61559261558a8561545b565b830182615532565b50505b505050565b5f82821c905092915050565b5f6155b55f198460080261559a565b1980831691505092915050565b5f6155cd83836155a6565b9150826002028217905092915050565b6155e682613f8d565b67ffffffffffffffff8111156155ff576155fe61403b565b5b61560982546152bf565b615614828285615554565b5f60209050601f831160018114615645575f8415615633578287015190505b61563d85826155c2565b8655506156a4565b601f19841661565386615449565b5f5b8281101561567a57848901518255600182019150602085019450602081019050615655565b868310156156975784890151615693601f8916826155a6565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156e382613e16565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615715576157146156ac565b5b600182019050919050565b5f61572a82613e16565b915061573583613e16565b925082820390508181111561574d5761574c6156ac565b5b92915050565b5f8151905061576181613e1f565b92915050565b5f6020828403121561577c5761577b613db4565b5b5f61578984828501615753565b91505092915050565b5f61579c82613e16565b91506157a783613e16565b92508282019050808211156157bf576157be6156ac565b5b92915050565b5f610100820190506157d95f83018b614cfa565b6157e6602083018a614cfa565b6157f36040830189613e87565b6158006060830188613e87565b61580d6080830187613e87565b61581a60a0830186613e87565b61582760c0830185614cfa565b61583460e0830184613e87565b9998505050505050505050565b5f805f6060848603121561585857615857613db4565b5b5f61586586828701615753565b935050602061587686828701615753565b925050604061588786828701615753565b9150509250925092565b5f6040820190506158a45f830185614cfa565b6158b16020830184614cfa565b9392505050565b5f6040820190506158cb5f830185613e87565b6158d86020830184613e87565b9392505050565b5f815190506158ed81613dec565b92915050565b5f6020828403121561590857615907613db4565b5b5f615915848285016158df565b91505092915050565b5f60e0820190506159315f83018a614cfa565b61593e6020830189614cfa565b61594b6040830188613e87565b6159586060830187613e87565b6159656080830186613e87565b61597260a0830185614cfa565b61597f60c0830184613e87565b98975050505050505050565b5f80604083850312156159a1576159a0613db4565b5b5f6159ae85828601615753565b92505060206159bf85828601615753565b9150509250929050565b5f6159d382613e16565b91506159de83613e16565b92508282026159ec81613e16565b91508282048414831517615a0357615a026156ac565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615a4182613e16565b9150615a4c83613e16565b925082615a5c57615a5b615a0a565b5b828204905092915050565b5f606082019050615a7a5f830186614cfa565b615a876020830185614cfa565b615a946040830184613e87565b949350505050565b5f81519050615aaa81614d22565b92915050565b5f60208284031215615ac557615ac4613db4565b5b5f615ad284828501615a9c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b615b0d81613ddb565b82525050565b5f615b1e8383615b04565b60208301905092915050565b5f602082019050919050565b5f615b4082615adb565b615b4a8185615ae5565b9350615b5583615af5565b805f5b83811015615b85578151615b6c8882615b13565b9750615b7783615b2a565b925050600181019050615b58565b5085935050505092915050565b5f60a082019050615ba55f830188613e87565b615bb26020830187613e87565b8181036040830152615bc48186615b36565b9050615bd36060830185614cfa565b615be06080830184613e87565b9695505050505050565b5f615bfc615bf7846140b3565b614099565b90508083825260208201905060208402830185811115615c1f57615c1e6140de565b5b835b81811015615c485780615c348882615753565b845260208401935050602081019050615c21565b5050509392505050565b5f82601f830112615c6657615c65614037565b5b8151615c76848260208601615bea565b91505092915050565b5f60208284031215615c9457615c93613db4565b5b5f82015167ffffffffffffffff811115615cb157615cb0613db8565b5b615cbd84828501615c52565b91505092915050565b5f604082019050615cd95f830185614cfa565b615ce66020830184613e87565b9392505050565b5f819050919050565b5f615d10615d0b615d0684615ced565b61460e565b613e16565b9050919050565b615d2081615cf6565b82525050565b5f604082019050615d395f830185614cfa565b615d466020830184615d17565b9392505050565b5f81519050919050565b5f82825260208201905092915050565b5f615d7182615d4d565b615d7b8185615d57565b9350615d8b818560208601613fa7565b615d9481613fcf565b840191505092915050565b5f60a082019050615db25f830188614cfa565b615dbf6020830187614cfa565b615dcc6040830186613e87565b615dd96060830185613e87565b8181036080830152615deb8184615d67565b90509695505050505050565b5f81519050615e0581613eda565b92915050565b5f60208284031215615e2057615e1f613db4565b5b5f615e2d84828501615df7565b91505092915050565b5f60a082019050615e495f830188614cfa565b615e566020830187614cfa565b8181036040830152615e688186614a41565b90508181036060830152615e7c8185614a41565b90508181036080830152615e908184615d67565b90509695505050505050565b5f81905092915050565b5f615eb082615d4d565b615eba8185615e9c565b9350615eca818560208601613fa7565b80840191505092915050565b5f615ee18284615ea6565b915081905092915050565b5f608082019050615eff5f830187614cfa565b615f0c6020830186613e87565b615f196040830185613e87565b615f266060830184613e87565b95945050505050565b5f6040820190508181035f830152615f478185614a41565b90508181036020830152615f5b8184614a41565b9050939250505056fea264697066735822122051efa173c94ef6b52f8eb5e62dcf4be19b02bd8a285c990213930cb047bdb76964736f6c634300081400330000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000088ee7a3537667958d040216d9dc1752d1274d838
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610250575f3560e01c8063715018a611610144578063bd85b039116100c1578063f23a6e6111610085578063f23a6e61146106dd578063f242432a1461070d578063f2fde38b14610729578063f5298aca14610745578063f807427d14610761578063f9020e331461077d57610250565b8063bd85b03914610612578063c4d32bf314610642578063cc33c8751461065e578063cf8ca74114610691578063e985e9c5146106ad57610250565b8063a8275ada11610108578063a8275ada14610570578063a98ad46c1461058c578063ae28b68c146105aa578063aed4aab6146105c6578063bc197c81146105e257610250565b8063715018a6146104f457806386f5c0d8146104fe5780638d8a818c1461051a5780638da5cb5b14610536578063a22cb4651461055457610250565b80633d54353a116101d25780634f558e79116101965780634f558e791461045257806355f804b31461048257806359d0f7131461049e5780636b20c454146104bc5780636b421a50146104d857610250565b80633d54353a146103ae5780633e7e30ba146103cc5780634891ad88146103ea5780634bb99351146104065780634e1273f41461042257610250565b80631694505e116102195780631694505e1461031c57806318160ddd1461033a5780632e6ceabe146103585780632eb2c2d61461037457806334b633ce1461039057610250565b8062fdd58e1461025457806301ffc9a7146102845780630e89341c146102b457806312d6f800146102e45780631481794e14610300575b5f80fd5b61026e60048036038101906102699190613e49565b61079b565b60405161027b9190613e96565b60405180910390f35b61029e60048036038101906102999190613f04565b6107f0565b6040516102ab9190613f49565b60405180910390f35b6102ce60048036038101906102c99190613f62565b6108d1565b6040516102db9190614017565b60405180910390f35b6102fe60048036038101906102f99190614499565b6109e0565b005b61031a60048036038101906103159190613e49565b610c14565b005b610324610d12565b6040516103319190614669565b60405180910390f35b610342610d37565b60405161034f9190613e96565b60405180910390f35b610372600480360381019061036d9190614682565b610d40565b005b61038e6004803603810190610389919061470b565b61107d565b005b610398611124565b6040516103a59190613e96565b60405180910390f35b6103b661112a565b6040516103c391906147f6565b60405180910390f35b6103d461114f565b6040516103e19190613e96565b60405180910390f35b61040460048036038101906103ff919061480f565b611155565b005b610420600480360381019061041b919061483a565b6111cd565b005b61043c60048036038101906104379190614970565b611292565b6040516104499190614a9d565b60405180910390f35b61046c60048036038101906104679190613f62565b61139f565b6040516104799190613f49565b60405180910390f35b61049c60048036038101906104979190614abd565b6113b2565b005b6104a66113c6565b6040516104b39190614b24565b60405180910390f35b6104d660048036038101906104d19190614b3d565b6113eb565b005b6104f260048036038101906104ed9190614bc5565b611497565b005b6104fc6116b3565b005b61051860048036038101906105139190614c3c565b6116c6565b005b610534600480360381019061052f9190614cbc565b611a22565b005b61053e611a39565b60405161054b9190614d09565b60405180910390f35b61056e60048036038101906105699190614d4c565b611a61565b005b61058a60048036038101906105859190613f62565b611a77565b005b610594611ada565b6040516105a191906147f6565b60405180910390f35b6105c460048036038101906105bf9190614c3c565b611b00565b005b6105e060048036038101906105db9190614dc5565b611b1b565b005b6105fc60048036038101906105f79190614eb1565b611b9d565b6040516106099190614f97565b60405180910390f35b61062c60048036038101906106279190613f62565b611bb4565b6040516106399190613e96565b60405180910390f35b61065c60048036038101906106579190614fb0565b611bce565b005b61067860048036038101906106739190613f62565b612070565b604051610688949392919061500f565b60405180910390f35b6106ab60048036038101906106a69190614c3c565b61213b565b005b6106c760048036038101906106c29190615059565b612156565b6040516106d49190613f49565b60405180910390f35b6106f760048036038101906106f29190615097565b6121e4565b6040516107049190614f97565b60405180910390f35b6107276004803603810190610722919061512d565b6121f9565b005b610743600480360381019061073e91906151c0565b6122a0565b005b61075f600480360381019061075a91906151eb565b612324565b005b61077b6004803603810190610776919061523b565b6123d0565b005b61078561245c565b6040516107929190615279565b60405180910390f35b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108ba57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108ca57506108c98261246e565b5b9050919050565b60605f60095f8481526020019081526020015f2060020180546108f3906152bf565b80601f016020809104026020016040519081016040528092919081815260200182805461091f906152bf565b801561096a5780601f106109415761010080835404028352916020019161096a565b820191905f5260205f20905b81548152906001019060200180831161094d57829003601f168201915b505050505090505f61097b846124d7565b90505f8251116109b4578061098f85612569565b6040516020016109a0929190615329565b6040516020818303038152906040526109d7565b80826040516020016109c7929190615329565b6040516020818303038152906040525b92505050919050565b6109e8612633565b855187511480156109fa575084518751145b8015610a07575083518751145b8015610a14575082518751145b8015610a21575081518751145b610a60576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5790615396565b60405180910390fd5b5f5b8751811015610bfd57610a8e888281518110610a8157610a806153b4565b5b602002602001015161139f565b15610ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac59061542b565b60405180910390fd5b6040518060800160405280868381518110610aec57610aeb6153b4565b5b60200260200101518152602001858381518110610b0c57610b0b6153b4565b5b602002602001015160ff168152602001848381518110610b2f57610b2e6153b4565b5b602002602001015160ff168152602001878381518110610b5257610b516153b4565b5b602002602001015181525060095f8a8481518110610b7357610b726153b4565b5b602002602001015181526020019081526020015f205f820151815f01556020820151816001015f6101000a81548160ff021916908360ff16021790555060408201518160010160016101000a81548160ff021916908360ff1602179055506060820151816002019081610be691906155dd565b509050508080610bf5906156d9565b915050610a62565b50610c0a888888846126ba565b5050505050505050565b610c1c612633565b610c2461273d565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610c625750600b548111155b610ca1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c9890615396565b60405180910390fd5b80600b5f828254610cb29190615720565b92505081905550610d068282600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127839092919063ffffffff16565b610d0e612802565b5050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600554905090565b610d48612633565b5f600b54600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610da79190614d09565b602060405180830381865afa158015610dc2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610de69190615767565b610df09190615720565b9050600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603610e8b5780851115610e8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8190615396565b60405180910390fd5b5b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603610f245780841115610f23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f1a90615396565b60405180910390fd5b5b610f7060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868973ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b610fbc60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858873ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8e33700888888888888306103844261100e9190615792565b6040518963ffffffff1660e01b81526004016110319897969594939291906157c5565b6060604051808303815f875af115801561104d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110719190615841565b50505050505050505050565b5f6110866128a5565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141580156110cb57506110c98682612156565b155b1561110f5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611106929190615891565b60405180910390fd5b61111c86868686866128ac565b505050505050565b600b5481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a5481565b61115d612633565b5f8160ff161480611171575060018160ff16145b6111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a790615396565b60405180910390fd5b80600c5f6101000a81548160ff021916908360ff16021790555050565b6111d5612633565b8051825114611219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121090615396565b60405180910390fd5b5f5b825181101561128d57818181518110611237576112366153b4565b5b602002602001015160095f858481518110611255576112546153b4565b5b602002602001015181526020019081526020015f20600201908161127991906155dd565b508080611285906156d9565b91505061121b565b505050565b606081518351146112de57815183516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016112d59291906158b8565b60405180910390fd5b5f835167ffffffffffffffff8111156112fa576112f961403b565b5b6040519080825280602002602001820160405280156113285781602001602082028036833780820191505090505b5090505f5b84518110156113945761136461134c82876129a090919063ffffffff16565b61135f83876129b390919063ffffffff16565b61079b565b828281518110611377576113766153b4565b5b6020026020010181815250508061138d906156d9565b905061132d565b508091505092915050565b5f806113aa83611bb4565b119050919050565b6113ba612633565b6113c3816129c6565b50565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6113f36128a5565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561143c575061143a836114356128a5565b612156565b155b15611487576114496128a5565b836040517fe237d92200000000000000000000000000000000000000000000000000000000815260040161147e929190615891565b60405180910390fd5b6114928383836129d9565b505050565b61149f612633565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a4390587876040518363ffffffff1660e01b81526004016114fc929190615891565b602060405180830381865afa158015611517573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061153b91906158f3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290615396565b60405180910390fd5b6115f760075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858373ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663baa2abde878787878730610384426116489190615792565b6040518863ffffffff1660e01b815260040161166a979695949392919061591e565b60408051808303815f875af1158015611685573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116a9919061598b565b5050505050505050565b6116bb612633565b6116c45f612a69565b565b6116ce61273d565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561170957505f82115b801561172657506001600c5f9054906101000a900460ff1660ff16145b80156117565750600160095f8581526020019081526020015f2060010160019054906101000a900460ff1660ff16145b611795576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178c90615396565b60405180910390fd5b5f8260095f8681526020019081526020015f205f01546117b591906159c9565b9050826117c2308661079b565b1015801561186b575080600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401611829929190615891565b602060405180830381865afa158015611844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118689190615767565b10155b8015611910575080600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016118ce9190614d09565b602060405180830381865afa1580156118e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061190d9190615767565b10155b61194f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194690615396565b60405180910390fd5b61199e333083600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b2c909392919063ffffffff16565b600160095f8681526020019081526020015f206001015f9054906101000a900460ff1660ff1603611a06576064600a54826119d991906159c9565b6119e39190615a37565b816119ee9190615720565b600b5f8282546119fe9190615792565b925050819055505b611a133086868686612bae565b50611a1c612802565b50505050565b611a2a612633565b611a35308383612cb4565b5050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611a73611a6c6128a5565b8383612d56565b5050565b611a7f612633565b60328110158015611a91575060648111155b611ad0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac790615396565b60405180910390fd5b80600a8190555050565b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611b08612633565b611b1533858585856121f9565b50505050565b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b8152600401611b5893929190615a67565b6020604051808303815f875af1158015611b74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b989190615ab0565b505050565b5f63bc197c8160e01b905098975050505050505050565b5f60045f8381526020019081526020015f20549050919050565b611bd6612633565b5f600267ffffffffffffffff811115611bf257611bf161403b565b5b604051908082528060200260200182016040528015611c205781602001602082028036833780820191505090505b5090505f8260ff1603611e6957600b54600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611c8b9190614d09565b602060405180830381865afa158015611ca6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cca9190615767565b611cd49190615720565b841115611d16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0d90615396565b60405180910390fd5b611d8460075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815f81518110611dba57611db96153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681600181518110611e2a57611e296153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611fb7565b611ed660075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661280c9092919063ffffffff16565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815f81518110611f0b57611f0a6153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600c60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681600181518110611f7c57611f7b6153b4565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173985858430610384426120069190615792565b6040518663ffffffff1660e01b8152600401612026959493929190615b92565b5f604051808303815f875af1158015612041573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906120699190615c7f565b5050505050565b6009602052805f5260405f205f91509050805f015490806001015f9054906101000a900460ff16908060010160019054906101000a900460ff16908060020180546120ba906152bf565b80601f01602080910402602001604051908101604052809291908181526020018280546120e6906152bf565b80156121315780601f1061210857610100808354040283529160200191612131565b820191905f5260205f20905b81548152906001019060200180831161211457829003601f168201915b5050505050905084565b612143612633565b6121503085858585612bae565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f63f23a6e6160e01b90509695505050505050565b5f6122026128a5565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415801561224757506122458682612156565b155b1561228b5780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401612282929190615891565b60405180910390fd5b6122988686868686612bae565b505050505050565b6122a8612633565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612318575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161230f9190614d09565b60405180910390fd5b61232181612a69565b50565b61232c6128a5565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561237557506123738361236e6128a5565b612156565b155b156123c0576123826128a5565b836040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016123b7929190615891565b60405180910390fd5b6123cb838383612cb4565b505050565b6123d8612633565b5f8160ff1614806123ec575060018160ff16145b61242b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242290615396565b60405180910390fd5b8060095f8481526020019081526020015f2060010160016101000a81548160ff021916908360ff1602179055505050565b600c5f9054906101000a900460ff1681565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060600280546124e6906152bf565b80601f0160208091040260200160405190810160405280929190818152602001828054612512906152bf565b801561255d5780601f106125345761010080835404028352916020019161255d565b820191905f5260205f20905b81548152906001019060200180831161254057829003601f168201915b50505050509050919050565b60605f600161257784612ebf565b0190505f8167ffffffffffffffff8111156125955761259461403b565b5b6040519080825280601f01601f1916602001820160405280156125c75781602001600182028036833780820191505090505b5090505f82602001820190505b600115612628578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161261d5761261c615a0a565b5b0494505f85036125d4575b819350505050919050565b61263b6128a5565b73ffffffffffffffffffffffffffffffffffffffff16612659611a39565b73ffffffffffffffffffffffffffffffffffffffff16146126b85761267c6128a5565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016126af9190614d09565b60405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361272a575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016127219190614d09565b60405180910390fd5b6127375f85858585613010565b50505050565b600260065403612779576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6127fd838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016127b6929190615cc6565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b505050565b6001600681905550565b5f8373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401612848929190615891565b602060405180830381865afa158015612863573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128879190615767565b905061289f8484848461289a9190615792565b613151565b50505050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361291c575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016129139190614d09565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361298c575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016129839190614d09565b60405180910390fd5b6129998585858585613010565b5050505050565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b80600290816129d591906155dd565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a49575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612a409190614d09565b60405180910390fd5b612a64835f848460405180602001604052805f815250613010565b505050565b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612ba8848573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401612b6193929190615a67565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c1e575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612c159190614d09565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c8e575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612c859190614d09565b60405180910390fd5b5f80612c9a858561325e565b91509150612cab8787848487613010565b50505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612d24575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612d1b9190614d09565b60405180910390fd5b5f80612d30848461325e565b91509150612d4f855f848460405180602001604052805f815250613010565b5050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612dc6575f6040517fced3e100000000000000000000000000000000000000000000000000000000008152600401612dbd9190614d09565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612eb29190613f49565b60405180910390a3505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612f1b577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381612f1157612f10615a0a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612f58576d04ee2d6d415b85acef81000000008381612f4e57612f4d615a0a565b5b0492506020810190505b662386f26fc100008310612f8757662386f26fc100008381612f7d57612f7c615a0a565b5b0492506010810190505b6305f5e1008310612fb0576305f5e1008381612fa657612fa5615a0a565b5b0492506008810190505b6127108310612fd5576127108381612fcb57612fca615a0a565b5b0492506004810190505b60648310612ff85760648381612fee57612fed615a0a565b5b0492506002810190505b600a8310613007576001810190505b80915050919050565b61301c8585858561328e565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146130b5575f6130586128a5565b905060018451036130a4575f6130775f866129b390919063ffffffff16565b90505f61308d5f866129b390919063ffffffff16565b905061309d8389898585896132a0565b50506130b3565b6130b281878787878761344f565b5b505b5050505050565b5f6130e6828473ffffffffffffffffffffffffffffffffffffffff166135fe90919063ffffffff16565b90505f81511415801561310a5750808060200190518101906131089190615ab0565b155b1561314c57826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016131439190614d09565b60405180910390fd5b505050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663095ea7b38484604051602401613181929190615cc6565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506131cf8482613613565b6132585761324d848573ffffffffffffffffffffffffffffffffffffffff1663095ea7b3865f604051602401613206929190615d26565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506130bc565b61325784826130bc565b5b50505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b61329a848484846136d2565b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115613447578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401613300959493929190615d9f565b6020604051808303815f875af192505050801561333b57506040513d601f19601f820116820180604052508101906133389190615e0b565b60015b6133bc573d805f8114613369576040519150601f19603f3d011682016040523d82523d5f602084013e61336e565b606091505b505f8151036133b457846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016133ab9190614d09565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461344557846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161343c9190614d09565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156135f6578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016134af959493929190615e36565b6020604051808303815f875af19250505080156134ea57506040513d601f19601f820116820180604052508101906134e79190615e0b565b60015b61356b573d805f8114613518576040519150601f19603f3d011682016040523d82523d5f602084013e61351d565b606091505b505f81510361356357846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161355a9190614d09565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146135f457846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016135eb9190614d09565b60405180910390fd5b505b505050505050565b606061360b83835f61387b565b905092915050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff168460405161363b9190615ed6565b5f604051808303815f865af19150503d805f8114613674576040519150601f19603f3d011682016040523d82523d5f602084013e613679565b606091505b50915091508180156136a657505f815114806136a55750808060200190518101906136a49190615ab0565b5b5b80156136c857505f8573ffffffffffffffffffffffffffffffffffffffff163b115b9250505092915050565b6136de84848484613944565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036137b7575f805b835181101561379c575f838281518110613731576137306153b4565b5b602002602001015190508060045f878581518110613752576137516153b4565b5b602002602001015181526020019081526020015f205f8282546137759190615792565b9250508190555080836137889190615792565b92505080613795906156d9565b9050613714565b508060055f8282546137ae9190615792565b92505081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613875575f805b8351811015613863575f83828151811061380a576138096153b4565b5b602002602001015190508060045f87858151811061382b5761382a6153b4565b5b602002602001015181526020019081526020015f205f82825403925050819055508083019250508061385c906156d9565b90506137ed565b508060055f8282540392505081905550505b50505050565b6060814710156138c257306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016138b99190614d09565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516138ea9190615ed6565b5f6040518083038185875af1925050503d805f8114613924576040519150601f19603f3d011682016040523d82523d5f602084013e613929565b606091505b5091509150613939868383613cda565b925050509392505050565b805182511461398e57815181516040517f5b0599910000000000000000000000000000000000000000000000000000000081526004016139859291906158b8565b60405180910390fd5b5f6139976128a5565b90505f5b8351811015613b99575f6139b882866129b390919063ffffffff16565b90505f6139ce83866129b390919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614613af1575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015613a9d57888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401613a949493929190615eec565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613b8657805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b7e9190615792565b925050819055505b505080613b92906156d9565b905061399b565b506001835103613c54575f613bb75f856129b390919063ffffffff16565b90505f613bcd5f856129b390919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613c459291906158b8565b60405180910390a45050613cd3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613cca929190615f2f565b60405180910390a45b5050505050565b606082613cef57613cea82613d67565b613d5f565b5f8251148015613d1557505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15613d5757836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401613d4e9190614d09565b60405180910390fd5b819050613d60565b5b9392505050565b5f81511115613d795780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613de582613dbc565b9050919050565b613df581613ddb565b8114613dff575f80fd5b50565b5f81359050613e1081613dec565b92915050565b5f819050919050565b613e2881613e16565b8114613e32575f80fd5b50565b5f81359050613e4381613e1f565b92915050565b5f8060408385031215613e5f57613e5e613db4565b5b5f613e6c85828601613e02565b9250506020613e7d85828601613e35565b9150509250929050565b613e9081613e16565b82525050565b5f602082019050613ea95f830184613e87565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ee381613eaf565b8114613eed575f80fd5b50565b5f81359050613efe81613eda565b92915050565b5f60208284031215613f1957613f18613db4565b5b5f613f2684828501613ef0565b91505092915050565b5f8115159050919050565b613f4381613f2f565b82525050565b5f602082019050613f5c5f830184613f3a565b92915050565b5f60208284031215613f7757613f76613db4565b5b5f613f8484828501613e35565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613fc4578082015181840152602081019050613fa9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f613fe982613f8d565b613ff38185613f97565b9350614003818560208601613fa7565b61400c81613fcf565b840191505092915050565b5f6020820190508181035f83015261402f8184613fdf565b905092915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61407182613fcf565b810181811067ffffffffffffffff821117156140905761408f61403b565b5b80604052505050565b5f6140a2613dab565b90506140ae8282614068565b919050565b5f67ffffffffffffffff8211156140cd576140cc61403b565b5b602082029050602081019050919050565b5f80fd5b5f6140f46140ef846140b3565b614099565b90508083825260208201905060208402830185811115614117576141166140de565b5b835b81811015614140578061412c8882613e35565b845260208401935050602081019050614119565b5050509392505050565b5f82601f83011261415e5761415d614037565b5b813561416e8482602086016140e2565b91505092915050565b5f67ffffffffffffffff8211156141915761419061403b565b5b602082029050602081019050919050565b5f80fd5b5f67ffffffffffffffff8211156141c0576141bf61403b565b5b6141c982613fcf565b9050602081019050919050565b828183375f83830152505050565b5f6141f66141f1846141a6565b614099565b905082815260208101848484011115614212576142116141a2565b5b61421d8482856141d6565b509392505050565b5f82601f83011261423957614238614037565b5b81356142498482602086016141e4565b91505092915050565b5f61426461425f84614177565b614099565b90508083825260208201905060208402830185811115614287576142866140de565b5b835b818110156142ce57803567ffffffffffffffff8111156142ac576142ab614037565b5b8086016142b98982614225565b85526020850194505050602081019050614289565b5050509392505050565b5f82601f8301126142ec576142eb614037565b5b81356142fc848260208601614252565b91505092915050565b5f67ffffffffffffffff82111561431f5761431e61403b565b5b602082029050602081019050919050565b5f60ff82169050919050565b61434581614330565b811461434f575f80fd5b50565b5f813590506143608161433c565b92915050565b5f61437861437384614305565b614099565b9050808382526020820190506020840283018581111561439b5761439a6140de565b5b835b818110156143c457806143b08882614352565b84526020840193505060208101905061439d565b5050509392505050565b5f82601f8301126143e2576143e1614037565b5b81356143f2848260208601614366565b91505092915050565b5f67ffffffffffffffff8211156144155761441461403b565b5b61441e82613fcf565b9050602081019050919050565b5f61443d614438846143fb565b614099565b905082815260208101848484011115614459576144586141a2565b5b6144648482856141d6565b509392505050565b5f82601f8301126144805761447f614037565b5b813561449084826020860161442b565b91505092915050565b5f805f805f805f80610100898b0312156144b6576144b5613db4565b5b5f6144c38b828c01613e02565b985050602089013567ffffffffffffffff8111156144e4576144e3613db8565b5b6144f08b828c0161414a565b975050604089013567ffffffffffffffff81111561451157614510613db8565b5b61451d8b828c0161414a565b965050606089013567ffffffffffffffff81111561453e5761453d613db8565b5b61454a8b828c016142d8565b955050608089013567ffffffffffffffff81111561456b5761456a613db8565b5b6145778b828c0161414a565b94505060a089013567ffffffffffffffff81111561459857614597613db8565b5b6145a48b828c016143ce565b93505060c089013567ffffffffffffffff8111156145c5576145c4613db8565b5b6145d18b828c016143ce565b92505060e089013567ffffffffffffffff8111156145f2576145f1613db8565b5b6145fe8b828c0161446c565b9150509295985092959890939650565b5f819050919050565b5f61463161462c61462784613dbc565b61460e565b613dbc565b9050919050565b5f61464282614617565b9050919050565b5f61465382614638565b9050919050565b61466381614649565b82525050565b5f60208201905061467c5f83018461465a565b92915050565b5f805f805f8060c0878903121561469c5761469b613db4565b5b5f6146a989828a01613e02565b96505060206146ba89828a01613e02565b95505060406146cb89828a01613e35565b94505060606146dc89828a01613e35565b93505060806146ed89828a01613e35565b92505060a06146fe89828a01613e35565b9150509295509295509295565b5f805f805f60a0868803121561472457614723613db4565b5b5f61473188828901613e02565b955050602061474288828901613e02565b945050604086013567ffffffffffffffff81111561476357614762613db8565b5b61476f8882890161414a565b935050606086013567ffffffffffffffff8111156147905761478f613db8565b5b61479c8882890161414a565b925050608086013567ffffffffffffffff8111156147bd576147bc613db8565b5b6147c98882890161446c565b9150509295509295909350565b5f6147e082614638565b9050919050565b6147f0816147d6565b82525050565b5f6020820190506148095f8301846147e7565b92915050565b5f6020828403121561482457614823613db4565b5b5f61483184828501614352565b91505092915050565b5f80604083850312156148505761484f613db4565b5b5f83013567ffffffffffffffff81111561486d5761486c613db8565b5b6148798582860161414a565b925050602083013567ffffffffffffffff81111561489a57614899613db8565b5b6148a6858286016142d8565b9150509250929050565b5f67ffffffffffffffff8211156148ca576148c961403b565b5b602082029050602081019050919050565b5f6148ed6148e8846148b0565b614099565b905080838252602082019050602084028301858111156149105761490f6140de565b5b835b8181101561493957806149258882613e02565b845260208401935050602081019050614912565b5050509392505050565b5f82601f83011261495757614956614037565b5b81356149678482602086016148db565b91505092915050565b5f806040838503121561498657614985613db4565b5b5f83013567ffffffffffffffff8111156149a3576149a2613db8565b5b6149af85828601614943565b925050602083013567ffffffffffffffff8111156149d0576149cf613db8565b5b6149dc8582860161414a565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b614a1881613e16565b82525050565b5f614a298383614a0f565b60208301905092915050565b5f602082019050919050565b5f614a4b826149e6565b614a5581856149f0565b9350614a6083614a00565b805f5b83811015614a90578151614a778882614a1e565b9750614a8283614a35565b925050600181019050614a63565b5085935050505092915050565b5f6020820190508181035f830152614ab58184614a41565b905092915050565b5f60208284031215614ad257614ad1613db4565b5b5f82013567ffffffffffffffff811115614aef57614aee613db8565b5b614afb84828501614225565b91505092915050565b5f614b0e82614638565b9050919050565b614b1e81614b04565b82525050565b5f602082019050614b375f830184614b15565b92915050565b5f805f60608486031215614b5457614b53613db4565b5b5f614b6186828701613e02565b935050602084013567ffffffffffffffff811115614b8257614b81613db8565b5b614b8e8682870161414a565b925050604084013567ffffffffffffffff811115614baf57614bae613db8565b5b614bbb8682870161414a565b9150509250925092565b5f805f805f60a08688031215614bde57614bdd613db4565b5b5f614beb88828901613e02565b9550506020614bfc88828901613e02565b9450506040614c0d88828901613e35565b9350506060614c1e88828901613e35565b9250506080614c2f88828901613e35565b9150509295509295909350565b5f805f8060808587031215614c5457614c53613db4565b5b5f614c6187828801613e02565b9450506020614c7287828801613e35565b9350506040614c8387828801613e35565b925050606085013567ffffffffffffffff811115614ca457614ca3613db8565b5b614cb08782880161446c565b91505092959194509250565b5f8060408385031215614cd257614cd1613db4565b5b5f614cdf85828601613e35565b9250506020614cf085828601613e35565b9150509250929050565b614d0381613ddb565b82525050565b5f602082019050614d1c5f830184614cfa565b92915050565b614d2b81613f2f565b8114614d35575f80fd5b50565b5f81359050614d4681614d22565b92915050565b5f8060408385031215614d6257614d61613db4565b5b5f614d6f85828601613e02565b9250506020614d8085828601614d38565b9150509250929050565b5f614d9482613ddb565b9050919050565b614da481614d8a565b8114614dae575f80fd5b50565b5f81359050614dbf81614d9b565b92915050565b5f8060408385031215614ddb57614dda613db4565b5b5f614de885828601614db1565b9250506020614df985828601613e35565b9150509250929050565b5f80fd5b5f8083601f840112614e1c57614e1b614037565b5b8235905067ffffffffffffffff811115614e3957614e38614e03565b5b602083019150836020820283011115614e5557614e546140de565b5b9250929050565b5f8083601f840112614e7157614e70614037565b5b8235905067ffffffffffffffff811115614e8e57614e8d614e03565b5b602083019150836001820283011115614eaa57614ea96140de565b5b9250929050565b5f805f805f805f8060a0898b031215614ecd57614ecc613db4565b5b5f614eda8b828c01613e02565b9850506020614eeb8b828c01613e02565b975050604089013567ffffffffffffffff811115614f0c57614f0b613db8565b5b614f188b828c01614e07565b9650965050606089013567ffffffffffffffff811115614f3b57614f3a613db8565b5b614f478b828c01614e07565b9450945050608089013567ffffffffffffffff811115614f6a57614f69613db8565b5b614f768b828c01614e5c565b92509250509295985092959890939650565b614f9181613eaf565b82525050565b5f602082019050614faa5f830184614f88565b92915050565b5f805f60608486031215614fc757614fc6613db4565b5b5f614fd486828701613e35565b9350506020614fe586828701613e35565b9250506040614ff686828701614352565b9150509250925092565b61500981614330565b82525050565b5f6080820190506150225f830187613e87565b61502f6020830186615000565b61503c6040830185615000565b818103606083015261504e8184613fdf565b905095945050505050565b5f806040838503121561506f5761506e613db4565b5b5f61507c85828601613e02565b925050602061508d85828601613e02565b9150509250929050565b5f805f805f8060a087890312156150b1576150b0613db4565b5b5f6150be89828a01613e02565b96505060206150cf89828a01613e02565b95505060406150e089828a01613e35565b94505060606150f189828a01613e35565b935050608087013567ffffffffffffffff81111561511257615111613db8565b5b61511e89828a01614e5c565b92509250509295509295509295565b5f805f805f60a0868803121561514657615145613db4565b5b5f61515388828901613e02565b955050602061516488828901613e02565b945050604061517588828901613e35565b935050606061518688828901613e35565b925050608086013567ffffffffffffffff8111156151a7576151a6613db8565b5b6151b38882890161446c565b9150509295509295909350565b5f602082840312156151d5576151d4613db4565b5b5f6151e284828501613e02565b91505092915050565b5f805f6060848603121561520257615201613db4565b5b5f61520f86828701613e02565b935050602061522086828701613e35565b925050604061523186828701613e35565b9150509250925092565b5f806040838503121561525157615250613db4565b5b5f61525e85828601613e35565b925050602061526f85828601614352565b9150509250929050565b5f60208201905061528c5f830184615000565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806152d657607f821691505b6020821081036152e9576152e8615292565b5b50919050565b5f81905092915050565b5f61530382613f8d565b61530d81856152ef565b935061531d818560208601613fa7565b80840191505092915050565b5f61533482856152f9565b915061534082846152f9565b91508190509392505050565b7f496e76616c6964207265717565737400000000000000000000000000000000005f82015250565b5f615380600f83613f97565b915061538b8261534c565b602082019050919050565b5f6020820190508181035f8301526153ad81615374565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20494420616c7265616479206578697374730000000000000000005f82015250565b5f615415601783613f97565b9150615420826153e1565b602082019050919050565b5f6020820190508181035f83015261544281615409565b9050919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026154a57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261546a565b6154af868361546a565b95508019841693508086168417925050509392505050565b5f6154e16154dc6154d784613e16565b61460e565b613e16565b9050919050565b5f819050919050565b6154fa836154c7565b61550e615506826154e8565b848454615476565b825550505050565b5f90565b615522615516565b61552d8184846154f1565b505050565b5b81811015615550576155455f8261551a565b600181019050615533565b5050565b601f8211156155955761556681615449565b61556f8461545b565b8101602085101561557e578190505b61559261558a8561545b565b830182615532565b50505b505050565b5f82821c905092915050565b5f6155b55f198460080261559a565b1980831691505092915050565b5f6155cd83836155a6565b9150826002028217905092915050565b6155e682613f8d565b67ffffffffffffffff8111156155ff576155fe61403b565b5b61560982546152bf565b615614828285615554565b5f60209050601f831160018114615645575f8415615633578287015190505b61563d85826155c2565b8655506156a4565b601f19841661565386615449565b5f5b8281101561567a57848901518255600182019150602085019450602081019050615655565b868310156156975784890151615693601f8916826155a6565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156e382613e16565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615715576157146156ac565b5b600182019050919050565b5f61572a82613e16565b915061573583613e16565b925082820390508181111561574d5761574c6156ac565b5b92915050565b5f8151905061576181613e1f565b92915050565b5f6020828403121561577c5761577b613db4565b5b5f61578984828501615753565b91505092915050565b5f61579c82613e16565b91506157a783613e16565b92508282019050808211156157bf576157be6156ac565b5b92915050565b5f610100820190506157d95f83018b614cfa565b6157e6602083018a614cfa565b6157f36040830189613e87565b6158006060830188613e87565b61580d6080830187613e87565b61581a60a0830186613e87565b61582760c0830185614cfa565b61583460e0830184613e87565b9998505050505050505050565b5f805f6060848603121561585857615857613db4565b5b5f61586586828701615753565b935050602061587686828701615753565b925050604061588786828701615753565b9150509250925092565b5f6040820190506158a45f830185614cfa565b6158b16020830184614cfa565b9392505050565b5f6040820190506158cb5f830185613e87565b6158d86020830184613e87565b9392505050565b5f815190506158ed81613dec565b92915050565b5f6020828403121561590857615907613db4565b5b5f615915848285016158df565b91505092915050565b5f60e0820190506159315f83018a614cfa565b61593e6020830189614cfa565b61594b6040830188613e87565b6159586060830187613e87565b6159656080830186613e87565b61597260a0830185614cfa565b61597f60c0830184613e87565b98975050505050505050565b5f80604083850312156159a1576159a0613db4565b5b5f6159ae85828601615753565b92505060206159bf85828601615753565b9150509250929050565b5f6159d382613e16565b91506159de83613e16565b92508282026159ec81613e16565b91508282048414831517615a0357615a026156ac565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615a4182613e16565b9150615a4c83613e16565b925082615a5c57615a5b615a0a565b5b828204905092915050565b5f606082019050615a7a5f830186614cfa565b615a876020830185614cfa565b615a946040830184613e87565b949350505050565b5f81519050615aaa81614d22565b92915050565b5f60208284031215615ac557615ac4613db4565b5b5f615ad284828501615a9c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b615b0d81613ddb565b82525050565b5f615b1e8383615b04565b60208301905092915050565b5f602082019050919050565b5f615b4082615adb565b615b4a8185615ae5565b9350615b5583615af5565b805f5b83811015615b85578151615b6c8882615b13565b9750615b7783615b2a565b925050600181019050615b58565b5085935050505092915050565b5f60a082019050615ba55f830188613e87565b615bb26020830187613e87565b8181036040830152615bc48186615b36565b9050615bd36060830185614cfa565b615be06080830184613e87565b9695505050505050565b5f615bfc615bf7846140b3565b614099565b90508083825260208201905060208402830185811115615c1f57615c1e6140de565b5b835b81811015615c485780615c348882615753565b845260208401935050602081019050615c21565b5050509392505050565b5f82601f830112615c6657615c65614037565b5b8151615c76848260208601615bea565b91505092915050565b5f60208284031215615c9457615c93613db4565b5b5f82015167ffffffffffffffff811115615cb157615cb0613db8565b5b615cbd84828501615c52565b91505092915050565b5f604082019050615cd95f830185614cfa565b615ce66020830184613e87565b9392505050565b5f819050919050565b5f615d10615d0b615d0684615ced565b61460e565b613e16565b9050919050565b615d2081615cf6565b82525050565b5f604082019050615d395f830185614cfa565b615d466020830184615d17565b9392505050565b5f81519050919050565b5f82825260208201905092915050565b5f615d7182615d4d565b615d7b8185615d57565b9350615d8b818560208601613fa7565b615d9481613fcf565b840191505092915050565b5f60a082019050615db25f830188614cfa565b615dbf6020830187614cfa565b615dcc6040830186613e87565b615dd96060830185613e87565b8181036080830152615deb8184615d67565b90509695505050505050565b5f81519050615e0581613eda565b92915050565b5f60208284031215615e2057615e1f613db4565b5b5f615e2d84828501615df7565b91505092915050565b5f60a082019050615e495f830188614cfa565b615e566020830187614cfa565b8181036040830152615e688186614a41565b90508181036060830152615e7c8185614a41565b90508181036080830152615e908184615d67565b90509695505050505050565b5f81905092915050565b5f615eb082615d4d565b615eba8185615e9c565b9350615eca818560208601613fa7565b80840191505092915050565b5f615ee18284615ea6565b915081905092915050565b5f608082019050615eff5f830187614cfa565b615f0c6020830186613e87565b615f196040830185613e87565b615f266060830184613e87565b95945050505050565b5f6040820190508181035f830152615f478185614a41565b90508181036020830152615f5b8184614a41565b9050939250505056fea264697066735822122051efa173c94ef6b52f8eb5e62dcf4be19b02bd8a285c990213930cb047bdb76964736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000088ee7a3537667958d040216d9dc1752d1274d838
-----Decoded View---------------
Arg [0] : _router (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [1] : _factory (address): 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
Arg [2] : _usdtToken (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [3] : _mmcToken (address): 0x88eE7a3537667958D040216D9Dc1752D1274D838
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [1] : 0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f
Arg [2] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [3] : 00000000000000000000000088ee7a3537667958d040216d9dc1752d1274d838
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.