ETH Price: $2,501.30 (-3.36%)

Token

WATER (WATER)
 

Overview

Max Total Supply

97,486,837,500,000,000,000,000,000,000,428,609.0266475 WATER

Holders

269

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
1,776 WATER

Value
$0.00
0x96CFB27C106c360692086a7Ba82ed71391a10b66
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Water

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion
File 1 of 14 : Water.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/*
    ➜ Twitter: https://x.com/WaterNodeETH
    ➜ Gitbook: https://docs.waternode.io/
    ➜ Website: https://waternode.io/
    ➜ Portal: https://t.me/WaterNodeETH
    ➜ DAPP: https://app.waternode.io/
*/

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./interfaces/IRouter.sol";
import "./interfaces/IPair.sol";
import "./interfaces/IFactory.sol";

contract Water is ERC20, Ownable, ReentrancyGuard {

    // user data structure for storing nodes number, claiming rewards and cases bought
    struct UserData {
        uint nodesNumber;
        uint lastClaimTimestamp;
        uint[] boughtCasesIds;
    }

    bool public tokenCasesAllowed; // true if cases are allowed to be bought with token
    bool public ethCasesAllowed; // true if cases are allowed to be bought with eth
    bool swapping; // prevent fees / swapping when contract is already swapping tokens
    bool tokenLaunched; // is token already launched
    bool shouldBuyBack = true; // true if contract is automatically buying back
    bool shouldSellFees = true; // true if contract is automatically selling tokens fees

    uint public launchTimestamp; // contract launch timestamp in seconds
    uint public casesBought; // keep track of cases bought to have unique id per case
    uint public totalNodes; // number of nodes minted

    // contract parameters

    uint public nodesRewardsRate = 100_000; // rate of reward per day per node (in DECIMALS) (10%)
    uint public ethNodesDiscount = 50_000; // discount of buying a node with eth (in DECIMALS) (5%)
    uint public caseOpenDelay = 1; // block required for a case to be claimable
    uint public minSwapTokenAmount = 1e18; // minimum amount of token required to swap (sell fees)
    uint public minSwapEthAmount = 1e16; // minimum amount of eth required to swap (buy back)

    // contract constants

    uint public constant NODE_TOKEN_PRICE = 50e18; // fixed case price in WATER token

    uint private constant DECIMALS = 1_000_000; // base decimals amount used by the contract values

    uint private constant TOTAL_SUPPLY = 444_000e18;
    uint private constant LIMITS_PERIOD = 120; // time in seconds during which max wallet is active
    uint private constant MAX_WALLET_AMOUNT = (TOTAL_SUPPLY * 5) / 100; // maximum token per wallet during limits period (5%)

    uint private constant CLAIM_FEES = 50_000; // claim fees (in DECIMALS) (5%)
    // swap fees during each successive periods (high fees, then medium fees, then low fees) (in DECIMALS) (30% - 10% - 3%)
    uint private constant HIGH_FEES = 180_000; 
    uint private constant MEDIUM_FEES = 100_000;
    uint private constant LOW_FEES = 30_000;
    uint private constant HIGH_FEES_PERIOD = 180; // 3 minutes duration
    uint private constant MEDIUM_FEES_PERIOD = 360; // 3 minutes duration

    address private constant BURN = 0x000000000000000000000000000000000000dEaD;
    address private immutable WETH;
    IRouter private immutable ROUTER;
    address public immutable pair;

    address payable public feesReceiver;

    mapping(address => UserData) public usersDatas; // store users data (nodes, claims, cases)
    mapping(uint => uint) public casesClaimableBlock; // minimum claimable block number per case id
    mapping(address => bool) public isFeesExempt; // store all fees exempted addresses

    event CaseBought(address indexed user, uint amount, bool inToken);
    event CaseOpened(address indexed user, uint nodesAmount);

    constructor(address _WETH, address _ROUTER) ERC20("WATER", "WATER") Ownable(msg.sender) {
        WETH = _WETH;
        ROUTER = IRouter(_ROUTER);
        
        pair = IFactory(ROUTER.factory()).createPair(
            address(this),
            WETH
        );

        feesReceiver = payable(msg.sender);

        isFeesExempt[address(this)] = true;
        isFeesExempt[msg.sender] = true;

        uint teamSupply = TOTAL_SUPPLY / 10;
        _mint(address(this), TOTAL_SUPPLY - teamSupply);
        _mint(msg.sender, teamSupply);
    }

    /// @dev prevent fees / swapping during swap by the contract
    modifier Swapping() {
        swapping = true;
        _;
        swapping = false;
    } 

    /// @dev add liquidity to the pool
    function launch() external payable onlyOwner Swapping {
        require(!tokenLaunched, "Token launched");
        tokenLaunched = true;
        launchTimestamp = block.timestamp;

        uint liqAmount = (balanceOf(address(this)) * 85) / 100;
        _approve(address(this), address(ROUTER), liqAmount);
        ROUTER.addLiquidityETH{value: address(this).balance}(address(this), liqAmount, 0, 0, msg.sender, block.timestamp); 
    }

    // CONTRACT PARAMETERS SETTER FUNCTIONS

    function setNumericParameter(uint _nodesRewardsRate, uint _caseOpenDelay, uint _ethNodesDiscount, uint _minSwapTokenAmount, uint _minSwapEthAmount) external onlyOwner {
        require(_nodesRewardsRate <= 300_000); // max 30% daily reward rate
        nodesRewardsRate = _nodesRewardsRate;

        require(_caseOpenDelay <= 30); // max 30 block delay after buy
        caseOpenDelay = _caseOpenDelay;

        require(_ethNodesDiscount <= 300_000); // max 30% eth discount
        ethNodesDiscount = _ethNodesDiscount;

        minSwapTokenAmount = _minSwapTokenAmount;
        minSwapEthAmount = _minSwapEthAmount;
    }

    function setContractSwaps(bool _shouldBuyBack, bool _shouldSellFees) external onlyOwner {
        shouldBuyBack = _shouldBuyBack;
        shouldSellFees = _shouldSellFees;
    }

    function setCasesAllowed(bool _tokenCases, bool _state) external onlyOwner {
        if (_tokenCases) tokenCasesAllowed = _state;
        else ethCasesAllowed = _state;
    }

    function setFeesExempted(address _account, bool _state) external onlyOwner {
        isFeesExempt[_account] = _state;
    }

    function setFeesReceiver(address _feesReceiver) external {
        require(feesReceiver == msg.sender);
        feesReceiver = payable(_feesReceiver);
    }

    /// @dev buy desired amount of cases with WATER tokens at a fixed price
    function buyCasesWater(uint _amount) external nonReentrant {
        require(tokenCasesAllowed, "Token cases disabled now");

        uint price = NODE_TOKEN_PRICE * _amount;
        _burn(msg.sender, price); // burn 100% of the price

        _buyCases(_amount);
        emit CaseBought(msg.sender, _amount, true);
    }

    /// @dev buy desired amount of cases with etheureum at a fixed price
    function buyCasesETH(uint _amount) external payable nonReentrant {
        require(ethCasesAllowed, "ETH cases disabled now");

        uint price = getCasePriceETH(_amount);
        require(msg.value >= price, "Not enough eth to pay");
        
        uint feesToDev = (msg.value * 15) / 100;

        (bool sent, ) = feesReceiver.call{value: feesToDev}("");
        require(sent);

        if (shouldBuyBack) _buyBack(); // buy back tokens with all ether amount of the contract (including the 85% of msg.value left)
        _buyCases(_amount);
        emit CaseBought(msg.sender, _amount, false);
    }

    /// @dev user version of _claimRewards with reentrancy guard
    function claimRewards() external nonReentrant {
        _claimRewards(msg.sender);
    }

    /// @dev directly buy nodes with rewards tokens (fees-free) (it is flooring the number of nodes)
    function compound() external nonReentrant {
        uint rewards = getNodesRewards(msg.sender);
        // do not apply claim fees here as it is a compound
        
        uint nodesAmount = rewards / NODE_TOKEN_PRICE;
        if (nodesAmount == 0) return; // if there is not enough reward to buy even 1 node, just return

        usersDatas[msg.sender].lastClaimTimestamp = block.timestamp; // set user rewards to 0

        _mintNodes(msg.sender, nodesAmount, false);
    }

    /// @dev open all claimable cases, mint earned nodes + 1 per deprecated case and ignore unclaimable cases
    function openAllCases() external nonReentrant returns (uint nodesToMint) {
        uint maxBlockNumber = block.number;
        uint minBlockNumber = block.number - 256;

        address sender = msg.sender;

        uint i = 0;
        while (i < usersDatas[sender].boughtCasesIds.length) {
            uint caseId = usersDatas[sender].boughtCasesIds[i];
            uint claimBlockNb = casesClaimableBlock[caseId];

            // first case is that the case is either claimable or deprecated (but can't be claimable in the future)
            if (claimBlockNb < maxBlockNumber) {
                // if the case is claimable (within the bounds of cases claimability), mint node
                if (claimBlockNb > minBlockNumber) nodesToMint += _getCaseNodesNumber(claimBlockNb, caseId, sender); 
                // else, the case is deprecated because of block number being too late (more or equal to 256 blocks after claiamble block), we mint 1 node
                else nodesToMint++;

                // for both case, we remove the case id from bought cases
                _removeFromBoughtCases(sender, i);
            }
            // else, it means the case is not claimable yet, it is saved (not deleted from boughtCases) and we pass to the next one
            else i++;
        }

        emit CaseOpened(msg.sender, nodesToMint);
        if (nodesToMint > 0) _mintNodes(msg.sender, nodesToMint, true); // mint nodes (rewarded / claimed + 1 node per deprecated cases)
    }

    /// @dev open one case using its index in bought cases list (mint 1 node if deprecated and revert if not claimable yet)
    function openCase(uint _boughtCasesIndex) external nonReentrant returns (uint nodesToMint) {
        uint caseId = usersDatas[msg.sender].boughtCasesIds[_boughtCasesIndex];
        uint claimBlockNb = casesClaimableBlock[caseId];

        require(claimBlockNb < block.number, "Not claimable yet");

        _removeFromBoughtCases(msg.sender, _boughtCasesIndex);
            
        // if the case is claimable (within the bounds of cases claimability), mint nodes
        if (claimBlockNb > block.number - 256) nodesToMint = _getCaseNodesNumber(claimBlockNb, caseId, msg.sender);
        // else, the case is deprecated because of block number being too late, we mint 1 node
        else nodesToMint = 1;

        emit CaseOpened(msg.sender, nodesToMint);
        _mintNodes(msg.sender, nodesToMint, true);
    }
    
    /// @dev internal function managing core operation for buying cases (not the payment)
    function _buyCases(uint _amount) private {
        uint claimableBlock = block.number + caseOpenDelay; // claimable block of all cases bought during this tx

        for (uint i = 0; i < _amount; i++) {
            usersDatas[msg.sender].boughtCasesIds.push(casesBought);
            casesClaimableBlock[casesBought] = claimableBlock;

            casesBought++;
        }
    }

    /// @dev internal function managing core operation for minting nodes
    function _mintNodes(address _account, uint _amount, bool _doClaimRewards) private {
        if (_doClaimRewards) _claimRewards(_account);

        totalNodes += _amount;

        usersDatas[_account].nodesNumber += _amount;
    }

    /// @dev claim rewards from node
    function _claimRewards(address _account) private {
        uint rewards = getNodesRewards(_account);
        uint fees = (rewards * CLAIM_FEES) / DECIMALS; // get total fees from claiming

        if (rewards != 0) {
            _mint(_account, rewards - fees); // mint rewards to the user with fees incurred
            _mint(address(this), fees / 2); // half of the fees go into this contract for the devs
            // the other half of the fees is being burned (<=> not minted)
        }

        usersDatas[_account].lastClaimTimestamp = block.timestamp;
    }

    function _removeFromBoughtCases(address _account, uint _id) internal {
        usersDatas[_account].boughtCasesIds[_id] = usersDatas[_account].boughtCasesIds[usersDatas[_account].boughtCasesIds.length - 1];
        usersDatas[_account].boughtCasesIds.pop();
    }

    function _getCaseNodesNumber(uint _claimBlockNb, uint _caseId, address _sender) private view returns (uint) {
        uint seed = (uint(keccak256(abi.encodePacked(blockhash(_claimBlockNb), _caseId, _sender))) % 100) + 1;

        if (seed <= 5) return 3;
        if (seed <= 20) return 2;
        return 1;
    }

    /// @dev get current total rewards (no fees included)
    function getNodesRewards(address _account) public view returns (uint) {
        uint nodesNumber = usersDatas[_account].nodesNumber;
        uint lastClaimTimestamp = usersDatas[_account].lastClaimTimestamp;

        uint totalTokensInNodes = NODE_TOKEN_PRICE * nodesNumber;
        uint rewardsPercentage = ((block.timestamp - lastClaimTimestamp) * nodesRewardsRate) / 1 days; // percentage of rewards of the total tokens (IN DECIMALS)

        return (totalTokensInNodes * rewardsPercentage) / DECIMALS;
    }

    /// @dev return the price in eth (wei) to buy an amount of cases (with a discount)
    function getCasePriceETH(uint _amount) public view returns (uint) {
        uint discountMultiplier = DECIMALS - ethNodesDiscount;

        (uint reserve0, uint reserve1, ) = IPair(pair).getReserves();
        require(reserve0 > 0 && reserve1 > 0, "No reserve");
        if (IPair(pair).token0() != WETH) (reserve0, reserve1) = (reserve1, reserve0);

        uint tokenPriceWEI = (reserve0 * 1e18) / reserve1;
        require(tokenPriceWEI != 0, "Invalid price");
        
        uint nodeFullPriceWEI = (NODE_TOKEN_PRICE * tokenPriceWEI) / 1e18;
        uint finalPrice = (nodeFullPriceWEI * discountMultiplier) / DECIMALS;
        return finalPrice * _amount;
    }

    function getOwnedCases(address _account) external view returns (uint[] memory) {
        return usersDatas[_account].boughtCasesIds;
    }

    /// @dev buy back tokens with contract balance
    function _buyBack() internal Swapping {
        if (address(this).balance < minSwapEthAmount) return;

        address[] memory path = new address[](2);
        path[0] = WETH;
        path[1] = address(this);

        ROUTER.swapExactETHForTokensSupportingFeeOnTransferTokens{value: address(this).balance}(
            0,
            path,
            BURN,
            block.timestamp + 1
        );

        _burn(BURN, balanceOf(BURN)); // burn all tokens received by BURN address
    }

    /// @dev sell tokens fees in the contract for eth
    function _sellFees(uint maxAmount) internal Swapping {
        uint256 balance = min(maxAmount, balanceOf(address(this)));
        if (balance < minSwapTokenAmount) return;

        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = WETH;

        _approve(address(this), address(ROUTER), type(uint256).max, false);
        ROUTER.swapExactTokensForETHSupportingFeeOnTransferTokens(
            balance,
            0,
            path,
            feesReceiver,
            block.timestamp
        );
    }

    /// @dev retreive eth or tokens funds (so in case buy back or sell fees are desactivated for any reasons, funds are not lost)
    function retreiveFunds(bool _eth) external onlyOwner Swapping {
        require(!shouldBuyBack || !shouldSellFees);

        if (_eth) {
            (bool sent, ) = feesReceiver.call{value: address(this).balance}("");
            require(sent);
        } else {
            transfer(feesReceiver, balanceOf(address(this)));
        }
    }

    /// @dev refund nodes from potential issues / offer some giveaway
    function awardNodes(address _account, uint _amount, bool _doClaimRewards) external onlyOwner {
        _mintNodes(_account, _amount, _doClaimRewards);
    }

    function _update(address from, address to, uint256 value) internal override {
        if (isFeesExempt[from] || isFeesExempt[to] || swapping) return super._update(from, to, value);

        // take fees if it is a swap
        bool takeFees = from == pair || to == pair;
        uint fees = takeFees ? (value * getFees()) / DECIMALS : 0;

        if (fees > 0) super._update(from, address(this), fees);
        value -= fees;

        // check for limits
        if (limitsActive() && to != pair && to != address(ROUTER)) {
            require(balanceOf(to) + value <= MAX_WALLET_AMOUNT, "Maximum token per wallet reached");
        }

        // sell fees
        if (shouldSellFees && from != pair) _sellFees(value);

        super._update(from, to, value);
    }

    function getFees() private view returns (uint) {
        uint elapsed = block.timestamp - launchTimestamp;
        if (elapsed > MEDIUM_FEES_PERIOD) return LOW_FEES;
        if (elapsed > HIGH_FEES_PERIOD) return MEDIUM_FEES;
        return HIGH_FEES;
    }

    function limitsActive() private view returns (bool) {
        return block.timestamp - launchTimestamp <= LIMITS_PERIOD;
    }

    function min(uint a, uint b) private pure returns (uint) {
        return a < b ? a : b;
    }

    receive() external payable {}
}

File 2 of 14 : Ownable.sol
// 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);
    }
}

File 3 of 14 : draft-IERC6093.sol
// 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);
}

File 4 of 14 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 5 of 14 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 6 of 14 : IERC20Permit.sol
// 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);
}

File 7 of 14 : IERC20.sol
// 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);
}

File 8 of 14 : SafeERC20.sol
// 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;
    }
}

File 9 of 14 : Address.sol
// 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();
        }
    }
}

File 10 of 14 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 11 of 14 : ReentrancyGuard.sol
// 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;
    }
}

File 12 of 14 : IFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IFactory {
    function createPair(
        address tokenA,
        address tokenB
    ) external returns (address pair);
}

File 13 of 14 : IPair.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IPair {
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}

File 14 of 14 : IRouter.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IRouter {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        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 addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_ROUTER","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inToken","type":"bool"}],"name":"CaseBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"nodesAmount","type":"uint256"}],"name":"CaseOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"NODE_TOKEN_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_doClaimRewards","type":"bool"}],"name":"awardNodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buyCasesETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buyCasesWater","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"caseOpenDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"casesBought","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"casesClaimableBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethCasesAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethNodesDiscount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesReceiver","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getCasePriceETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getNodesRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getOwnedCases","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFeesExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"launchTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwapEthAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwapTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodesRewardsRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openAllCases","outputs":[{"internalType":"uint256","name":"nodesToMint","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_boughtCasesIndex","type":"uint256"}],"name":"openCase","outputs":[{"internalType":"uint256","name":"nodesToMint","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_eth","type":"bool"}],"name":"retreiveFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_tokenCases","type":"bool"},{"internalType":"bool","name":"_state","type":"bool"}],"name":"setCasesAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldBuyBack","type":"bool"},{"internalType":"bool","name":"_shouldSellFees","type":"bool"}],"name":"setContractSwaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_state","type":"bool"}],"name":"setFeesExempted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feesReceiver","type":"address"}],"name":"setFeesReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nodesRewardsRate","type":"uint256"},{"internalType":"uint256","name":"_caseOpenDelay","type":"uint256"},{"internalType":"uint256","name":"_ethNodesDiscount","type":"uint256"},{"internalType":"uint256","name":"_minSwapTokenAmount","type":"uint256"},{"internalType":"uint256","name":"_minSwapEthAmount","type":"uint256"}],"name":"setNumericParameter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCasesAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNodes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersDatas","outputs":[{"internalType":"uint256","name":"nodesNumber","type":"uint256"},{"internalType":"uint256","name":"lastClaimTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e06040526001600760046101000a81548160ff0219169083151502179055506001600760056101000a81548160ff021916908315150217905550620186a0600b5561c350600c556001600d55670de0b6b3a7640000600e55662386f26fc10000600f553480156200007057600080fd5b5060405162005eef38038062005eef8339818101604052810190620000969190620010be565b336040518060400160405280600581526020017f57415445520000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f574154455200000000000000000000000000000000000000000000000000000081525081600390816200011491906200137f565b5080600490816200012691906200137f565b505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200019e5760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040162000195919062001477565b60405180910390fd5b620001af816200049d60201b60201c565b5060016006819055508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505060a05173ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000294919062001494565b73ffffffffffffffffffffffffffffffffffffffff1663c9c65396306080516040518363ffffffff1660e01b8152600401620002d2929190620014c6565b6020604051808303816000875af1158015620002f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000318919062001494565b73ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff168152505033601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001601360003073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001601360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600a695e0549c9632e1d80000062000457919062001551565b9050620004823082695e0549c9632e1d80000062000476919062001589565b6200056360201b60201c565b6200049433826200056360201b60201c565b5050506200193d565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620005d85760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401620005cf919062001477565b60405180910390fd5b620005ec60008383620005f060201b60201c565b5050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680620006925750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80620006aa5750600760029054906101000a900460ff165b15620006c957620006c38383836200093960201b60201c565b62000934565b600060c05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148062000735575060c05173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b90506000816200074757600062000775565b620f42406200075b62000b6960201b60201c565b84620007689190620015c4565b62000774919062001551565b5b905060008111156200079557620007948530836200093960201b60201c565b5b8083620007a3919062001589565b9250620007b562000bb760201b60201c565b8015620007f0575060c05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b80156200082b575060a05173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15620008bb5760646005695e0549c9632e1d8000006200084c9190620015c4565b62000858919062001551565b836200086a8662000bd260201b60201c565b6200087691906200160f565b1115620008ba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008b190620016ab565b60405180910390fd5b5b600760059054906101000a900460ff16801562000906575060c05173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b156200091e576200091d8362000c1a60201b60201c565b5b620009318585856200093960201b60201c565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200098f5780600260008282546200098291906200160f565b9250508190555062000a65565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101562000a1e578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040162000a1593929190620016de565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000ab0578060026000828254039250508190555062000afd565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405162000b5c91906200171b565b60405180910390a3505050565b6000806008544262000b7c919062001589565b905061016881111562000b955761753091505062000bb4565b60b481111562000bac57620186a091505062000bb4565b6202bf209150505b90565b600060786008544262000bcb919062001589565b1115905090565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6001600760026101000a81548160ff021916908315150217905550600062000c598262000c4d3062000bd260201b60201c565b62000e5960201b60201c565b9050600e5481101562000c6d575062000e3b565b6000600267ffffffffffffffff81111562000c8d5762000c8c62001110565b5b60405190808252806020026020018201604052801562000cbc5781602001602082028036833780820191505090505b509050308160008151811062000cd75762000cd662001738565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506080518160018151811062000d2b5762000d2a62001738565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505062000d9c3060a0517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600062000e7460201b60201c565b60a05173ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040162000e04959493929190620018d9565b600060405180830381600087803b15801562000e1f57600080fd5b505af115801562000e34573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831062000e6a578162000e6c565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160362000ee95760006040517fe602df0500000000000000000000000000000000000000000000000000000000815260040162000ee0919062001477565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000f5e5760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040162000f55919062001477565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156200104e578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516200104591906200171b565b60405180910390a35b50505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620010868262001059565b9050919050565b620010988162001079565b8114620010a457600080fd5b50565b600081519050620010b8816200108d565b92915050565b60008060408385031215620010d857620010d762001054565b5b6000620010e885828601620010a7565b9250506020620010fb85828601620010a7565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200118757607f821691505b6020821081036200119d576200119c6200113f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620012077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620011c8565b620012138683620011c8565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620012606200125a62001254846200122b565b62001235565b6200122b565b9050919050565b6000819050919050565b6200127c836200123f565b620012946200128b8262001267565b848454620011d5565b825550505050565b600090565b620012ab6200129c565b620012b881848462001271565b505050565b5b81811015620012e057620012d4600082620012a1565b600181019050620012be565b5050565b601f8211156200132f57620012f981620011a3565b6200130484620011b8565b8101602085101562001314578190505b6200132c6200132385620011b8565b830182620012bd565b50505b505050565b600082821c905092915050565b6000620013546000198460080262001334565b1980831691505092915050565b60006200136f838362001341565b9150826002028217905092915050565b6200138a8262001105565b67ffffffffffffffff811115620013a657620013a562001110565b5b620013b282546200116e565b620013bf828285620012e4565b600060209050601f831160018114620013f75760008415620013e2578287015190505b620013ee858262001361565b8655506200145e565b601f1984166200140786620011a3565b60005b8281101562001431578489015182556001820191506020850194506020810190506200140a565b868310156200145157848901516200144d601f89168262001341565b8355505b6001600288020188555050505b505050505050565b620014718162001079565b82525050565b60006020820190506200148e600083018462001466565b92915050565b600060208284031215620014ad57620014ac62001054565b5b6000620014bd84828501620010a7565b91505092915050565b6000604082019050620014dd600083018562001466565b620014ec602083018462001466565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200155e826200122b565b91506200156b836200122b565b9250826200157e576200157d620014f3565b5b828204905092915050565b600062001596826200122b565b9150620015a3836200122b565b9250828203905081811115620015be57620015bd62001522565b5b92915050565b6000620015d1826200122b565b9150620015de836200122b565b9250828202620015ee816200122b565b9150828204841483151762001608576200160762001522565b5b5092915050565b60006200161c826200122b565b915062001629836200122b565b925082820190508082111562001644576200164362001522565b5b92915050565b600082825260208201905092915050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b6000620016936020836200164a565b9150620016a0826200165b565b602082019050919050565b60006020820190508181036000830152620016c68162001684565b9050919050565b620016d8816200122b565b82525050565b6000606082019050620016f5600083018662001466565b620017046020830185620016cd565b620017136040830184620016cd565b949350505050565b6000602082019050620017326000830184620016cd565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b6000620017926200178c620017868462001767565b62001235565b6200122b565b9050919050565b620017a48162001771565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b620017e18162001079565b82525050565b6000620017f58383620017d6565b60208301905092915050565b6000602082019050919050565b60006200181b82620017aa565b620018278185620017b5565b93506200183483620017c6565b8060005b838110156200186b5781516200184f8882620017e7565b97506200185c8362001801565b92505060018101905062001838565b5085935050505092915050565b600062001899620018936200188d8462001059565b62001235565b62001059565b9050919050565b6000620018ad8262001878565b9050919050565b6000620018c182620018a0565b9050919050565b620018d381620018b4565b82525050565b600060a082019050620018f06000830188620016cd565b620018ff602083018762001799565b81810360408301526200191381866200180e565b9050620019246060830185620018c8565b620019336080830184620016cd565b9695505050505050565b60805160a05160c051614527620019c8600039600081816115b7015281816116f1015281816119cb01528181612b2c01528181612b8101528181612c370152612d75015260008181610b2c01528181610b53015281816120d501528181612c8f01528181613241015261328a0152600081816116ba0152818161201701526131ce01526145276000f3fe6080604052600436106102765760003560e01c80637ab18aad1161014f578063bca93cf5116100c1578063df5fef921161007a578063df5fef9214610984578063ead267e7146109ad578063f18e7951146109d8578063f2fde38b14610a01578063f69e204614610a2a578063f906b61814610a415761027d565b8063bca93cf514610850578063c40d24b21461087b578063c92f69a9146108b8578063cc66ccea146108e1578063d58a90a71461091e578063dd62ed3e146109475761027d565b80639592d424116101135780639592d4241461072a57806395d89b4114610755578063a8aa1b3114610780578063a9059cbb146107ab578063aa3164c4146107e8578063b865e5d9146108255761027d565b80637ab18aad1461061c5780637d6731701461065a578063846f299e146106855780638da5cb5b146106c2578063946da64e146106ed5761027d565b8063328881df116101e85780635055c413116101ac5780635055c4131461051c5780636182d05d1461054757806365cf7c9b1461057257806367c7f5951461059d57806370a08231146105c8578063715018a6146106055761027d565b8063328881df1461045d5780633688555614610486578063372500ab146104af5780633c6ece75146104c6578063489f91d6146104f15761027d565b806317ed9d9d1161023a57806317ed9d9d1461033957806318160ddd146103645780631ae483b61461038f5780632073b17c146103b857806323b872dd146103f5578063313ce567146104325761027d565b806301339c211461028257806302f729b81461028c57806306fdde03146102b5578063095ea7b3146102e05780630c7c5c2a1461031d5761027d565b3661027d57005b600080fd5b61028a610a6c565b005b34801561029857600080fd5b506102b360048036038101906102ae91906133b3565b610c1a565b005b3480156102c157600080fd5b506102ca610c7a565b6040516102d791906134be565b60405180910390f35b3480156102ec57600080fd5b506103076004803603810190610302919061353e565b610d0c565b6040516103149190613599565b60405180910390f35b610337600480360381019061033291906135b4565b610d2f565b005b34801561034557600080fd5b5061034e610f11565b60405161035b91906135f0565b60405180910390f35b34801561037057600080fd5b50610379610f1e565b60405161038691906135f0565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190613637565b610f28565b005b3480156103c457600080fd5b506103df60048036038101906103da91906135b4565b611075565b6040516103ec91906135f0565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190613664565b6111db565b6040516104299190613599565b60405180910390f35b34801561043e57600080fd5b5061044761120a565b60405161045491906136d3565b60405180910390f35b34801561046957600080fd5b50610484600480360381019061047f91906136ee565b611213565b005b34801561049257600080fd5b506104ad60048036038101906104a891906135b4565b61122b565b005b3480156104bb57600080fd5b506104c461130b565b005b3480156104d257600080fd5b506104db611326565b6040516104e891906135f0565b60405180910390f35b3480156104fd57600080fd5b5061050661132c565b60405161051391906135f0565b60405180910390f35b34801561052857600080fd5b50610531611332565b60405161053e9190613599565b60405180910390f35b34801561055357600080fd5b5061055c611345565b60405161056991906135f0565b60405180910390f35b34801561057e57600080fd5b5061058761150a565b60405161059491906135f0565b60405180910390f35b3480156105a957600080fd5b506105b2611510565b6040516105bf91906135f0565b60405180910390f35b3480156105d457600080fd5b506105ef60048036038101906105ea9190613741565b611516565b6040516105fc91906135f0565b60405180910390f35b34801561061157600080fd5b5061061a61155e565b005b34801561062857600080fd5b50610643600480360381019061063e9190613741565b611572565b60405161065192919061376e565b60405180910390f35b34801561066657600080fd5b5061066f611596565b60405161067c91906135f0565b60405180910390f35b34801561069157600080fd5b506106ac60048036038101906106a791906135b4565b61159c565b6040516106b991906135f0565b60405180910390f35b3480156106ce57600080fd5b506106d761186d565b6040516106e491906137a6565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190613741565b611897565b604051610721919061387f565b60405180910390f35b34801561073657600080fd5b5061073f611931565b60405161074c91906135f0565b60405180910390f35b34801561076157600080fd5b5061076a611937565b60405161077791906134be565b60405180910390f35b34801561078c57600080fd5b506107956119c9565b6040516107a291906137a6565b60405180910390f35b3480156107b757600080fd5b506107d260048036038101906107cd919061353e565b6119ed565b6040516107df9190613599565b60405180910390f35b3480156107f457600080fd5b5061080f600480360381019061080a91906135b4565b611a10565b60405161081c91906135f0565b60405180910390f35b34801561083157600080fd5b5061083a611a28565b60405161084791906135f0565b60405180910390f35b34801561085c57600080fd5b50610865611a2e565b60405161087291906138c2565b60405180910390f35b34801561088757600080fd5b506108a2600480360381019061089d9190613741565b611a54565b6040516108af9190613599565b60405180910390f35b3480156108c457600080fd5b506108df60048036038101906108da91906138dd565b611a74565b005b3480156108ed57600080fd5b5061090860048036038101906109039190613741565b611ad7565b60405161091591906135f0565b60405180910390f35b34801561092a57600080fd5b506109456004803603810190610940919061391d565b611bcf565b005b34801561095357600080fd5b5061096e6004803603810190610969919061395d565b611c0f565b60405161097b91906135f0565b60405180910390f35b34801561099057600080fd5b506109ab60048036038101906109a6919061391d565b611c96565b005b3480156109b957600080fd5b506109c2611ce2565b6040516109cf91906135f0565b60405180910390f35b3480156109e457600080fd5b506109ff60048036038101906109fa9190613741565b611ce8565b005b348015610a0d57600080fd5b50610a286004803603810190610a239190613741565b611d86565b005b348015610a3657600080fd5b50610a3f611e0c565b005b348015610a4d57600080fd5b50610a56611ea9565b604051610a639190613599565b60405180910390f35b610a74611ebc565b6001600760026101000a81548160ff021916908315150217905550600760039054906101000a900460ff1615610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad6906139e9565b60405180910390fd5b6001600760036101000a81548160ff02191690831515021790555042600881905550600060646055610b1030611516565b610b1a9190613a38565b610b249190613aa9565b9050610b51307f000000000000000000000000000000000000000000000000000000000000000083611f43565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f305d71947308460008033426040518863ffffffff1660e01b8152600401610bb696959493929190613b1f565b60606040518083038185885af1158015610bd4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610bf99190613b95565b505050506000600760026101000a81548160ff021916908315150217905550565b610c22611ebc565b620493e0851115610c3257600080fd5b84600b81905550601e841115610c4757600080fd5b83600d81905550620493e0831115610c5e57600080fd5b82600c8190555081600e8190555080600f819055505050505050565b606060038054610c8990613c17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590613c17565b8015610d025780601f10610cd757610100808354040283529160200191610d02565b820191906000526020600020905b815481529060010190602001808311610ce557829003601f168201915b5050505050905090565b600080610d17611f55565b9050610d24818585611f43565b600191505092915050565b610d37611f5d565b600760019054906101000a900460ff16610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90613c94565b60405180910390fd5b6000610d918261159c565b905080341015610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd90613d00565b60405180910390fd5b60006064600f34610de79190613a38565b610df19190613aa9565b90506000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682604051610e3b90613d51565b60006040518083038185875af1925050503d8060008114610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b5050905080610e8b57600080fd5b600760049054906101000a900460ff1615610ea957610ea8611fa3565b5b610eb2846121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c7716856000604051610efb929190613d66565b60405180910390a2505050610f0e61227b565b50565b6802b5e3af16b188000081565b6000600254905090565b610f30611ebc565b6001600760026101000a81548160ff021916908315150217905550600760049054906101000a900460ff161580610f745750600760059054906101000a900460ff16155b610f7d57600080fd5b8015611021576000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1647604051610fcb90613d51565b60006040518083038185875af1925050503d8060008114611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b505090508061101b57600080fd5b50611057565b611055601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661105030611516565b6119ed565b505b6000600760026101000a81548160ff02191690831515021790555050565b600061107f611f5d565b6000601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020183815481106110d5576110d4613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905043811061113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113390613e0a565b60405180910390fd5b6111463385612285565b610100436111549190613e2a565b81111561116d57611166818333612403565b9250611172565b600192505b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc846040516111b891906135f0565b60405180910390a26111cc33846001612480565b50506111d661227b565b919050565b6000806111e6611f55565b90506111f3858285612507565b6111fe85858561259b565b60019150509392505050565b60006012905090565b61121b611ebc565b611226838383612480565b505050565b611233611f5d565b600760009054906101000a900460ff16611282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127990613eaa565b60405180910390fd5b6000816802b5e3af16b18800006112999190613a38565b90506112a5338261268f565b6112ae826121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c77168360016040516112f7929190613d66565b60405180910390a25061130861227b565b50565b611313611f5d565b61131c33612711565b61132461227b565b565b600f5481565b60095481565b600760019054906101000a900460ff1681565b600061134f611f5d565b60004390506000610100436113649190613e2a565b9050600033905060005b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180549050811015611497576000601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061141157611410613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905085811015611481578481111561146357611451818386612403565b8761145c9190613eca565b9650611472565b868061146e90613efe565b9750505b61147c8484612285565b611490565b828061148c90613efe565b9350505b505061136e565b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc866040516114dd91906135f0565b60405180910390a260008511156114fb576114fa33866001612480565b5b5050505061150761227b565b90565b60085481565b600c5481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611566611ebc565b61157060006127be565b565b60116020528060005260406000206000915090508060000154908060010154905082565b600e5481565b600080600c54620f42406115b09190613e2a565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190613fc8565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156116795750600081115b6116b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116af90614067565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177e919061409c565b73ffffffffffffffffffffffffffffffffffffffff16146117a457808280925081935050505b600081670de0b6b3a7640000846117bb9190613a38565b6117c59190613aa9565b90506000810361180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190614115565b60405180910390fd5b6000670de0b6b3a7640000826802b5e3af16b188000061182a9190613a38565b6118349190613aa9565b90506000620f424086836118489190613a38565b6118529190613aa9565b905087816118609190613a38565b9650505050505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180548060200260200160405190810160405280929190818152602001828054801561192557602002820191906000526020600020905b815481526020019060010190808311611911575b50505050509050919050565b600a5481565b60606004805461194690613c17565b80601f016020809104026020016040519081016040528092919081815260200182805461197290613c17565b80156119bf5780601f10611994576101008083540402835291602001916119bf565b820191906000526020600020905b8154815290600101906020018083116119a257829003601f168201915b5050505050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806119f8611f55565b9050611a0581858561259b565b600191505092915050565b60126020528060005260406000206000915090505481565b600d5481565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60136020528060005260406000206000915054906101000a900460ff1681565b611a7c611ebc565b80601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490506000826802b5e3af16b1880000611b7d9190613a38565b9050600062015180600b548442611b949190613e2a565b611b9e9190613a38565b611ba89190613aa9565b9050620f42408183611bba9190613a38565b611bc49190613aa9565b945050505050919050565b611bd7611ebc565b81600760046101000a81548160ff02191690831515021790555080600760056101000a81548160ff0219169083151502179055505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611c9e611ebc565b8115611cc35780600760006101000a81548160ff021916908315150217905550611cde565b80600760016101000a81548160ff0219169083151502179055505b5050565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d4257600080fd5b80601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d8e611ebc565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e005760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611df791906137a6565b60405180910390fd5b611e09816127be565b50565b611e14611f5d565b6000611e1f33611ad7565b905060006802b5e3af16b188000082611e389190613aa9565b905060008103611e49575050611e9f565b42601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550611e9c33826000612480565b50505b611ea761227b565b565b600760009054906101000a900460ff1681565b611ec4611f55565b73ffffffffffffffffffffffffffffffffffffffff16611ee261186d565b73ffffffffffffffffffffffffffffffffffffffff1614611f4157611f05611f55565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f3891906137a6565b60405180910390fd5b565b611f508383836001612884565b505050565b600033905090565b600260065403611f99576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6001600760026101000a81548160ff021916908315150217905550600f54471061218c576000600267ffffffffffffffff811115611fe457611fe3614135565b5b6040519080825280602002602001820160405280156120125781602001602082028036833780820191505090505b5090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061204a57612049613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050308160018151811061209957612098613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b6f9de954760008461dead6001426121239190613eca565b6040518663ffffffff1660e01b81526004016121429493929190614222565b6000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505061218a61dead61218561dead611516565b61268f565b505b6000600760026101000a81548160ff021916908315150217905550565b6000600d54436121b99190613eca565b905060005b8281101561227657601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600954908060018154018082558091505060019003906000526020600020016000909190919091505581601260006009548152602001908152602001600020819055506009600081548092919061225e90613efe565b9190505550808061226e90613efe565b9150506121be565b505050565b6001600681905550565b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016001601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201805490506123199190613e2a565b8154811061232a57612329613d8f565b5b9060005260206000200154601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061238957612388613d8f565b5b9060005260206000200181905550601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054806123e9576123e861426e565b5b600190038181906000526020600020016000905590555050565b600080600160648640868660405160200161242093929190614331565b6040516020818303038152906040528051906020012060001c612443919061436e565b61244d9190613eca565b905060058111612461576003915050612479565b60148111612473576002915050612479565b60019150505b9392505050565b80156124905761248f83612711565b5b81600a60008282546124a29190613eca565b9250508190555081601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546124fb9190613eca565b92505081905550505050565b60006125138484611c0f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125955781811015612585578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161257c9392919061439f565b60405180910390fd5b61259484848484036000612884565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361260d5760006040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161260491906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361267f5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161267691906137a6565b60405180910390fd5b61268a838383612a5b565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127015760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016126f891906137a6565b60405180910390fd5b61270d82600083612a5b565b5050565b600061271c82611ad7565b90506000620f424061c350836127329190613a38565b61273c9190613aa9565b9050600082146127725761275b8382846127569190613e2a565b612de6565b6127713060028361276c9190613aa9565b612de6565b5b42601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036128f65760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016128ed91906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129685760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161295f91906137a6565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612a55578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a4c91906135f0565b60405180910390a35b50505050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680612afc5750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80612b135750600760029054906101000a900460ff165b15612b2857612b23838383612e68565b612de1565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bcf57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b9050600081612bdf576000612c01565b620f4240612beb61308d565b84612bf69190613a38565b612c009190613aa9565b5b90506000811115612c1857612c17853083612e68565b5b8083612c249190613e2a565b9250612c2e6130d5565b8015612c8657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015612cde57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15612d5c5760646005695e0549c9632e1d800000612cfc9190613a38565b612d069190613aa9565b83612d1086611516565b612d1a9190613eca565b1115612d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5290614422565b60405180910390fd5b5b600760059054906101000a900460ff168015612dc457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15612dd357612dd2836130ee565b5b612dde858585612e68565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e585760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612e4f91906137a6565b60405180910390fd5b612e6460008383612a5b565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612eba578060026000828254612eae9190613eca565b92505081905550612f8d565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612f46578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612f3d9392919061439f565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fd65780600260008282540392505081905550613023565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161308091906135f0565b60405180910390a3505050565b6000806008544261309e9190613e2a565b90506101688111156130b5576175309150506130d2565b60b48111156130ca57620186a09150506130d2565b6202bf209150505b90565b60006078600854426130e79190613e2a565b1115905090565b6001600760026101000a81548160ff021916908315150217905550600061311d8261311830611516565b61335f565b9050600e5481101561312f5750613341565b6000600267ffffffffffffffff81111561314c5761314b614135565b5b60405190808252806020026020018201604052801561317a5781602001602082028036833780820191505090505b509050308160008151811061319257613191613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061320157613200613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613288307f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000612884565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040161330c959493929190614497565b600060405180830381600087803b15801561332657600080fd5b505af115801561333a573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831061336e5781613370565b825b905092915050565b600080fd5b6000819050919050565b6133908161337d565b811461339b57600080fd5b50565b6000813590506133ad81613387565b92915050565b600080600080600060a086880312156133cf576133ce613378565b5b60006133dd8882890161339e565b95505060206133ee8882890161339e565b94505060406133ff8882890161339e565b93505060606134108882890161339e565b92505060806134218882890161339e565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346857808201518184015260208101905061344d565b60008484015250505050565b6000601f19601f8301169050919050565b60006134908261342e565b61349a8185613439565b93506134aa81856020860161344a565b6134b381613474565b840191505092915050565b600060208201905081810360008301526134d88184613485565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061350b826134e0565b9050919050565b61351b81613500565b811461352657600080fd5b50565b60008135905061353881613512565b92915050565b6000806040838503121561355557613554613378565b5b600061356385828601613529565b92505060206135748582860161339e565b9150509250929050565b60008115159050919050565b6135938161357e565b82525050565b60006020820190506135ae600083018461358a565b92915050565b6000602082840312156135ca576135c9613378565b5b60006135d88482850161339e565b91505092915050565b6135ea8161337d565b82525050565b600060208201905061360560008301846135e1565b92915050565b6136148161357e565b811461361f57600080fd5b50565b6000813590506136318161360b565b92915050565b60006020828403121561364d5761364c613378565b5b600061365b84828501613622565b91505092915050565b60008060006060848603121561367d5761367c613378565b5b600061368b86828701613529565b935050602061369c86828701613529565b92505060406136ad8682870161339e565b9150509250925092565b600060ff82169050919050565b6136cd816136b7565b82525050565b60006020820190506136e860008301846136c4565b92915050565b60008060006060848603121561370757613706613378565b5b600061371586828701613529565b93505060206137268682870161339e565b925050604061373786828701613622565b9150509250925092565b60006020828403121561375757613756613378565b5b600061376584828501613529565b91505092915050565b600060408201905061378360008301856135e1565b61379060208301846135e1565b9392505050565b6137a081613500565b82525050565b60006020820190506137bb6000830184613797565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137f68161337d565b82525050565b600061380883836137ed565b60208301905092915050565b6000602082019050919050565b600061382c826137c1565b61383681856137cc565b9350613841836137dd565b8060005b8381101561387257815161385988826137fc565b975061386483613814565b925050600181019050613845565b5085935050505092915050565b600060208201905081810360008301526138998184613821565b905092915050565b60006138ac826134e0565b9050919050565b6138bc816138a1565b82525050565b60006020820190506138d760008301846138b3565b92915050565b600080604083850312156138f4576138f3613378565b5b600061390285828601613529565b925050602061391385828601613622565b9150509250929050565b6000806040838503121561393457613933613378565b5b600061394285828601613622565b925050602061395385828601613622565b9150509250929050565b6000806040838503121561397457613973613378565b5b600061398285828601613529565b925050602061399385828601613529565b9150509250929050565b7f546f6b656e206c61756e63686564000000000000000000000000000000000000600082015250565b60006139d3600e83613439565b91506139de8261399d565b602082019050919050565b60006020820190508181036000830152613a02816139c6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a438261337d565b9150613a4e8361337d565b9250828202613a5c8161337d565b91508282048414831517613a7357613a72613a09565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613ab48261337d565b9150613abf8361337d565b925082613acf57613ace613a7a565b5b828204905092915050565b6000819050919050565b6000819050919050565b6000613b09613b04613aff84613ada565b613ae4565b61337d565b9050919050565b613b1981613aee565b82525050565b600060c082019050613b346000830189613797565b613b4160208301886135e1565b613b4e6040830187613b10565b613b5b6060830186613b10565b613b686080830185613797565b613b7560a08301846135e1565b979650505050505050565b600081519050613b8f81613387565b92915050565b600080600060608486031215613bae57613bad613378565b5b6000613bbc86828701613b80565b9350506020613bcd86828701613b80565b9250506040613bde86828701613b80565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c2f57607f821691505b602082108103613c4257613c41613be8565b5b50919050565b7f4554482063617365732064697361626c6564206e6f7700000000000000000000600082015250565b6000613c7e601683613439565b9150613c8982613c48565b602082019050919050565b60006020820190508181036000830152613cad81613c71565b9050919050565b7f4e6f7420656e6f7567682065746820746f207061790000000000000000000000600082015250565b6000613cea601583613439565b9150613cf582613cb4565b602082019050919050565b60006020820190508181036000830152613d1981613cdd565b9050919050565b600081905092915050565b50565b6000613d3b600083613d20565b9150613d4682613d2b565b600082019050919050565b6000613d5c82613d2e565b9150819050919050565b6000604082019050613d7b60008301856135e1565b613d88602083018461358a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e6f7420636c61696d61626c6520796574000000000000000000000000000000600082015250565b6000613df4601183613439565b9150613dff82613dbe565b602082019050919050565b60006020820190508181036000830152613e2381613de7565b9050919050565b6000613e358261337d565b9150613e408361337d565b9250828203905081811115613e5857613e57613a09565b5b92915050565b7f546f6b656e2063617365732064697361626c6564206e6f770000000000000000600082015250565b6000613e94601883613439565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b6000613ed58261337d565b9150613ee08361337d565b9250828201905080821115613ef857613ef7613a09565b5b92915050565b6000613f098261337d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f3b57613f3a613a09565b5b600182019050919050565b60006dffffffffffffffffffffffffffff82169050919050565b613f6981613f46565b8114613f7457600080fd5b50565b600081519050613f8681613f60565b92915050565b600063ffffffff82169050919050565b613fa581613f8c565b8114613fb057600080fd5b50565b600081519050613fc281613f9c565b92915050565b600080600060608486031215613fe157613fe0613378565b5b6000613fef86828701613f77565b935050602061400086828701613f77565b925050604061401186828701613fb3565b9150509250925092565b7f4e6f207265736572766500000000000000000000000000000000000000000000600082015250565b6000614051600a83613439565b915061405c8261401b565b602082019050919050565b6000602082019050818103600083015261408081614044565b9050919050565b60008151905061409681613512565b92915050565b6000602082840312156140b2576140b1613378565b5b60006140c084828501614087565b91505092915050565b7f496e76616c696420707269636500000000000000000000000000000000000000600082015250565b60006140ff600d83613439565b915061410a826140c9565b602082019050919050565b6000602082019050818103600083015261412e816140f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61419981613500565b82525050565b60006141ab8383614190565b60208301905092915050565b6000602082019050919050565b60006141cf82614164565b6141d9818561416f565b93506141e483614180565b8060005b838110156142155781516141fc888261419f565b9750614207836141b7565b9250506001810190506141e8565b5085935050505092915050565b60006080820190506142376000830187613b10565b818103602083015261424981866141c4565b90506142586040830185613797565b61426560608301846135e1565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000819050919050565b6000819050919050565b6142c26142bd8261429d565b6142a7565b82525050565b6000819050919050565b6142e36142de8261337d565b6142c8565b82525050565b60008160601b9050919050565b6000614301826142e9565b9050919050565b6000614313826142f6565b9050919050565b61432b61432682613500565b614308565b82525050565b600061433d82866142b1565b60208201915061434d82856142d2565b60208201915061435d828461431a565b601482019150819050949350505050565b60006143798261337d565b91506143848361337d565b92508261439457614393613a7a565b5b828206905092915050565b60006060820190506143b46000830186613797565b6143c160208301856135e1565b6143ce60408301846135e1565b949350505050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b600061440c602083613439565b9150614417826143d6565b602082019050919050565b6000602082019050818103600083015261443b816143ff565b9050919050565b600061445d614458614453846134e0565b613ae4565b6134e0565b9050919050565b600061446f82614442565b9050919050565b600061448182614464565b9050919050565b61449181614476565b82525050565b600060a0820190506144ac60008301886135e1565b6144b96020830187613b10565b81810360408301526144cb81866141c4565b90506144da6060830185614488565b6144e760808301846135e1565b969550505050505056fea2646970667358221220b49cfa279018054d00c5bd4ce0f943faab20ecf256a784bc4b5274208e73c54e64736f6c63430008140033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d

Deployed Bytecode

0x6080604052600436106102765760003560e01c80637ab18aad1161014f578063bca93cf5116100c1578063df5fef921161007a578063df5fef9214610984578063ead267e7146109ad578063f18e7951146109d8578063f2fde38b14610a01578063f69e204614610a2a578063f906b61814610a415761027d565b8063bca93cf514610850578063c40d24b21461087b578063c92f69a9146108b8578063cc66ccea146108e1578063d58a90a71461091e578063dd62ed3e146109475761027d565b80639592d424116101135780639592d4241461072a57806395d89b4114610755578063a8aa1b3114610780578063a9059cbb146107ab578063aa3164c4146107e8578063b865e5d9146108255761027d565b80637ab18aad1461061c5780637d6731701461065a578063846f299e146106855780638da5cb5b146106c2578063946da64e146106ed5761027d565b8063328881df116101e85780635055c413116101ac5780635055c4131461051c5780636182d05d1461054757806365cf7c9b1461057257806367c7f5951461059d57806370a08231146105c8578063715018a6146106055761027d565b8063328881df1461045d5780633688555614610486578063372500ab146104af5780633c6ece75146104c6578063489f91d6146104f15761027d565b806317ed9d9d1161023a57806317ed9d9d1461033957806318160ddd146103645780631ae483b61461038f5780632073b17c146103b857806323b872dd146103f5578063313ce567146104325761027d565b806301339c211461028257806302f729b81461028c57806306fdde03146102b5578063095ea7b3146102e05780630c7c5c2a1461031d5761027d565b3661027d57005b600080fd5b61028a610a6c565b005b34801561029857600080fd5b506102b360048036038101906102ae91906133b3565b610c1a565b005b3480156102c157600080fd5b506102ca610c7a565b6040516102d791906134be565b60405180910390f35b3480156102ec57600080fd5b506103076004803603810190610302919061353e565b610d0c565b6040516103149190613599565b60405180910390f35b610337600480360381019061033291906135b4565b610d2f565b005b34801561034557600080fd5b5061034e610f11565b60405161035b91906135f0565b60405180910390f35b34801561037057600080fd5b50610379610f1e565b60405161038691906135f0565b60405180910390f35b34801561039b57600080fd5b506103b660048036038101906103b19190613637565b610f28565b005b3480156103c457600080fd5b506103df60048036038101906103da91906135b4565b611075565b6040516103ec91906135f0565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190613664565b6111db565b6040516104299190613599565b60405180910390f35b34801561043e57600080fd5b5061044761120a565b60405161045491906136d3565b60405180910390f35b34801561046957600080fd5b50610484600480360381019061047f91906136ee565b611213565b005b34801561049257600080fd5b506104ad60048036038101906104a891906135b4565b61122b565b005b3480156104bb57600080fd5b506104c461130b565b005b3480156104d257600080fd5b506104db611326565b6040516104e891906135f0565b60405180910390f35b3480156104fd57600080fd5b5061050661132c565b60405161051391906135f0565b60405180910390f35b34801561052857600080fd5b50610531611332565b60405161053e9190613599565b60405180910390f35b34801561055357600080fd5b5061055c611345565b60405161056991906135f0565b60405180910390f35b34801561057e57600080fd5b5061058761150a565b60405161059491906135f0565b60405180910390f35b3480156105a957600080fd5b506105b2611510565b6040516105bf91906135f0565b60405180910390f35b3480156105d457600080fd5b506105ef60048036038101906105ea9190613741565b611516565b6040516105fc91906135f0565b60405180910390f35b34801561061157600080fd5b5061061a61155e565b005b34801561062857600080fd5b50610643600480360381019061063e9190613741565b611572565b60405161065192919061376e565b60405180910390f35b34801561066657600080fd5b5061066f611596565b60405161067c91906135f0565b60405180910390f35b34801561069157600080fd5b506106ac60048036038101906106a791906135b4565b61159c565b6040516106b991906135f0565b60405180910390f35b3480156106ce57600080fd5b506106d761186d565b6040516106e491906137a6565b60405180910390f35b3480156106f957600080fd5b50610714600480360381019061070f9190613741565b611897565b604051610721919061387f565b60405180910390f35b34801561073657600080fd5b5061073f611931565b60405161074c91906135f0565b60405180910390f35b34801561076157600080fd5b5061076a611937565b60405161077791906134be565b60405180910390f35b34801561078c57600080fd5b506107956119c9565b6040516107a291906137a6565b60405180910390f35b3480156107b757600080fd5b506107d260048036038101906107cd919061353e565b6119ed565b6040516107df9190613599565b60405180910390f35b3480156107f457600080fd5b5061080f600480360381019061080a91906135b4565b611a10565b60405161081c91906135f0565b60405180910390f35b34801561083157600080fd5b5061083a611a28565b60405161084791906135f0565b60405180910390f35b34801561085c57600080fd5b50610865611a2e565b60405161087291906138c2565b60405180910390f35b34801561088757600080fd5b506108a2600480360381019061089d9190613741565b611a54565b6040516108af9190613599565b60405180910390f35b3480156108c457600080fd5b506108df60048036038101906108da91906138dd565b611a74565b005b3480156108ed57600080fd5b5061090860048036038101906109039190613741565b611ad7565b60405161091591906135f0565b60405180910390f35b34801561092a57600080fd5b506109456004803603810190610940919061391d565b611bcf565b005b34801561095357600080fd5b5061096e6004803603810190610969919061395d565b611c0f565b60405161097b91906135f0565b60405180910390f35b34801561099057600080fd5b506109ab60048036038101906109a6919061391d565b611c96565b005b3480156109b957600080fd5b506109c2611ce2565b6040516109cf91906135f0565b60405180910390f35b3480156109e457600080fd5b506109ff60048036038101906109fa9190613741565b611ce8565b005b348015610a0d57600080fd5b50610a286004803603810190610a239190613741565b611d86565b005b348015610a3657600080fd5b50610a3f611e0c565b005b348015610a4d57600080fd5b50610a56611ea9565b604051610a639190613599565b60405180910390f35b610a74611ebc565b6001600760026101000a81548160ff021916908315150217905550600760039054906101000a900460ff1615610adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad6906139e9565b60405180910390fd5b6001600760036101000a81548160ff02191690831515021790555042600881905550600060646055610b1030611516565b610b1a9190613a38565b610b249190613aa9565b9050610b51307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d83611f43565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663f305d71947308460008033426040518863ffffffff1660e01b8152600401610bb696959493929190613b1f565b60606040518083038185885af1158015610bd4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610bf99190613b95565b505050506000600760026101000a81548160ff021916908315150217905550565b610c22611ebc565b620493e0851115610c3257600080fd5b84600b81905550601e841115610c4757600080fd5b83600d81905550620493e0831115610c5e57600080fd5b82600c8190555081600e8190555080600f819055505050505050565b606060038054610c8990613c17565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590613c17565b8015610d025780601f10610cd757610100808354040283529160200191610d02565b820191906000526020600020905b815481529060010190602001808311610ce557829003601f168201915b5050505050905090565b600080610d17611f55565b9050610d24818585611f43565b600191505092915050565b610d37611f5d565b600760019054906101000a900460ff16610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90613c94565b60405180910390fd5b6000610d918261159c565b905080341015610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd90613d00565b60405180910390fd5b60006064600f34610de79190613a38565b610df19190613aa9565b90506000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682604051610e3b90613d51565b60006040518083038185875af1925050503d8060008114610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b5050905080610e8b57600080fd5b600760049054906101000a900460ff1615610ea957610ea8611fa3565b5b610eb2846121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c7716856000604051610efb929190613d66565b60405180910390a2505050610f0e61227b565b50565b6802b5e3af16b188000081565b6000600254905090565b610f30611ebc565b6001600760026101000a81548160ff021916908315150217905550600760049054906101000a900460ff161580610f745750600760059054906101000a900460ff16155b610f7d57600080fd5b8015611021576000601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1647604051610fcb90613d51565b60006040518083038185875af1925050503d8060008114611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b505090508061101b57600080fd5b50611057565b611055601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661105030611516565b6119ed565b505b6000600760026101000a81548160ff02191690831515021790555050565b600061107f611f5d565b6000601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020183815481106110d5576110d4613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905043811061113c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113390613e0a565b60405180910390fd5b6111463385612285565b610100436111549190613e2a565b81111561116d57611166818333612403565b9250611172565b600192505b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc846040516111b891906135f0565b60405180910390a26111cc33846001612480565b50506111d661227b565b919050565b6000806111e6611f55565b90506111f3858285612507565b6111fe85858561259b565b60019150509392505050565b60006012905090565b61121b611ebc565b611226838383612480565b505050565b611233611f5d565b600760009054906101000a900460ff16611282576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127990613eaa565b60405180910390fd5b6000816802b5e3af16b18800006112999190613a38565b90506112a5338261268f565b6112ae826121a9565b3373ffffffffffffffffffffffffffffffffffffffff167f4b6d5f6ec5b6bf274645c1a2e74f3f3749626863dbd4519f46fe943be67c77168360016040516112f7929190613d66565b60405180910390a25061130861227b565b50565b611313611f5d565b61131c33612711565b61132461227b565b565b600f5481565b60095481565b600760019054906101000a900460ff1681565b600061134f611f5d565b60004390506000610100436113649190613e2a565b9050600033905060005b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180549050811015611497576000601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061141157611410613d8f565b5b9060005260206000200154905060006012600083815260200190815260200160002054905085811015611481578481111561146357611451818386612403565b8761145c9190613eca565b9650611472565b868061146e90613efe565b9750505b61147c8484612285565b611490565b828061148c90613efe565b9350505b505061136e565b3373ffffffffffffffffffffffffffffffffffffffff167ffa1af51da9b0b353ee7b16e1a4ce5dabd2cd61a26eeb31f8fb1352dca4df13bc866040516114dd91906135f0565b60405180910390a260008511156114fb576114fa33866001612480565b5b5050505061150761227b565b90565b60085481565b600c5481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611566611ebc565b61157060006127be565b565b60116020528060005260406000206000915090508060000154908060010154905082565b600e5481565b600080600c54620f42406115b09190613e2a565b90506000807f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611620573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116449190613fc8565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156116795750600081115b6116b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116af90614067565b60405180910390fd5b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561175a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177e919061409c565b73ffffffffffffffffffffffffffffffffffffffff16146117a457808280925081935050505b600081670de0b6b3a7640000846117bb9190613a38565b6117c59190613aa9565b90506000810361180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190614115565b60405180910390fd5b6000670de0b6b3a7640000826802b5e3af16b188000061182a9190613a38565b6118349190613aa9565b90506000620f424086836118489190613a38565b6118529190613aa9565b905087816118609190613a38565b9650505050505050919050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180548060200260200160405190810160405280929190818152602001828054801561192557602002820191906000526020600020905b815481526020019060010190808311611911575b50505050509050919050565b600a5481565b60606004805461194690613c17565b80601f016020809104026020016040519081016040528092919081815260200182805461197290613c17565b80156119bf5780601f10611994576101008083540402835291602001916119bf565b820191906000526020600020905b8154815290600101906020018083116119a257829003601f168201915b5050505050905090565b7f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544181565b6000806119f8611f55565b9050611a0581858561259b565b600191505092915050565b60126020528060005260406000206000915090505481565b600d5481565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60136020528060005260406000206000915054906101000a900460ff1681565b611a7c611ebc565b80601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600080601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490506000826802b5e3af16b1880000611b7d9190613a38565b9050600062015180600b548442611b949190613e2a565b611b9e9190613a38565b611ba89190613aa9565b9050620f42408183611bba9190613a38565b611bc49190613aa9565b945050505050919050565b611bd7611ebc565b81600760046101000a81548160ff02191690831515021790555080600760056101000a81548160ff0219169083151502179055505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b611c9e611ebc565b8115611cc35780600760006101000a81548160ff021916908315150217905550611cde565b80600760016101000a81548160ff0219169083151502179055505b5050565b600b5481565b3373ffffffffffffffffffffffffffffffffffffffff16601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d4257600080fd5b80601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b611d8e611ebc565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e005760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611df791906137a6565b60405180910390fd5b611e09816127be565b50565b611e14611f5d565b6000611e1f33611ad7565b905060006802b5e3af16b188000082611e389190613aa9565b905060008103611e49575050611e9f565b42601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550611e9c33826000612480565b50505b611ea761227b565b565b600760009054906101000a900460ff1681565b611ec4611f55565b73ffffffffffffffffffffffffffffffffffffffff16611ee261186d565b73ffffffffffffffffffffffffffffffffffffffff1614611f4157611f05611f55565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611f3891906137a6565b60405180910390fd5b565b611f508383836001612884565b505050565b600033905090565b600260065403611f99576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600681905550565b6001600760026101000a81548160ff021916908315150217905550600f54471061218c576000600267ffffffffffffffff811115611fe457611fe3614135565b5b6040519080825280602002602001820160405280156120125781602001602082028036833780820191505090505b5090507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160008151811061204a57612049613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050308160018151811061209957612098613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663b6f9de954760008461dead6001426121239190613eca565b6040518663ffffffff1660e01b81526004016121429493929190614222565b6000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505061218a61dead61218561dead611516565b61268f565b505b6000600760026101000a81548160ff021916908315150217905550565b6000600d54436121b99190613eca565b905060005b8281101561227657601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600954908060018154018082558091505060019003906000526020600020016000909190919091505581601260006009548152602001908152602001600020819055506009600081548092919061225e90613efe565b9190505550808061226e90613efe565b9150506121be565b505050565b6001600681905550565b601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016001601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201805490506123199190613e2a565b8154811061232a57612329613d8f565b5b9060005260206000200154601160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201828154811061238957612388613d8f565b5b9060005260206000200181905550601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002018054806123e9576123e861426e565b5b600190038181906000526020600020016000905590555050565b600080600160648640868660405160200161242093929190614331565b6040516020818303038152906040528051906020012060001c612443919061436e565b61244d9190613eca565b905060058111612461576003915050612479565b60148111612473576002915050612479565b60019150505b9392505050565b80156124905761248f83612711565b5b81600a60008282546124a29190613eca565b9250508190555081601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282546124fb9190613eca565b92505081905550505050565b60006125138484611c0f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146125955781811015612585578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161257c9392919061439f565b60405180910390fd5b61259484848484036000612884565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361260d5760006040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040161260491906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361267f5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161267691906137a6565b60405180910390fd5b61268a838383612a5b565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036127015760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016126f891906137a6565b60405180910390fd5b61270d82600083612a5b565b5050565b600061271c82611ad7565b90506000620f424061c350836127329190613a38565b61273c9190613aa9565b9050600082146127725761275b8382846127569190613e2a565b612de6565b6127713060028361276c9190613aa9565b612de6565b5b42601160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036128f65760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016128ed91906137a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129685760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161295f91906137a6565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612a55578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a4c91906135f0565b60405180910390a35b50505050565b601360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680612afc5750601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b80612b135750600760029054906101000a900460ff165b15612b2857612b23838383612e68565b612de1565b60007f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bcf57507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b9050600081612bdf576000612c01565b620f4240612beb61308d565b84612bf69190613a38565b612c009190613aa9565b5b90506000811115612c1857612c17853083612e68565b5b8083612c249190613e2a565b9250612c2e6130d5565b8015612c8657507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b8015612cde57507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b15612d5c5760646005695e0549c9632e1d800000612cfc9190613a38565b612d069190613aa9565b83612d1086611516565b612d1a9190613eca565b1115612d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d5290614422565b60405180910390fd5b5b600760059054906101000a900460ff168015612dc457507f000000000000000000000000a3502a7b4e0632c18fa74d79a0b06cf22349544173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15612dd357612dd2836130ee565b5b612dde858585612e68565b50505b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612e585760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612e4f91906137a6565b60405180910390fd5b612e6460008383612a5b565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612eba578060026000828254612eae9190613eca565b92505081905550612f8d565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612f46578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612f3d9392919061439f565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fd65780600260008282540392505081905550613023565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161308091906135f0565b60405180910390a3505050565b6000806008544261309e9190613e2a565b90506101688111156130b5576175309150506130d2565b60b48111156130ca57620186a09150506130d2565b6202bf209150505b90565b60006078600854426130e79190613e2a565b1115905090565b6001600760026101000a81548160ff021916908315150217905550600061311d8261311830611516565b61335f565b9050600e5481101561312f5750613341565b6000600267ffffffffffffffff81111561314c5761314b614135565b5b60405190808252806020026020018201604052801561317a5781602001602082028036833780820191505090505b509050308160008151811061319257613191613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160018151811061320157613200613d8f565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613288307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000612884565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d73ffffffffffffffffffffffffffffffffffffffff1663791ac94783600084601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16426040518663ffffffff1660e01b815260040161330c959493929190614497565b600060405180830381600087803b15801561332657600080fd5b505af115801561333a573d6000803e3d6000fd5b5050505050505b6000600760026101000a81548160ff02191690831515021790555050565b600081831061336e5781613370565b825b905092915050565b600080fd5b6000819050919050565b6133908161337d565b811461339b57600080fd5b50565b6000813590506133ad81613387565b92915050565b600080600080600060a086880312156133cf576133ce613378565b5b60006133dd8882890161339e565b95505060206133ee8882890161339e565b94505060406133ff8882890161339e565b93505060606134108882890161339e565b92505060806134218882890161339e565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b8381101561346857808201518184015260208101905061344d565b60008484015250505050565b6000601f19601f8301169050919050565b60006134908261342e565b61349a8185613439565b93506134aa81856020860161344a565b6134b381613474565b840191505092915050565b600060208201905081810360008301526134d88184613485565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061350b826134e0565b9050919050565b61351b81613500565b811461352657600080fd5b50565b60008135905061353881613512565b92915050565b6000806040838503121561355557613554613378565b5b600061356385828601613529565b92505060206135748582860161339e565b9150509250929050565b60008115159050919050565b6135938161357e565b82525050565b60006020820190506135ae600083018461358a565b92915050565b6000602082840312156135ca576135c9613378565b5b60006135d88482850161339e565b91505092915050565b6135ea8161337d565b82525050565b600060208201905061360560008301846135e1565b92915050565b6136148161357e565b811461361f57600080fd5b50565b6000813590506136318161360b565b92915050565b60006020828403121561364d5761364c613378565b5b600061365b84828501613622565b91505092915050565b60008060006060848603121561367d5761367c613378565b5b600061368b86828701613529565b935050602061369c86828701613529565b92505060406136ad8682870161339e565b9150509250925092565b600060ff82169050919050565b6136cd816136b7565b82525050565b60006020820190506136e860008301846136c4565b92915050565b60008060006060848603121561370757613706613378565b5b600061371586828701613529565b93505060206137268682870161339e565b925050604061373786828701613622565b9150509250925092565b60006020828403121561375757613756613378565b5b600061376584828501613529565b91505092915050565b600060408201905061378360008301856135e1565b61379060208301846135e1565b9392505050565b6137a081613500565b82525050565b60006020820190506137bb6000830184613797565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6137f68161337d565b82525050565b600061380883836137ed565b60208301905092915050565b6000602082019050919050565b600061382c826137c1565b61383681856137cc565b9350613841836137dd565b8060005b8381101561387257815161385988826137fc565b975061386483613814565b925050600181019050613845565b5085935050505092915050565b600060208201905081810360008301526138998184613821565b905092915050565b60006138ac826134e0565b9050919050565b6138bc816138a1565b82525050565b60006020820190506138d760008301846138b3565b92915050565b600080604083850312156138f4576138f3613378565b5b600061390285828601613529565b925050602061391385828601613622565b9150509250929050565b6000806040838503121561393457613933613378565b5b600061394285828601613622565b925050602061395385828601613622565b9150509250929050565b6000806040838503121561397457613973613378565b5b600061398285828601613529565b925050602061399385828601613529565b9150509250929050565b7f546f6b656e206c61756e63686564000000000000000000000000000000000000600082015250565b60006139d3600e83613439565b91506139de8261399d565b602082019050919050565b60006020820190508181036000830152613a02816139c6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a438261337d565b9150613a4e8361337d565b9250828202613a5c8161337d565b91508282048414831517613a7357613a72613a09565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613ab48261337d565b9150613abf8361337d565b925082613acf57613ace613a7a565b5b828204905092915050565b6000819050919050565b6000819050919050565b6000613b09613b04613aff84613ada565b613ae4565b61337d565b9050919050565b613b1981613aee565b82525050565b600060c082019050613b346000830189613797565b613b4160208301886135e1565b613b4e6040830187613b10565b613b5b6060830186613b10565b613b686080830185613797565b613b7560a08301846135e1565b979650505050505050565b600081519050613b8f81613387565b92915050565b600080600060608486031215613bae57613bad613378565b5b6000613bbc86828701613b80565b9350506020613bcd86828701613b80565b9250506040613bde86828701613b80565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c2f57607f821691505b602082108103613c4257613c41613be8565b5b50919050565b7f4554482063617365732064697361626c6564206e6f7700000000000000000000600082015250565b6000613c7e601683613439565b9150613c8982613c48565b602082019050919050565b60006020820190508181036000830152613cad81613c71565b9050919050565b7f4e6f7420656e6f7567682065746820746f207061790000000000000000000000600082015250565b6000613cea601583613439565b9150613cf582613cb4565b602082019050919050565b60006020820190508181036000830152613d1981613cdd565b9050919050565b600081905092915050565b50565b6000613d3b600083613d20565b9150613d4682613d2b565b600082019050919050565b6000613d5c82613d2e565b9150819050919050565b6000604082019050613d7b60008301856135e1565b613d88602083018461358a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e6f7420636c61696d61626c6520796574000000000000000000000000000000600082015250565b6000613df4601183613439565b9150613dff82613dbe565b602082019050919050565b60006020820190508181036000830152613e2381613de7565b9050919050565b6000613e358261337d565b9150613e408361337d565b9250828203905081811115613e5857613e57613a09565b5b92915050565b7f546f6b656e2063617365732064697361626c6564206e6f770000000000000000600082015250565b6000613e94601883613439565b9150613e9f82613e5e565b602082019050919050565b60006020820190508181036000830152613ec381613e87565b9050919050565b6000613ed58261337d565b9150613ee08361337d565b9250828201905080821115613ef857613ef7613a09565b5b92915050565b6000613f098261337d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613f3b57613f3a613a09565b5b600182019050919050565b60006dffffffffffffffffffffffffffff82169050919050565b613f6981613f46565b8114613f7457600080fd5b50565b600081519050613f8681613f60565b92915050565b600063ffffffff82169050919050565b613fa581613f8c565b8114613fb057600080fd5b50565b600081519050613fc281613f9c565b92915050565b600080600060608486031215613fe157613fe0613378565b5b6000613fef86828701613f77565b935050602061400086828701613f77565b925050604061401186828701613fb3565b9150509250925092565b7f4e6f207265736572766500000000000000000000000000000000000000000000600082015250565b6000614051600a83613439565b915061405c8261401b565b602082019050919050565b6000602082019050818103600083015261408081614044565b9050919050565b60008151905061409681613512565b92915050565b6000602082840312156140b2576140b1613378565b5b60006140c084828501614087565b91505092915050565b7f496e76616c696420707269636500000000000000000000000000000000000000600082015250565b60006140ff600d83613439565b915061410a826140c9565b602082019050919050565b6000602082019050818103600083015261412e816140f2565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61419981613500565b82525050565b60006141ab8383614190565b60208301905092915050565b6000602082019050919050565b60006141cf82614164565b6141d9818561416f565b93506141e483614180565b8060005b838110156142155781516141fc888261419f565b9750614207836141b7565b9250506001810190506141e8565b5085935050505092915050565b60006080820190506142376000830187613b10565b818103602083015261424981866141c4565b90506142586040830185613797565b61426560608301846135e1565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000819050919050565b6000819050919050565b6142c26142bd8261429d565b6142a7565b82525050565b6000819050919050565b6142e36142de8261337d565b6142c8565b82525050565b60008160601b9050919050565b6000614301826142e9565b9050919050565b6000614313826142f6565b9050919050565b61432b61432682613500565b614308565b82525050565b600061433d82866142b1565b60208201915061434d82856142d2565b60208201915061435d828461431a565b601482019150819050949350505050565b60006143798261337d565b91506143848361337d565b92508261439457614393613a7a565b5b828206905092915050565b60006060820190506143b46000830186613797565b6143c160208301856135e1565b6143ce60408301846135e1565b949350505050565b7f4d6178696d756d20746f6b656e207065722077616c6c65742072656163686564600082015250565b600061440c602083613439565b9150614417826143d6565b602082019050919050565b6000602082019050818103600083015261443b816143ff565b9050919050565b600061445d614458614453846134e0565b613ae4565b6134e0565b9050919050565b600061446f82614442565b9050919050565b600061448182614464565b9050919050565b61449181614476565b82525050565b600060a0820190506144ac60008301886135e1565b6144b96020830187613b10565b81810360408301526144cb81866141c4565b90506144da6060830185614488565b6144e760808301846135e1565b969550505050505056fea2646970667358221220b49cfa279018054d00c5bd4ce0f943faab20ecf256a784bc4b5274208e73c54e64736f6c63430008140033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d

-----Decoded View---------------
Arg [0] : _WETH (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : _ROUTER (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d


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.