ETH Price: $2,483.71 (-0.94%)

Token

[LIKWID] Likwid Shortable Token demo (LSTD)
 

Overview

Max Total Supply

1,386,322.108015774413455256 LSTD

Holders

705

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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:
SlaveTokenProduct

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 100 runs

Other Settings:
paris EvmVersion
File 1 of 20 : SlaveTokenProduct.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {LikwidProduct} from "./LikwidProduct.sol";
import {IMessageStruct} from "@vizing/contracts/interface/IMessageStruct.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

import {ActionType} from "../constants/ActionType.sol";

import {IFactorySlave} from "../interface/IFactorySlave.sol";
import {IChannelSlave} from "../interface/IChannelSlave.sol";

contract SlaveTokenProduct is LikwidProduct {
    IFactorySlave public _factory;
    IChannelSlave public _channel;
    address public signer;
    uint public launchLimit;

    constructor(
        string memory _name,
        string memory _symbol,
        address _ownerAddr,
        address _factoryAddress,
        uint _omniSupply,
        uint _launchFunds,
        uint _launchTime,
        uint _launchHardCap,
        address _creatorAddr,
        address _signer,
        bytes memory params
    )
        LikwidProduct(
            _name,
            _symbol,
            _ownerAddr,
            _factoryAddress,
            _omniSupply,
            _launchFunds,
            _launchTime,
            _launchHardCap,
            _creatorAddr
        )
    {
        signer = _signer;
        _factory = IFactorySlave(_factoryAddress);
        _channel = IChannelSlave(_factory.getChannelAddress());
        if (params.length > 0) {
            (, , launchLimit, signSwitch) = abi.decode(params, (uint, uint, uint, bool));
        }
    }

    mapping(address => uint) public depositPing;
    mapping(address => uint) public buyNonce;
    mapping(address => mapping(uint => bool)) public buyNoncePong;

    mapping(address => uint) public sellNonce;
    mapping(address => mapping(uint => bool)) public sellNoncePong;

    function setSigner(address addr_) external onlyOwner {
        signer = addr_;
    }

    function setLaunched(bool _launched) external {
        require(signer == _msgSender() || owner() == _msgSender(), "only signer/owner call");
        launched = _launched;
    }

    function depositTotal(address sender) public view returns (uint) {
        uint amount;
        if (sender == creatorAddr) {
            amount = launchLimit * 10;
        } else {
            amount = launchLimit;
        }
        if (amount == 0) {
            amount = launchFunds / 100;
        }
        if (amount > launchFunds) {
            amount = launchFunds;
        }
        return amount;
    }

    function action_func(uint64 srcChainId, address sender, uint8 action, uint, bytes memory params) internal override {
        if (action == uint8(ActionType.buyPong)) {
            (uint nonce, address target, uint native, uint token, bool masterLaunch) = abi.decode(
                params,
                (uint, address, uint, uint, bool)
            );
            slave_buy(srcChainId, sender, target, native, token, masterLaunch, nonce);
        } else if (action == uint8(ActionType.sellPong)) {
            (uint nonce, address target, uint token, uint native) = abi.decode(params, (uint, address, uint, uint));
            slave_sell(srcChainId, sender, target, native, token, nonce);
        } else if (action == uint8(ActionType.unStakePong)) {
            (uint nonce, address target, uint token) = abi.decode(params, (uint, address, uint));
            slave_unstake(target, token, nonce);
        } else if (action == uint8(ActionType.crossPing)) {
            (uint nonce, uint64 chainid, address to, uint token) = abi.decode(params, (uint, uint64, address, uint));
            slave_cross(srcChainId, sender, chainid, to, token, nonce);
        } else revert NotImplement();
    }

    //----slave call
    function slave_buy(
        uint64,
        address,
        address target,
        uint native,
        uint token,
        bool masterLaunch,
        uint nonce
    ) internal {
        require(!buyNoncePong[target][nonce], "nonce repetition");
        if (!launched) {
            launched = masterLaunch;
        }
        buyNoncePong[target][nonce] = true;
        if (token > 0) _mint(target, token);
        if (native > 0) transferNative(target, native);
    }

    function slave_sell(uint64, address, address target, uint native, uint, uint nonce) internal {
        require(!sellNoncePong[target][nonce], "nonce repetition");
        sellNoncePong[target][nonce] = true;
        if (!launched) {
            if (native < depositPing[target]) {
                depositPing[target] -= native;
            } else {
                depositPing[target] = 0;
            }
        }
        // if (token > 0) _mint(target, token);
        if (native > 0) transferNative(target, native);
    }

    // ----Signature---

    function _buyPingSignature(
        uint nonce,
        address target,
        uint pongFee,
        uint amountIn
    ) internal view returns (bytes memory) {
        return abi.encode(uint8(ActionType.buyPing), symbol(), pongFee, abi.encode(nonce, target, amountIn));
    }

    function _sellPingSignature(
        uint nonce,
        address target,
        uint pongFee,
        uint amountIn
    ) internal view returns (bytes memory) {
        return abi.encode(uint8(ActionType.sellPing), symbol(), pongFee, abi.encode(nonce, target, amountIn));
    }

    uint public cutShortTime = 600; //10 minute

    function setCutShortTime(uint time) public onlyOwner {
        cutShortTime = time;
    }

    function getHash(
        string memory biz,
        string memory symbol,
        uint amount,
        address sender
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(biz, symbol, amount, sender));
    }

    bool public signSwitch = false;

    function setSignSwitch(bool pause_) public onlyOwner {
        signSwitch = pause_;
    }

    //----_buy

    function buyPingEstimateGas(uint pongFee, address target, uint amountIn) public view returns (uint pingFee) {
        uint nonce = buyNonce[_msgSender()];
        pingFee = _channel.paramsEstimateGas(pongFee, _buyPingSignature(nonce + 1, target, pongFee, amountIn));
    }

    uint public swapTime = 100; //60 minute

    function setSwapTime(uint time) public onlyOwner {
        swapTime = time;
    }

    function _buy(uint pongFee, address to) internal {
        uint pingFee = buyPingEstimateGas(pongFee, to, msg.value);
        if (pongFee == 0) {
            pongFee = pingFee;
        }
        uint amountIn = msg.value - pingFee - pongFee;
        require(amountIn >= nativeMin, "the amount cannot be too small");
        require(amountIn <= nativeMax, "the amount cannot be too large");
        if (!launched) {
            depositPing[_msgSender()] += amountIn;
            require(depositPing[_msgSender()] <= depositTotal(_msgSender()), "pay too much");
        }
        uint nonce = buyNonce[_msgSender()];
        _channel.paramsEmit2LaunchPad{value: msg.value}(
            pingFee,
            amountIn + pongFee,
            _buyPingSignature(nonce + 1, to, pongFee, amountIn),
            _msgSender()
        );
        buyNonce[_msgSender()]++;
    }

    //----_sell

    function sellPingEstimateGas(uint pongFee, address target, uint amountIn) public view returns (uint pingFee) {
        uint nonce = sellNonce[_msgSender()];

        pingFee = _channel.paramsEstimateGas(pongFee, _sellPingSignature(nonce + 1, target, pongFee, amountIn));
    }

    function _sell(uint pongFee, address from, address to, uint amountIn) internal {
        require(amountIn > 0, "amount in err.");
        require(balanceOf(from) >= amountIn, "sell amount exceeds balance");
        uint pingFee = sellPingEstimateGas(pongFee, to, amountIn);
        if (pongFee == 0) {
            pongFee = pingFee;
        }
        require(msg.value >= pingFee + pongFee, "bridge fee not enough");

        require(amountIn >= tokenMin, "the amount cannot be too small");

        uint nonce = sellNonce[_msgSender()];
        bytes memory params = _sellPingSignature(nonce + 1, to, pongFee, amountIn);

        _burn(from, amountIn);
        _channel.paramsEmit2LaunchPad{value: msg.value}(pingFee, pongFee, params, _msgSender());
        sellNonce[_msgSender()]++;
    }

    //----314token
    function getReserves() public pure returns (uint, uint) {
        revert NotImplement();
    }

    function getAmountOut(uint, bool) public pure returns (uint) {
        revert NotImplement();
    }

    bool public swapPause = false;

    function setSwapPause(bool pause_) public onlyOwner {
        swapPause = pause_;
    }

    function swapExactETHForTokens(uint pongFee, address to, bytes calldata signature) external payable nonReentrant {
        require(!swapPause, "swap pause");
        if (signSwitch && !launched) {
            bytes32 hash = getHash("buy", symbol(), msg.value, _msgSender());
            require(SignatureChecker.isValidSignatureNow(signer, hash, signature), "verify error");
        }

        _buy(pongFee, to);
    }

    function swapExactTokensForETH(uint pongFee, uint amountIn, address to) external payable nonReentrant {
        require(!swapPause, "swap pause");
        _sell(pongFee, _msgSender(), to, amountIn);
    }

    function slave_cross(uint64 srcChainId, address, uint64 dstChainId, address to, uint token, uint nonce) internal {
        require(!crossNoncePing[srcChainId][to][nonce], "nonce repetition");
        crossNoncePing[srcChainId][to][nonce] = true;
        require(dstChainId == block.chainid, "chain id err");
        if (token > 0) _mint(to, token);
        emit Crossed(srcChainId, to, to, token, nonce);
    }

    function crossToEstimateGas(uint64 dstChainId, address to, uint amount) public view returns (uint pingFee) {
        uint nonce = crossNonce[dstChainId][to];
        pingFee = _channel.paramsEstimateGas(0, _crossPingSignature(nonce + 1, dstChainId, to, amount));
    }

    function crossTo(uint64 dstChainId, address to, uint amount) external payable {
        address owner = _msgSender();
        require(balanceOf(owner) >= amount, "insufficient balance");
        _burn(owner, amount);
        uint nonce = crossNonce[block.chainid][_msgSender()];
        uint pingFee = crossToEstimateGas(dstChainId, to, amount);
        _channel.paramsEmit2LaunchPad{value: msg.value}(
            pingFee,
            0,
            _crossPingSignature(nonce + 1, dstChainId, to, amount),
            _msgSender()
        );
        crossNonce[block.chainid][_msgSender()]++;
    }

    mapping(address => mapping(uint => bool)) public unStakeNoncePing;
    mapping(address => uint) public unStakeNonce;

    function _stakePingSignature(address target, uint token, uint duration) internal view returns (bytes memory) {
        return abi.encode(uint8(ActionType.stakePing), symbol(), 0, abi.encode(target, token, duration));
    }

    function stakePingEstimateGas(address target, uint token, uint duration) public view returns (uint pingFee) {
        pingFee = _channel.paramsEstimateGas(0, _stakePingSignature(target, token, duration));
    }

    function stake(uint token, uint duration) external payable nonReentrant {
        require(token > 0, "token in err.");
        address target = _msgSender();
        require(balanceOf(target) >= token, "stake amount exceeds balance");
        uint pingFee = stakePingEstimateGas(target, token, duration);
        require(msg.value >= pingFee, "bridge fee not enough");

        bytes memory params = _stakePingSignature(target, token, duration);

        _burn(target, token);
        _channel.paramsEmit2LaunchPad{value: msg.value}(pingFee, 0, params, _msgSender());
    }

    function slave_unstake(address target, uint token, uint nonce) internal {
        require(!unStakeNoncePing[target][nonce], "nonce repetition");
        unStakeNoncePing[target][nonce] = true;
        if (token > 0) _mint(target, token);
    }

    function _unStakePingSignature(
        uint nonce,
        address target,
        uint pongFee,
        uint token
    ) internal view returns (bytes memory) {
        return abi.encode(uint8(ActionType.unStakePing), symbol(), pongFee, abi.encode(nonce, target, token));
    }

    function unStakePingEstimateGas(uint pongFee, address target, uint token) public view returns (uint pingFee) {
        uint nonce = unStakeNonce[_msgSender()];
        pingFee = _channel.paramsEstimateGas(pongFee, _unStakePingSignature(nonce + 1, target, pongFee, token));
    }

    function unStake(uint pongFee, uint token) external payable nonReentrant {
        require(token > 0, "token in err.");
        address target = _msgSender();
        uint pingFee = unStakePingEstimateGas(pongFee, target, token);
        require(msg.value >= pingFee + pongFee, "bridge fee not enough");

        uint nonce = unStakeNonce[target];
        bytes memory params = _unStakePingSignature(nonce + 1, target, pongFee, token);

        _channel.paramsEmit2LaunchPad{value: msg.value}(pingFee, pongFee, params, _msgSender());
        unStakeNonce[target]++;
    }

    /**
     * @dev Fallback function to buy tokens with ETH.
     */
    receive() external payable {
        _buy(0, _msgSender());
    }
}

File 2 of 20 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @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 {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _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 20 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 4 of 20 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @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;

    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
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // 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 5 of 20 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.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}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * 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.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => 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 override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override 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 override returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override 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 `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` 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 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        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 `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `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.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` 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.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

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

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

File 6 of 20 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
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 7 of 20 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

File 8 of 20 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @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 9 of 20 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

File 10 of 20 : SignatureChecker.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "../../interfaces/IERC1271.sol";

/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        return
            (error == ECDSA.RecoverError.NoError && recovered == signer) ||
            isValidERC1271SignatureNow(signer, hash, signature);
    }

    /**
     * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
     * against the signer smart contract using ERC1271.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidERC1271SignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success &&
            result.length >= 32 &&
            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
    }
}

File 11 of 20 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 12 of 20 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 13 of 20 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 14 of 20 : IMessageStruct.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface IMessageStruct {
    struct launchParams {
        uint64 earliestArrivalTimestamp;
        uint64 latestArrivalTimestamp;
        address relayer;
        address sender;
        uint256 value;
        uint64 destChainid;
        bytes additionParams;
        bytes message;
    }

    struct landingParams {
        bytes32 messageId;
        uint64 earliestArrivalTimestamp;
        uint64 latestArrivalTimestamp;
        uint64 srcChainid;
        bytes32 srcTxHash;
        uint256 srcContract;
        uint32 srcChainNonce;
        uint256 sender;
        uint256 value;
        bytes additionParams;
        bytes message;
    }

    struct launchEnhanceParams {
        uint64 earliestArrivalTimestamp;
        uint64 latestArrivalTimestamp;
        address relayer;
        address sender;
        uint256[] value;
        uint64[] destChainid;
        bytes[] additionParams;
        bytes[] message;
    }

    struct RollupMessageStruct {
        SignedMessageBase base;
        IMessageStruct.launchParams params;
    }

    struct SignedMessageBase {
        uint64 srcChainId;
        uint24 nonceLaunch;
        bytes32 srcTxHash;
        bytes32 destTxHash;
        uint64 srcTxTimestamp;
        uint64 destTxTimestamp;
    }
}

File 15 of 20 : ActionType.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

enum ActionType {
    buyPing,
    buyPong,
    sellPing,
    sellPong,
    crossPing,
    stakePing,
    unStakePing,
    unStakePong
}

File 16 of 20 : IChannelSlave.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IChannelSlave {
    function paramsEstimateGas(uint value, bytes memory params) external view returns (uint);

    function paramsEmit2LaunchPad(uint bridgeFee, uint value, bytes memory params, address sender) external payable;
}

File 17 of 20 : IFactoryBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

interface IFactoryBase {
    function getChannelAddress() external view returns (address);

    function getProduct(string memory symbol_) external view returns (IProductBase);

    function getSymbol(address _addr) external view returns (string memory);

    function existProduct(address _addr) external view returns (bool);

    function getShortByLong(address longAddr) external view returns (address);
}

File 18 of 20 : IFactorySlave.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

interface IFactorySlave is IFactoryBase {}

File 19 of 20 : IProductBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IProductBase {
    function actionCall(
        uint64 srcChainId,
        address sender,
        uint8 action,
        uint pongFee,
        bytes memory params
    ) external payable;
}

File 20 of 20 : LikwidProduct.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

import {ActionType} from "../constants/ActionType.sol";

import {IFactoryBase} from "../interface/IFactoryBase.sol";
import {IProductBase} from "../interface/IProductBase.sol";

abstract contract LikwidProduct is ERC20, Ownable, ReentrancyGuard, IProductBase {
    error NotImplement();
    using Strings for uint256;

    event MessageReceived(uint64 _srcChainId, address _srcAddress, uint value, bytes _payload);
    event PongfeeFailed(uint64 _srcChainId, address _srcAddress, uint8 _action, uint _pongFee, uint _expectPongFee);

    event Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, uint nonce);

    event AssetLocked(
        ActionType _action,
        uint64 _srcChainId,
        address _owner,
        uint _lockedNative,
        uint _lockedToken,
        uint nonce
    );

    event Crossed(uint64 _srcChainId, address _sender, address _to, uint _token, uint nonce);
    event Unlocked(address _owner, address _to, uint _native, uint _token);
    event Stake(address indexed sender, uint64 _srcChainId, uint tokenIn, uint tokenOut, uint nonce);

    mapping(uint => mapping(address => mapping(uint => bool))) public crossNoncePing;
    mapping(uint => mapping(address => uint)) public crossNonce;

    bool public launched;
    uint public messageReceived;
    address public feeAddress;
    uint public omniSupply;
    uint public launchFunds;
    uint public launchTime;
    uint public launchHardCap;
    address public creatorAddr;
    address public airdropAddr;

    address public factoryAddress;

    function setFeeAddress(address addr) public virtual onlyOwner {
        feeAddress = addr;
    }

    function setAirdropAddr(address addr) public virtual onlyOwner {
        airdropAddr = addr;
    }

    function setCreatorAddr(address addr) public virtual onlyOwner {
        creatorAddr = addr;
    }

    function setLaunchHardCap(uint amount) public virtual onlyOwner {
        launchHardCap = amount;
    }

    function setLaunchTime(uint launchTime_) public virtual onlyOwner {
        launchTime = launchTime_;
    }

    uint version = 7 ether;
    uint public nativeMax = 5 ether;
    uint public nativeMin = 0.0001 ether;
    uint public tokenMin = 1 ether;
    uint public nativeTotal = 50 ether;

    function setNativeTotal(uint amount) public virtual onlyOwner {
        nativeTotal = amount;
    }

    function setNativeMax(uint amount) public virtual onlyOwner {
        nativeMax = amount;
    }

    function setNativeMin(uint amount) public virtual onlyOwner {
        nativeMin = amount;
    }

    function setTokenMin(uint amount) public virtual onlyOwner {
        tokenMin = amount;
    }

    function nowTime() public view returns (uint) {
        return block.timestamp;
    }

    function getVersion() public view returns (uint) {
        return version;
    }

    constructor(
        string memory _name,
        string memory _symbol,
        address _ownerAddr,
        address _factoryAddress,
        uint _omniSupply,
        uint _launchFunds,
        uint _launchTime,
        uint _launchHardCap,
        address _creatorAddr
    ) ERC20(_name, _symbol) {
        launched = false;
        feeAddress = _ownerAddr;
        airdropAddr = _ownerAddr;
        omniSupply = _omniSupply;
        launchFunds = _launchFunds;
        launchTime = _launchTime;
        launchHardCap = _launchHardCap;
        creatorAddr = _creatorAddr;
        factoryAddress = _factoryAddress;
        require(launchFunds > 0, "launch funds err");
        require(omniSupply > 0, "total supply init err");
    }

    function transferNative(address to, uint amount) internal {
        (bool success, ) = to.call{value: amount}("");
        require(success, string.concat("Product Transfer failed.", amount.toString()));
    }

    function action_func(uint64, address, uint8, uint, bytes memory) internal virtual {
        revert NotImplement();
    }

    function actionCall(
        uint64 srcChainId,
        address sender,
        uint8 action,
        uint pongFee,
        bytes memory params
    ) external payable {
        require(
            _msgSender() == IFactoryBase(factoryAddress).getChannelAddress(),
            "LikwidProduct: caller must be channel"
        );
        emit MessageReceived(srcChainId, sender, msg.value, params);
        action_func(srcChainId, sender, action, pongFee, params);
    }

    function _transfer(address from, address to, uint256 amount) internal virtual override {
        if (_msgSender() != address(this) && to == address(this)) {
            revert("Unsupported");
        } else {
            super._transfer(from, to, amount);
        }
    }

    function _crossPingSignature(
        uint nonce,
        uint64 dstChainId,
        address target,
        uint token
    ) internal view virtual returns (bytes memory) {
        return abi.encode(uint8(ActionType.crossPing), symbol(), 0, abi.encode(nonce, dstChainId, target, token));
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_ownerAddr","type":"address"},{"internalType":"address","name":"_factoryAddress","type":"address"},{"internalType":"uint256","name":"_omniSupply","type":"uint256"},{"internalType":"uint256","name":"_launchFunds","type":"uint256"},{"internalType":"uint256","name":"_launchTime","type":"uint256"},{"internalType":"uint256","name":"_launchHardCap","type":"uint256"},{"internalType":"address","name":"_creatorAddr","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotImplement","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":false,"internalType":"enum ActionType","name":"_action","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_lockedNative","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lockedToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"AssetLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"Crossed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"_srcAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"_srcAddress","type":"address"},{"indexed":false,"internalType":"uint8","name":"_action","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_pongFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_expectPongFee","type":"uint256"}],"name":"PongfeeFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"tokenIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"Swap","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_native","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_token","type":"uint256"}],"name":"Unlocked","type":"event"},{"inputs":[],"name":"_channel","outputs":[{"internalType":"contract IChannelSlave","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_factory","outputs":[{"internalType":"contract IFactorySlave","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"actionCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"airdropAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"address","name":"","type":"address"}],"name":"buyNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"buyNoncePong","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"buyPingEstimateGas","outputs":[{"internalType":"uint256","name":"pingFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creatorAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"crossNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"crossNoncePing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"crossTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"crossToEstimateGas","outputs":[{"internalType":"uint256","name":"pingFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cutShortTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"depositPing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"depositTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"biz","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sender","type":"address"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launchFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchHardCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launched","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageReceived","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":"nativeMax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nowTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"omniSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"sellNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"sellNoncePong","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"sellPingEstimateGas","outputs":[{"internalType":"uint256","name":"pingFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setAirdropAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setCreatorAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCutShortTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setLaunchHardCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"launchTime_","type":"uint256"}],"name":"setLaunchTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_launched","type":"bool"}],"name":"setLaunched","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setNativeMax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setNativeMin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setNativeTotal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"pause_","type":"bool"}],"name":"setSignSwitch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"pause_","type":"bool"}],"name":"setSwapPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setSwapTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setTokenMin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"token","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"stakePingEstimateGas","outputs":[{"internalType":"uint256","name":"pingFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"swapExactETHForTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"swapExactTokensForETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapPause","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenMin","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":"amount","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":"amount","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":"uint256","name":"pongFee","type":"uint256"},{"internalType":"uint256","name":"token","type":"uint256"}],"name":"unStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unStakeNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"unStakeNoncePing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pongFee","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"token","type":"uint256"}],"name":"unStakePingEstimateGas","outputs":[{"internalType":"uint256","name":"pingFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052676124fee993bc0000601355674563918244f40000601455655af3107a4000601555670de0b6b3a76400006016556802b5e3af16b18800006017556102586021556022805460ff1990811690915560646023556024805490911690553480156200006d57600080fd5b506040516200409f3803806200409f83398101604081905262000090916200044c565b8a8a8a8a8a8a8a8a8a88886003620000a98382620005f0565b506004620000b88282620005f0565b505050620000d5620000cf6200031160201b60201c565b62000315565b60016006556009805460ff19169055600b80546001600160a01b03199081166001600160a01b038a81169182179093556011805483169091179055600c879055600d869055600e859055600f8490556010805482168484161790556012805490911691881691909117905583620001865760405162461bcd60e51b815260206004820152601060248201526f3630bab731b410333ab732399032b93960811b60448201526064015b60405180910390fd5b6000600c5411620001da5760405162461bcd60e51b815260206004820152601560248201527f746f74616c20737570706c7920696e697420657272000000000000000000000060448201526064016200017d565b50505050505050505081601a60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087601860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550601860009054906101000a90046001600160a01b03166001600160a01b031663995cf0a46040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000285573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ab9190620006bc565b601980546001600160a01b0319166001600160a01b0392909216919091179055805115620003005780806020019051810190620002e99190620006e1565b6022805460ff1916911515919091179055601b5550505b505050505050505050505062000729565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200038f57600080fd5b81516001600160401b0380821115620003ac57620003ac62000367565b604051601f8301601f19908116603f01168101908282118183101715620003d757620003d762000367565b8160405283815260209250866020858801011115620003f557600080fd5b600091505b83821015620004195785820183015181830184015290820190620003fa565b6000602085830101528094505050505092915050565b80516001600160a01b03811681146200044757600080fd5b919050565b60008060008060008060008060008060006101608c8e0312156200046f57600080fd5b8b516001600160401b038111156200048657600080fd5b620004948e828f016200037d565b60208e0151909c5090506001600160401b03811115620004b357600080fd5b620004c18e828f016200037d565b9a5050620004d260408d016200042f565b9850620004e260608d016200042f565b975060808c0151965060a08c0151955060c08c0151945060e08c015193506200050f6101008d016200042f565b9250620005206101208d016200042f565b6101408d01519092506001600160401b038111156200053e57600080fd5b6200054c8e828f016200037d565b9150509295989b509295989b9093969950565b600181811c908216806200057457607f821691505b6020821081036200059557634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005eb576000816000526020600020601f850160051c81016020861015620005c65750805b601f850160051c820191505b81811015620005e757828155600101620005d2565b5050505b505050565b81516001600160401b038111156200060c576200060c62000367565b62000624816200061d84546200055f565b846200059b565b602080601f8311600181146200065c5760008415620006435750858301515b600019600386901b1c1916600185901b178555620005e7565b600085815260208120601f198616915b828110156200068d578886015182559484019460019091019084016200066c565b5085821015620006ac5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215620006cf57600080fd5b620006da826200042f565b9392505050565b60008060008060808587031215620006f857600080fd5b845193506020850151925060408501519150606085015180151581146200071e57600080fd5b939692955090935050565b61396680620007396000396000f3fe6080604052600436106104265760003560e01c80636b0d3a121161022f57806395d89b4111610139578063b8b971b8116100b6578063e40afab21161007a578063e40afab214610d33578063f00e51f914610d60578063f2fde38b14610d80578063f56f403014610da0578063f765d1c614610db357600080fd5b8063b8b971b814610c93578063c5cc6b6a14610cb3578063d54a5c7a14610cd3578063dd62ed3e14610cf3578063e0d313ab14610d1357600080fd5b8063a457c2d7116100fd578063a457c2d714610be5578063a9059cbb14610c05578063acbd65e614610c25578063b3affc5114610c5d578063b883d89c14610c7357600080fd5b806395d89b4114610b5d578063966dae0e14610b725780639a93883614610b925780639ff46e7414610bb2578063a1fe036214610bd257600080fd5b80637be36869116101c75780638091f3bf1161018b5780638091f3bf14610ac55780638705fcd414610adf5780638708fbbc14610aff5780638da5cb5b14610b1f578063944d928d14610b3d57600080fd5b80637be3686914610a2a5780637d189f1714610a635780637fb181c114610a795780637fb3961c14610a8f5780638014f74914610aa557600080fd5b80636b0d3a121461094d5780636c19e7831461096d57806370a082311461098d578063715018a6146109ad578063763b45ba146109c2578063763f3954146109d8578063786627ce146109eb578063790ca41314610a015780637b0472f014610a1757600080fd5b8063313ce567116103305780634c2c8370116102c85780635c0f7dd11161028c5780635c0f7dd1146108a25780635f04a791146108b85780636715f709146108f35780636723b9621461091357806369ac3a4f1461092d57600080fd5b80634c2c8370146107f25780634e2525e6146108125780634fa579411461083f57806351932c9a1461086c5780635252281a1461088c57600080fd5b8063313ce567146106d557806333195d51146106f1578063335f1b3714610711578063372caeb81461072457806339509351146107375780633c58a1541461075757806341275358146107775780634431665e146107975780634856a0cf146107b757600080fd5b806311232b88116103be57806318160ddd1161038257806318160ddd146106335780631b095b3314610648578063238ac9331461066857806323b872dd1461068857806324fbafb0146106a857600080fd5b806311232b88146105b4578063116d464f146105ca57806314ed913c146105e057806315c3fc21146105f3578063165523931461061357600080fd5b806306fdde031461043d5780630810e632146104685780630902f1ac146104a0578063095ea7b3146104ca5780630d7d9fe6146104fa5780630d8e6e2c1461051a5780630eefd8861461053957806310be675f1461057a57806311106ee21461059457600080fd5b3661043857610436600033610dc9565b005b600080fd5b34801561044957600080fd5b50610452610fd2565b60405161045f9190612fae565b60405180910390f35b34801561047457600080fd5b50601954610488906001600160a01b031681565b6040516001600160a01b03909116815260200161045f565b3480156104ac57600080fd5b506104b5611064565b6040805192835260208301919091520161045f565b3480156104d657600080fd5b506104ea6104e5366004612fdd565b611083565b604051901515815260200161045f565b34801561050657600080fd5b50610436610515366004613009565b61109d565b34801561052657600080fd5b506013545b60405190815260200161045f565b34801561054557600080fd5b506104ea610554366004613022565b600760209081526000938452604080852082529284528284209052825290205460ff1681565b34801561058657600080fd5b506022546104ea9060ff1681565b3480156105a057600080fd5b5061052b6105af366004613068565b6110aa565b3480156105c057600080fd5b5061052b60155481565b3480156105d657600080fd5b5061052b600d5481565b6104366105ee3660046130ad565b6110c8565b3480156105ff57600080fd5b5061043661060e366004613009565b6111fe565b34801561061f57600080fd5b50601054610488906001600160a01b031681565b34801561063f57600080fd5b5060025461052b565b34801561065457600080fd5b506104366106633660046130dd565b61120b565b34801561067457600080fd5b50601a54610488906001600160a01b031681565b34801561069457600080fd5b506104ea6106a33660046130fa565b611226565b3480156106b457600080fd5b5061052b6106c336600461311a565b601f6020526000908152604090205481565b3480156106e157600080fd5b506040516012815260200161045f565b3480156106fd57600080fd5b5061043661070c366004613009565b61124a565b34801561071d57600080fd5b504261052b565b610436610732366004613137565b611257565b34801561074357600080fd5b506104ea610752366004612fdd565b61138f565b34801561076357600080fd5b5061052b610772366004613022565b6113b1565b34801561078357600080fd5b50600b54610488906001600160a01b031681565b3480156107a357600080fd5b506104366107b23660046130dd565b611450565b3480156107c357600080fd5b506104ea6107d2366004612fdd565b602560209081526000928352604080842090915290825290205460ff1681565b3480156107fe57600080fd5b5061052b61080d366004613022565b61146b565b34801561081e57600080fd5b5061052b61082d36600461311a565b60266020526000908152604090205481565b34801561084b57600080fd5b5061052b61085a36600461311a565b601c6020526000908152604090205481565b34801561087857600080fd5b50610436610887366004613009565b6114a3565b34801561089857600080fd5b5061052b60175481565b3480156108ae57600080fd5b5061052b601b5481565b3480156108c457600080fd5b506104ea6108d3366004612fdd565b601e60209081526000928352604080842090915290825290205460ff1681565b3480156108ff57600080fd5b5061052b61090e366004613022565b6114b0565b34801561091f57600080fd5b506024546104ea9060ff1681565b34801561093957600080fd5b506104366109483660046130dd565b6114e8565b34801561095957600080fd5b5061052b61096836600461311a565b611563565b34801561097957600080fd5b5061043661098836600461311a565b6115c6565b34801561099957600080fd5b5061052b6109a836600461311a565b6115f0565b3480156109b957600080fd5b5061043661160b565b3480156109ce57600080fd5b5061052b60165481565b6104366109e63660046131e4565b61161f565b3480156109f757600080fd5b5061052b600a5481565b348015610a0d57600080fd5b5061052b600e5481565b610436610a25366004613137565b611755565b348015610a3657600080fd5b506104ea610a45366004612fdd565b60208080526000928352604080842090915290825290205460ff1681565b348015610a6f57600080fd5b5061052b600f5481565b348015610a8557600080fd5b5061052b60235481565b348015610a9b57600080fd5b5061052b600c5481565b348015610ab157600080fd5b5061052b610ac03660046130ad565b611893565b348015610ad157600080fd5b506009546104ea9060ff1681565b348015610aeb57600080fd5b50610436610afa36600461311a565b6118e2565b348015610b0b57600080fd5b50610436610b1a366004613009565b61190c565b348015610b2b57600080fd5b506005546001600160a01b0316610488565b348015610b4957600080fd5b50610436610b58366004613009565b611919565b348015610b6957600080fd5b50610452611926565b348015610b7e57600080fd5b50601254610488906001600160a01b031681565b348015610b9e57600080fd5b50610436610bad366004613009565b611935565b348015610bbe57600080fd5b50610436610bcd366004613009565b611942565b610436610be036600461327c565b61194f565b348015610bf157600080fd5b506104ea610c00366004612fdd565b611995565b348015610c1157600080fd5b506104ea610c20366004612fdd565b611a10565b348015610c3157600080fd5b5061052b610c403660046132b5565b600860209081526000928352604080842090915290825290205481565b348015610c6957600080fd5b5061052b60145481565b348015610c7f57600080fd5b50610436610c8e36600461311a565b611a1e565b348015610c9f57600080fd5b5061052b610cae3660046132fa565b611a48565b348015610cbf57600080fd5b50601854610488906001600160a01b031681565b348015610cdf57600080fd5b50610436610cee36600461311a565b611a81565b348015610cff57600080fd5b5061052b610d0e366004613379565b611aab565b348015610d1f57600080fd5b50601154610488906001600160a01b031681565b348015610d3f57600080fd5b5061052b610d4e36600461311a565b601d6020526000908152604090205481565b348015610d6c57600080fd5b5061052b610d7b3660046133a7565b611ad6565b348015610d8c57600080fd5b50610436610d9b36600461311a565b611b5c565b610436610dae3660046133dc565b611bd5565b348015610dbf57600080fd5b5061052b60215481565b6000610dd683833461146b565b905082600003610de4578092505b600083610df1833461347a565b610dfb919061347a565b9050601554811015610e285760405162461bcd60e51b8152600401610e1f9061348d565b60405180910390fd5b601454811115610e7a5760405162461bcd60e51b815260206004820152601e60248201527f74686520616d6f756e742063616e6e6f7420626520746f6f206c6172676500006044820152606401610e1f565b60095460ff16610eff57336000908152601c602052604081208054839290610ea39084906134c4565b90915550610eb2905033611563565b336000908152601c60205260409020541115610eff5760405162461bcd60e51b815260206004820152600c60248201526b0e0c2f240e8dede40daeac6d60a31b6044820152606401610e1f565b336000908152601d60205260409020546019546001600160a01b031663549aa4a43485610f2c89876134c4565b610f42610f3a8760016134c4565b8a8c8a611cf2565b336040518663ffffffff1660e01b8152600401610f6294939291906134d7565b6000604051808303818588803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b5050505050601d6000610f9f3390565b6001600160a01b0316815260208101919091526040016000908120805491610fc68361350f565b91905055505050505050565b606060038054610fe190613528565b80601f016020809104026020016040519081016040528092919081815260200182805461100d90613528565b801561105a5780601f1061102f5761010080835404028352916020019161105a565b820191906000526020600020905b81548152906001019060200180831161103d57829003601f168201915b5050505050905090565b60008060405160016235f76760e11b0319815260040160405180910390fd5b600033611091818585611d5a565b60019150505b92915050565b6110a5611e7e565b601455565b600060405160016235f76760e11b0319815260040160405180910390fd5b33816110d3826115f0565b10156111185760405162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b6044820152606401610e1f565b6111228183611ed8565b46600090815260086020908152604080832033845290915281205490611149868686611893565b6019549091506001600160a01b031663549aa4a43483600061117761116f8860016134c4565b8c8c8c611ff8565b336040518663ffffffff1660e01b815260040161119794939291906134d7565b6000604051808303818588803b1580156111b057600080fd5b505af11580156111c4573d6000803e3d6000fd5b5050466000908152600860209081526040808320338452909152812080549450925090506111f18361350f565b9190505550505050505050565b611206611e7e565b602155565b611213611e7e565b6022805460ff1916911515919091179055565b600033611234858285612056565b61123f8585856120ca565b506001949350505050565b611252611e7e565b601755565b61125f612128565b6000811161127f5760405162461bcd60e51b8152600401610e1f90613562565b33600061128d8483856113b1565b905061129984826134c4565b3410156112b85760405162461bcd60e51b8152600401610e1f90613589565b6001600160a01b038216600090815260266020526040812054906112e86112e08360016134c4565b858888612181565b601954604051631526a92960e21b81529192506001600160a01b03169063549aa4a49034906113219087908b90879033906004016134d7565b6000604051808303818588803b15801561133a57600080fd5b505af115801561134e573d6000803e3d6000fd5b5050506001600160a01b03861660009081526026602052604081208054935091506113788361350f565b91905055505050505061138b6001600655565b5050565b6000336110918185856113a28383611aab565b6113ac91906134c4565b611d5a565b336000908152602660205260408120546019546001600160a01b031663cb1b3dd1866113e96113e18560016134c4565b888a89612181565b6040518363ffffffff1660e01b81526004016114069291906135b8565b602060405180830381865afa158015611423573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144791906135d1565b95945050505050565b611458611e7e565b6024805460ff1916911515919091179055565b336000908152601d60205260408120546019546001600160a01b031663cb1b3dd1866113e961149b8560016134c4565b888a89611cf2565b6114ab611e7e565b601555565b336000908152601f60205260408120546019546001600160a01b031663cb1b3dd1866113e96114e08560016134c4565b888a8961218a565b601a546001600160a01b031633148061150b57506005546001600160a01b031633145b6115505760405162461bcd60e51b81526020600482015260166024820152751bdb9b1e481cda59db995c8bdbdddb995c8818d85b1b60521b6044820152606401610e1f565b6009805460ff1916911515919091179055565b60105460009081906001600160a01b039081169084160361159357601b5461158c90600a6135ea565b9050611598565b50601b545b806000036115b2576064600d546115af9190613601565b90505b600d548111156110975750600d5492915050565b6115ce611e7e565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b031660009081526020819052604090205490565b611613611e7e565b61161d6000612193565b565b601260009054906101000a90046001600160a01b03166001600160a01b031663995cf0a46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116969190613623565b6001600160a01b0316336001600160a01b0316146117045760405162461bcd60e51b815260206004820152602560248201527f4c696b77696450726f647563743a2063616c6c6572206d757374206265206368604482015264185b9b995b60da1b6064820152608401610e1f565b7ff496afe4c96f98ccadfe979e32fee625d67b649ab3b164a018eedbaecdcb7b2a858534846040516117399493929190613640565b60405180910390a161174e85858585856121e5565b5050505050565b61175d612128565b6000821161177d5760405162461bcd60e51b8152600401610e1f90613562565b3382611788826115f0565b10156117d65760405162461bcd60e51b815260206004820152601c60248201527f7374616b6520616d6f756e7420657863656564732062616c616e6365000000006044820152606401610e1f565b60006117e3828585611ad6565b9050803410156118055760405162461bcd60e51b8152600401610e1f90613589565b600061181283868661230b565b905061181e8386611ed8565b6019546001600160a01b031663549aa4a43484600085336040518663ffffffff1660e01b815260040161185494939291906134d7565b6000604051808303818588803b15801561186d57600080fd5b505af1158015611881573d6000803e3d6000fd5b505050505050505061138b6001600655565b6001600160401b03831660009081526008602090815260408083206001600160a01b038087168552925282205460195490911663cb1b3dd1836113e96118da8560016134c4565b898989611ff8565b6118ea611e7e565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b611914611e7e565b602355565b611921611e7e565b601655565b606060048054610fe190613528565b61193d611e7e565b600f55565b61194a611e7e565b600e55565b611957612128565b60245460ff161561197a5760405162461bcd60e51b8152600401610e1f90613676565b61198683338385612375565b6119906001600655565b505050565b600033816119a38286611aab565b905083811015611a035760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e1f565b61123f8286868403611d5a565b6000336110918185856120ca565b611a26611e7e565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b600084848484604051602001611a61949392919061369a565b604051602081830303815290604052805190602001209050949350505050565b611a89611e7e565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6019546000906001600160a01b031663cb1b3dd182611af687878761230b565b6040518363ffffffff1660e01b8152600401611b139291906135b8565b602060405180830381865afa158015611b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5491906135d1565b949350505050565b611b64611e7e565b6001600160a01b038116611bc95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e1f565b611bd281612193565b50565b611bdd612128565b60245460ff1615611c005760405162461bcd60e51b8152600401610e1f90613676565b60225460ff168015611c15575060095460ff16155b15611cd8576000611c4a6040518060400160405280600381526020016262757960e81b815250611c43611926565b3433611a48565b601a54604080516020601f8701819004810282018101909252858152929350611c9b926001600160a01b03909216918491879087908190840183828082843760009201919091525061254e92505050565b611cd65760405162461bcd60e51b815260206004820152600c60248201526b3b32b934b33c9032b93937b960a11b6044820152606401610e1f565b505b611ce28484610dc9565b611cec6001600655565b50505050565b606060005b611cff611926565b60408051602081018990526001600160a01b0388168183015260608082018790528251808303909101815260808201909252611d41939291879160a0016136fc565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611dbc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e1f565b6001600160a01b038216611e1d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e1f565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6005546001600160a01b0316331461161d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e1f565b6001600160a01b038216611f385760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610e1f565b6001600160a01b03821660009081526020819052604090205481811015611fac5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610e1f565b6001600160a01b038316600081815260208181526040808320868603905560028054879003905551858152919291600080516020613911833981519152910160405180910390a3505050565b60606004612004611926565b60408051602081018990526001600160401b038816818301526001600160a01b038716606082015260808082018790528251808303909101815260a08201909252611d4193929160009160c00161373b565b60006120628484611aab565b90506000198114611cec57818110156120bd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e1f565b611cec8484848403611d5a565b3330148015906120e257506001600160a01b03821630145b1561211d5760405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b6044820152606401610e1f565b6119908383836125af565b60026006540361217a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e1f565b6002600655565b60606006611cf7565b60606002611cf7565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60001960ff8416016122305760008060008060008580602001905181019061220d9190613772565b945094509450945094506122268a8a868686868b612741565b505050505061174e565b60021960ff841601612275576000806000808480602001905181019061225691906137ca565b935093509350935061226c8989858486896127f5565b5050505061174e565b60061960ff8416016122b35760008060008380602001905181019061229a9190613808565b9250925092506122ab8282856128f2565b50505061174e565b60031960ff8416016122ef57600080600080848060200190518101906122d99190613841565b935093509350935061226c898985858589612974565b60405160016235f76760e11b0319815260040160405180910390fd5b60606005612317611926565b604080516001600160a01b03881660208201529081018690526060810185905260009060800160408051601f198184030181529082905261235d9493929160200161373b565b60405160208183030381529060405290509392505050565b600081116123b65760405162461bcd60e51b815260206004820152600e60248201526d30b6b7bab73a1034b71032b9391760911b6044820152606401610e1f565b806123c0846115f0565b101561240e5760405162461bcd60e51b815260206004820152601b60248201527f73656c6c20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610e1f565b600061241b8584846114b0565b905084600003612429578094505b61243385826134c4565b3410156124525760405162461bcd60e51b8152600401610e1f90613589565b6016548210156124745760405162461bcd60e51b8152600401610e1f9061348d565b336000908152601f60205260408120549061249b6124938360016134c4565b86898761218a565b90506124a78685611ed8565b6019546001600160a01b031663549aa4a434858a85336040518663ffffffff1660e01b81526004016124dc94939291906134d7565b6000604051808303818588803b1580156124f557600080fd5b505af1158015612509573d6000803e3d6000fd5b5050505050601f60006125193390565b6001600160a01b03168152602081019190915260400160009081208054916125408361350f565b919050555050505050505050565b600080600061255d8585612abf565b90925090506000816004811115612576576125766136e6565b1480156125945750856001600160a01b0316826001600160a01b0316145b806125a557506125a5868686612b04565b9695505050505050565b6001600160a01b0383166126135760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610e1f565b6001600160a01b0382166126755760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610e1f565b6001600160a01b038316600090815260208190526040902054818110156126ed5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e1f565b6001600160a01b0384811660008181526020818152604080832087870390559387168083529184902080548701905592518581529092600080516020613911833981519152910160405180910390a3611cec565b6001600160a01b0385166000908152601e6020908152604080832084845290915290205460ff16156127855760405162461bcd60e51b8152600401610e1f9061388a565b60095460ff1661279e576009805460ff19168315151790555b6001600160a01b0385166000908152601e602090815260408083208484529091529020805460ff1916600117905582156127dc576127dc8584612bf0565b83156127ec576127ec8585612c9d565b50505050505050565b6001600160a01b03841660009081526020808052604080832084845290915290205460ff16156128375760405162461bcd60e51b8152600401610e1f9061388a565b6001600160a01b0384166000908152602080805260408083208484529091529020805460ff1916600117905560095460ff166128da576001600160a01b0384166000908152601c60205260409020548310156128c0576001600160a01b0384166000908152601c6020526040812080548592906128b590849061347a565b909155506128da9050565b6001600160a01b0384166000908152601c60205260408120555b82156128ea576128ea8484612c9d565b505050505050565b6001600160a01b038316600090815260256020908152604080832084845290915290205460ff16156129365760405162461bcd60e51b8152600401610e1f9061388a565b6001600160a01b03831660009081526025602090815260408083208484529091529020805460ff191660011790558115611990576119908383612bf0565b6001600160401b03861660009081526007602090815260408083206001600160a01b0387168452825280832084845290915290205460ff16156129c95760405162461bcd60e51b8152600401610e1f9061388a565b6001600160401b0380871660009081526007602090815260408083206001600160a01b038816845282528083208584529091529020805460ff1916600117905584164614612a485760405162461bcd60e51b815260206004820152600c60248201526b31b430b4b71034b21032b93960a11b6044820152606401610e1f565b8115612a5857612a588383612bf0565b604080516001600160401b03881681526001600160a01b0385166020820181905281830152606081018490526080810183905290517f1c632a7a248c29ea7884a8324f916f13dbb7519f10f16833f711879a8aa670d29181900360a00190a1505050505050565b6000808251604103612af55760208301516040840151606085015160001a612ae987828585612d3a565b94509450505050612afd565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b8686604051602401612b2e9291906135b8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612b6c91906138b4565b600060405180830381855afa9150503d8060008114612ba7576040519150601f19603f3d011682016040523d82523d6000602084013e612bac565b606091505b5091509150818015612bc057506020815110155b80156125a557508051630b135d3f60e11b90612be590830160209081019084016135d1565b149695505050505050565b6001600160a01b038216612c465760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610e1f565b8060026000828254612c5891906134c4565b90915550506001600160a01b03821660008181526020818152604080832080548601905551848152600080516020613911833981519152910160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612cea576040519150601f19603f3d011682016040523d82523d6000602084013e612cef565b606091505b5050905080612cfd83612df4565b604051602001612d0d91906138d0565b60405160208183030381529060405290611cec5760405162461bcd60e51b8152600401610e1f9190612fae565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115612d675750600090506003612deb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612dbb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612de457600060019250925050612deb565b9150600090505b94509492505050565b60606000612e0183612e86565b60010190506000816001600160401b03811115612e2057612e20613159565b6040519080825280601f01601f191660200182016040528015612e4a576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612e5457509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612ec55772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612ef1576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612f0f57662386f26fc10000830492506010015b6305f5e1008310612f27576305f5e100830492506008015b6127108310612f3b57612710830492506004015b60648310612f4d576064830492506002015b600a83106110975760010192915050565b60005b83811015612f79578181015183820152602001612f61565b50506000910152565b60008151808452612f9a816020860160208601612f5e565b601f01601f19169290920160200192915050565b602081526000612fc16020830184612f82565b9392505050565b6001600160a01b0381168114611bd257600080fd5b60008060408385031215612ff057600080fd5b8235612ffb81612fc8565b946020939093013593505050565b60006020828403121561301b57600080fd5b5035919050565b60008060006060848603121561303757600080fd5b83359250602084013561304981612fc8565b929592945050506040919091013590565b8015158114611bd257600080fd5b6000806040838503121561307b57600080fd5b82359150602083013561308d8161305a565b809150509250929050565b6001600160401b0381168114611bd257600080fd5b6000806000606084860312156130c257600080fd5b83356130cd81613098565b9250602084013561304981612fc8565b6000602082840312156130ef57600080fd5b8135612fc18161305a565b60008060006060848603121561310f57600080fd5b83356130cd81612fc8565b60006020828403121561312c57600080fd5b8135612fc181612fc8565b6000806040838503121561314a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b038084111561318957613189613159565b604051601f8501601f19908116603f011681019082821181831017156131b1576131b1613159565b816040528093508581528686860111156131ca57600080fd5b858560208301376000602087830101525050509392505050565b600080600080600060a086880312156131fc57600080fd5b853561320781613098565b9450602086013561321781612fc8565b9350604086013560ff8116811461322d57600080fd5b92506060860135915060808601356001600160401b0381111561324f57600080fd5b8601601f8101881361326057600080fd5b61326f8882356020840161316f565b9150509295509295909350565b60008060006060848603121561329157600080fd5b833592506020840135915060408401356132aa81612fc8565b809150509250925092565b600080604083850312156132c857600080fd5b82359150602083013561308d81612fc8565b600082601f8301126132eb57600080fd5b612fc18383356020850161316f565b6000806000806080858703121561331057600080fd5b84356001600160401b038082111561332757600080fd5b613333888389016132da565b9550602087013591508082111561334957600080fd5b50613356878288016132da565b93505060408501359150606085013561336e81612fc8565b939692955090935050565b6000806040838503121561338c57600080fd5b823561339781612fc8565b9150602083013561308d81612fc8565b6000806000606084860312156133bc57600080fd5b83356133c781612fc8565b95602085013595506040909401359392505050565b600080600080606085870312156133f257600080fd5b84359350602085013561340481612fc8565b925060408501356001600160401b038082111561342057600080fd5b818701915087601f83011261343457600080fd5b81358181111561344357600080fd5b88602082850101111561345557600080fd5b95989497505060200194505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561109757611097613464565b6020808252601e908201527f74686520616d6f756e742063616e6e6f7420626520746f6f20736d616c6c0000604082015260600190565b8082018082111561109757611097613464565b8481528360208201526080604082015260006134f66080830185612f82565b905060018060a01b038316606083015295945050505050565b60006001820161352157613521613464565b5060010190565b600181811c9082168061353c57607f821691505b60208210810361355c57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600d908201526c3a37b5b2b71034b71032b9391760991b604082015260600190565b6020808252601590820152740c4e4d2c8ceca40cccaca40dcdee840cadcdeeaced605b1b604082015260600190565b828152604060208201526000611b546040830184612f82565b6000602082840312156135e357600080fd5b5051919050565b808202811582820484141761109757611097613464565b60008261361e57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561363557600080fd5b8151612fc181612fc8565b6001600160401b038516815260018060a01b03841660208201528260408201526080606082015260006125a56080830184612f82565b6020808252600a90820152697377617020706175736560b01b604082015260600190565b600085516136ac818460208a01612f5e565b8551908301906136c0818360208a01612f5e565b01938452505060601b6bffffffffffffffffffffffff1916602082015260340192915050565b634e487b7160e01b600052602160045260246000fd5b60ff851681526080602082015260006137186080830186612f82565b84604084015282810360608401526137308185612f82565b979650505050505050565b60ff851681526080602082015260006137576080830186612f82565b60ff8516604084015282810360608401526137308185612f82565b600080600080600060a0868803121561378a57600080fd5b85519450602086015161379c81612fc8565b80945050604086015192506060860151915060808601516137bc8161305a565b809150509295509295909350565b600080600080608085870312156137e057600080fd5b8451935060208501516137f281612fc8565b6040860151606090960151949790965092505050565b60008060006060848603121561381d57600080fd5b83519250602084015161382f81612fc8565b80925050604084015190509250925092565b6000806000806080858703121561385757600080fd5b84519350602085015161386981613098565b604086015190935061387a81612fc8565b6060959095015193969295505050565b60208082526010908201526f3737b731b2903932b832ba34ba34b7b760811b604082015260600190565b600082516138c6818460208701612f5e565b9190910192915050565b77283937b23ab1ba102a3930b739b332b9103330b4b632b21760411b815260008251613903816018850160208701612f5e565b919091016018019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122031cf79bb9bc6dcac76ba40156b19c0bb95e5d71c9ca3f01320407cae981d01c064736f6c63430008170033000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000ea7744c4fa1101f9e6df5688fc19e3ee941064390000000000000000000000004cdbc49a24c634d67642de875088a45fec39bf53000000000000000000000000000000000000000000084595161401484a000000000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000066d6c1a80000000000000000000000000000000000000000000000000f43fc2c04ee00000000000000000000000000004d7de41c9e128f8fcfdf479a533987320520fc9f000000000000000000000000ca709ea906207b44521f03ecf5b594d247dffac5000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000245b4c494b5749445d204c696b7769642053686f727461626c6520546f6b656e2064656d6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044c535444000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106104265760003560e01c80636b0d3a121161022f57806395d89b4111610139578063b8b971b8116100b6578063e40afab21161007a578063e40afab214610d33578063f00e51f914610d60578063f2fde38b14610d80578063f56f403014610da0578063f765d1c614610db357600080fd5b8063b8b971b814610c93578063c5cc6b6a14610cb3578063d54a5c7a14610cd3578063dd62ed3e14610cf3578063e0d313ab14610d1357600080fd5b8063a457c2d7116100fd578063a457c2d714610be5578063a9059cbb14610c05578063acbd65e614610c25578063b3affc5114610c5d578063b883d89c14610c7357600080fd5b806395d89b4114610b5d578063966dae0e14610b725780639a93883614610b925780639ff46e7414610bb2578063a1fe036214610bd257600080fd5b80637be36869116101c75780638091f3bf1161018b5780638091f3bf14610ac55780638705fcd414610adf5780638708fbbc14610aff5780638da5cb5b14610b1f578063944d928d14610b3d57600080fd5b80637be3686914610a2a5780637d189f1714610a635780637fb181c114610a795780637fb3961c14610a8f5780638014f74914610aa557600080fd5b80636b0d3a121461094d5780636c19e7831461096d57806370a082311461098d578063715018a6146109ad578063763b45ba146109c2578063763f3954146109d8578063786627ce146109eb578063790ca41314610a015780637b0472f014610a1757600080fd5b8063313ce567116103305780634c2c8370116102c85780635c0f7dd11161028c5780635c0f7dd1146108a25780635f04a791146108b85780636715f709146108f35780636723b9621461091357806369ac3a4f1461092d57600080fd5b80634c2c8370146107f25780634e2525e6146108125780634fa579411461083f57806351932c9a1461086c5780635252281a1461088c57600080fd5b8063313ce567146106d557806333195d51146106f1578063335f1b3714610711578063372caeb81461072457806339509351146107375780633c58a1541461075757806341275358146107775780634431665e146107975780634856a0cf146107b757600080fd5b806311232b88116103be57806318160ddd1161038257806318160ddd146106335780631b095b3314610648578063238ac9331461066857806323b872dd1461068857806324fbafb0146106a857600080fd5b806311232b88146105b4578063116d464f146105ca57806314ed913c146105e057806315c3fc21146105f3578063165523931461061357600080fd5b806306fdde031461043d5780630810e632146104685780630902f1ac146104a0578063095ea7b3146104ca5780630d7d9fe6146104fa5780630d8e6e2c1461051a5780630eefd8861461053957806310be675f1461057a57806311106ee21461059457600080fd5b3661043857610436600033610dc9565b005b600080fd5b34801561044957600080fd5b50610452610fd2565b60405161045f9190612fae565b60405180910390f35b34801561047457600080fd5b50601954610488906001600160a01b031681565b6040516001600160a01b03909116815260200161045f565b3480156104ac57600080fd5b506104b5611064565b6040805192835260208301919091520161045f565b3480156104d657600080fd5b506104ea6104e5366004612fdd565b611083565b604051901515815260200161045f565b34801561050657600080fd5b50610436610515366004613009565b61109d565b34801561052657600080fd5b506013545b60405190815260200161045f565b34801561054557600080fd5b506104ea610554366004613022565b600760209081526000938452604080852082529284528284209052825290205460ff1681565b34801561058657600080fd5b506022546104ea9060ff1681565b3480156105a057600080fd5b5061052b6105af366004613068565b6110aa565b3480156105c057600080fd5b5061052b60155481565b3480156105d657600080fd5b5061052b600d5481565b6104366105ee3660046130ad565b6110c8565b3480156105ff57600080fd5b5061043661060e366004613009565b6111fe565b34801561061f57600080fd5b50601054610488906001600160a01b031681565b34801561063f57600080fd5b5060025461052b565b34801561065457600080fd5b506104366106633660046130dd565b61120b565b34801561067457600080fd5b50601a54610488906001600160a01b031681565b34801561069457600080fd5b506104ea6106a33660046130fa565b611226565b3480156106b457600080fd5b5061052b6106c336600461311a565b601f6020526000908152604090205481565b3480156106e157600080fd5b506040516012815260200161045f565b3480156106fd57600080fd5b5061043661070c366004613009565b61124a565b34801561071d57600080fd5b504261052b565b610436610732366004613137565b611257565b34801561074357600080fd5b506104ea610752366004612fdd565b61138f565b34801561076357600080fd5b5061052b610772366004613022565b6113b1565b34801561078357600080fd5b50600b54610488906001600160a01b031681565b3480156107a357600080fd5b506104366107b23660046130dd565b611450565b3480156107c357600080fd5b506104ea6107d2366004612fdd565b602560209081526000928352604080842090915290825290205460ff1681565b3480156107fe57600080fd5b5061052b61080d366004613022565b61146b565b34801561081e57600080fd5b5061052b61082d36600461311a565b60266020526000908152604090205481565b34801561084b57600080fd5b5061052b61085a36600461311a565b601c6020526000908152604090205481565b34801561087857600080fd5b50610436610887366004613009565b6114a3565b34801561089857600080fd5b5061052b60175481565b3480156108ae57600080fd5b5061052b601b5481565b3480156108c457600080fd5b506104ea6108d3366004612fdd565b601e60209081526000928352604080842090915290825290205460ff1681565b3480156108ff57600080fd5b5061052b61090e366004613022565b6114b0565b34801561091f57600080fd5b506024546104ea9060ff1681565b34801561093957600080fd5b506104366109483660046130dd565b6114e8565b34801561095957600080fd5b5061052b61096836600461311a565b611563565b34801561097957600080fd5b5061043661098836600461311a565b6115c6565b34801561099957600080fd5b5061052b6109a836600461311a565b6115f0565b3480156109b957600080fd5b5061043661160b565b3480156109ce57600080fd5b5061052b60165481565b6104366109e63660046131e4565b61161f565b3480156109f757600080fd5b5061052b600a5481565b348015610a0d57600080fd5b5061052b600e5481565b610436610a25366004613137565b611755565b348015610a3657600080fd5b506104ea610a45366004612fdd565b60208080526000928352604080842090915290825290205460ff1681565b348015610a6f57600080fd5b5061052b600f5481565b348015610a8557600080fd5b5061052b60235481565b348015610a9b57600080fd5b5061052b600c5481565b348015610ab157600080fd5b5061052b610ac03660046130ad565b611893565b348015610ad157600080fd5b506009546104ea9060ff1681565b348015610aeb57600080fd5b50610436610afa36600461311a565b6118e2565b348015610b0b57600080fd5b50610436610b1a366004613009565b61190c565b348015610b2b57600080fd5b506005546001600160a01b0316610488565b348015610b4957600080fd5b50610436610b58366004613009565b611919565b348015610b6957600080fd5b50610452611926565b348015610b7e57600080fd5b50601254610488906001600160a01b031681565b348015610b9e57600080fd5b50610436610bad366004613009565b611935565b348015610bbe57600080fd5b50610436610bcd366004613009565b611942565b610436610be036600461327c565b61194f565b348015610bf157600080fd5b506104ea610c00366004612fdd565b611995565b348015610c1157600080fd5b506104ea610c20366004612fdd565b611a10565b348015610c3157600080fd5b5061052b610c403660046132b5565b600860209081526000928352604080842090915290825290205481565b348015610c6957600080fd5b5061052b60145481565b348015610c7f57600080fd5b50610436610c8e36600461311a565b611a1e565b348015610c9f57600080fd5b5061052b610cae3660046132fa565b611a48565b348015610cbf57600080fd5b50601854610488906001600160a01b031681565b348015610cdf57600080fd5b50610436610cee36600461311a565b611a81565b348015610cff57600080fd5b5061052b610d0e366004613379565b611aab565b348015610d1f57600080fd5b50601154610488906001600160a01b031681565b348015610d3f57600080fd5b5061052b610d4e36600461311a565b601d6020526000908152604090205481565b348015610d6c57600080fd5b5061052b610d7b3660046133a7565b611ad6565b348015610d8c57600080fd5b50610436610d9b36600461311a565b611b5c565b610436610dae3660046133dc565b611bd5565b348015610dbf57600080fd5b5061052b60215481565b6000610dd683833461146b565b905082600003610de4578092505b600083610df1833461347a565b610dfb919061347a565b9050601554811015610e285760405162461bcd60e51b8152600401610e1f9061348d565b60405180910390fd5b601454811115610e7a5760405162461bcd60e51b815260206004820152601e60248201527f74686520616d6f756e742063616e6e6f7420626520746f6f206c6172676500006044820152606401610e1f565b60095460ff16610eff57336000908152601c602052604081208054839290610ea39084906134c4565b90915550610eb2905033611563565b336000908152601c60205260409020541115610eff5760405162461bcd60e51b815260206004820152600c60248201526b0e0c2f240e8dede40daeac6d60a31b6044820152606401610e1f565b336000908152601d60205260409020546019546001600160a01b031663549aa4a43485610f2c89876134c4565b610f42610f3a8760016134c4565b8a8c8a611cf2565b336040518663ffffffff1660e01b8152600401610f6294939291906134d7565b6000604051808303818588803b158015610f7b57600080fd5b505af1158015610f8f573d6000803e3d6000fd5b5050505050601d6000610f9f3390565b6001600160a01b0316815260208101919091526040016000908120805491610fc68361350f565b91905055505050505050565b606060038054610fe190613528565b80601f016020809104026020016040519081016040528092919081815260200182805461100d90613528565b801561105a5780601f1061102f5761010080835404028352916020019161105a565b820191906000526020600020905b81548152906001019060200180831161103d57829003601f168201915b5050505050905090565b60008060405160016235f76760e11b0319815260040160405180910390fd5b600033611091818585611d5a565b60019150505b92915050565b6110a5611e7e565b601455565b600060405160016235f76760e11b0319815260040160405180910390fd5b33816110d3826115f0565b10156111185760405162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b6044820152606401610e1f565b6111228183611ed8565b46600090815260086020908152604080832033845290915281205490611149868686611893565b6019549091506001600160a01b031663549aa4a43483600061117761116f8860016134c4565b8c8c8c611ff8565b336040518663ffffffff1660e01b815260040161119794939291906134d7565b6000604051808303818588803b1580156111b057600080fd5b505af11580156111c4573d6000803e3d6000fd5b5050466000908152600860209081526040808320338452909152812080549450925090506111f18361350f565b9190505550505050505050565b611206611e7e565b602155565b611213611e7e565b6022805460ff1916911515919091179055565b600033611234858285612056565b61123f8585856120ca565b506001949350505050565b611252611e7e565b601755565b61125f612128565b6000811161127f5760405162461bcd60e51b8152600401610e1f90613562565b33600061128d8483856113b1565b905061129984826134c4565b3410156112b85760405162461bcd60e51b8152600401610e1f90613589565b6001600160a01b038216600090815260266020526040812054906112e86112e08360016134c4565b858888612181565b601954604051631526a92960e21b81529192506001600160a01b03169063549aa4a49034906113219087908b90879033906004016134d7565b6000604051808303818588803b15801561133a57600080fd5b505af115801561134e573d6000803e3d6000fd5b5050506001600160a01b03861660009081526026602052604081208054935091506113788361350f565b91905055505050505061138b6001600655565b5050565b6000336110918185856113a28383611aab565b6113ac91906134c4565b611d5a565b336000908152602660205260408120546019546001600160a01b031663cb1b3dd1866113e96113e18560016134c4565b888a89612181565b6040518363ffffffff1660e01b81526004016114069291906135b8565b602060405180830381865afa158015611423573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144791906135d1565b95945050505050565b611458611e7e565b6024805460ff1916911515919091179055565b336000908152601d60205260408120546019546001600160a01b031663cb1b3dd1866113e961149b8560016134c4565b888a89611cf2565b6114ab611e7e565b601555565b336000908152601f60205260408120546019546001600160a01b031663cb1b3dd1866113e96114e08560016134c4565b888a8961218a565b601a546001600160a01b031633148061150b57506005546001600160a01b031633145b6115505760405162461bcd60e51b81526020600482015260166024820152751bdb9b1e481cda59db995c8bdbdddb995c8818d85b1b60521b6044820152606401610e1f565b6009805460ff1916911515919091179055565b60105460009081906001600160a01b039081169084160361159357601b5461158c90600a6135ea565b9050611598565b50601b545b806000036115b2576064600d546115af9190613601565b90505b600d548111156110975750600d5492915050565b6115ce611e7e565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b031660009081526020819052604090205490565b611613611e7e565b61161d6000612193565b565b601260009054906101000a90046001600160a01b03166001600160a01b031663995cf0a46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116969190613623565b6001600160a01b0316336001600160a01b0316146117045760405162461bcd60e51b815260206004820152602560248201527f4c696b77696450726f647563743a2063616c6c6572206d757374206265206368604482015264185b9b995b60da1b6064820152608401610e1f565b7ff496afe4c96f98ccadfe979e32fee625d67b649ab3b164a018eedbaecdcb7b2a858534846040516117399493929190613640565b60405180910390a161174e85858585856121e5565b5050505050565b61175d612128565b6000821161177d5760405162461bcd60e51b8152600401610e1f90613562565b3382611788826115f0565b10156117d65760405162461bcd60e51b815260206004820152601c60248201527f7374616b6520616d6f756e7420657863656564732062616c616e6365000000006044820152606401610e1f565b60006117e3828585611ad6565b9050803410156118055760405162461bcd60e51b8152600401610e1f90613589565b600061181283868661230b565b905061181e8386611ed8565b6019546001600160a01b031663549aa4a43484600085336040518663ffffffff1660e01b815260040161185494939291906134d7565b6000604051808303818588803b15801561186d57600080fd5b505af1158015611881573d6000803e3d6000fd5b505050505050505061138b6001600655565b6001600160401b03831660009081526008602090815260408083206001600160a01b038087168552925282205460195490911663cb1b3dd1836113e96118da8560016134c4565b898989611ff8565b6118ea611e7e565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b611914611e7e565b602355565b611921611e7e565b601655565b606060048054610fe190613528565b61193d611e7e565b600f55565b61194a611e7e565b600e55565b611957612128565b60245460ff161561197a5760405162461bcd60e51b8152600401610e1f90613676565b61198683338385612375565b6119906001600655565b505050565b600033816119a38286611aab565b905083811015611a035760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e1f565b61123f8286868403611d5a565b6000336110918185856120ca565b611a26611e7e565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b600084848484604051602001611a61949392919061369a565b604051602081830303815290604052805190602001209050949350505050565b611a89611e7e565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6019546000906001600160a01b031663cb1b3dd182611af687878761230b565b6040518363ffffffff1660e01b8152600401611b139291906135b8565b602060405180830381865afa158015611b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5491906135d1565b949350505050565b611b64611e7e565b6001600160a01b038116611bc95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e1f565b611bd281612193565b50565b611bdd612128565b60245460ff1615611c005760405162461bcd60e51b8152600401610e1f90613676565b60225460ff168015611c15575060095460ff16155b15611cd8576000611c4a6040518060400160405280600381526020016262757960e81b815250611c43611926565b3433611a48565b601a54604080516020601f8701819004810282018101909252858152929350611c9b926001600160a01b03909216918491879087908190840183828082843760009201919091525061254e92505050565b611cd65760405162461bcd60e51b815260206004820152600c60248201526b3b32b934b33c9032b93937b960a11b6044820152606401610e1f565b505b611ce28484610dc9565b611cec6001600655565b50505050565b606060005b611cff611926565b60408051602081018990526001600160a01b0388168183015260608082018790528251808303909101815260808201909252611d41939291879160a0016136fc565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611dbc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e1f565b6001600160a01b038216611e1d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e1f565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6005546001600160a01b0316331461161d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e1f565b6001600160a01b038216611f385760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610e1f565b6001600160a01b03821660009081526020819052604090205481811015611fac5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610e1f565b6001600160a01b038316600081815260208181526040808320868603905560028054879003905551858152919291600080516020613911833981519152910160405180910390a3505050565b60606004612004611926565b60408051602081018990526001600160401b038816818301526001600160a01b038716606082015260808082018790528251808303909101815260a08201909252611d4193929160009160c00161373b565b60006120628484611aab565b90506000198114611cec57818110156120bd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e1f565b611cec8484848403611d5a565b3330148015906120e257506001600160a01b03821630145b1561211d5760405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b6044820152606401610e1f565b6119908383836125af565b60026006540361217a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e1f565b6002600655565b60606006611cf7565b60606002611cf7565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60001960ff8416016122305760008060008060008580602001905181019061220d9190613772565b945094509450945094506122268a8a868686868b612741565b505050505061174e565b60021960ff841601612275576000806000808480602001905181019061225691906137ca565b935093509350935061226c8989858486896127f5565b5050505061174e565b60061960ff8416016122b35760008060008380602001905181019061229a9190613808565b9250925092506122ab8282856128f2565b50505061174e565b60031960ff8416016122ef57600080600080848060200190518101906122d99190613841565b935093509350935061226c898985858589612974565b60405160016235f76760e11b0319815260040160405180910390fd5b60606005612317611926565b604080516001600160a01b03881660208201529081018690526060810185905260009060800160408051601f198184030181529082905261235d9493929160200161373b565b60405160208183030381529060405290509392505050565b600081116123b65760405162461bcd60e51b815260206004820152600e60248201526d30b6b7bab73a1034b71032b9391760911b6044820152606401610e1f565b806123c0846115f0565b101561240e5760405162461bcd60e51b815260206004820152601b60248201527f73656c6c20616d6f756e7420657863656564732062616c616e636500000000006044820152606401610e1f565b600061241b8584846114b0565b905084600003612429578094505b61243385826134c4565b3410156124525760405162461bcd60e51b8152600401610e1f90613589565b6016548210156124745760405162461bcd60e51b8152600401610e1f9061348d565b336000908152601f60205260408120549061249b6124938360016134c4565b86898761218a565b90506124a78685611ed8565b6019546001600160a01b031663549aa4a434858a85336040518663ffffffff1660e01b81526004016124dc94939291906134d7565b6000604051808303818588803b1580156124f557600080fd5b505af1158015612509573d6000803e3d6000fd5b5050505050601f60006125193390565b6001600160a01b03168152602081019190915260400160009081208054916125408361350f565b919050555050505050505050565b600080600061255d8585612abf565b90925090506000816004811115612576576125766136e6565b1480156125945750856001600160a01b0316826001600160a01b0316145b806125a557506125a5868686612b04565b9695505050505050565b6001600160a01b0383166126135760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610e1f565b6001600160a01b0382166126755760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610e1f565b6001600160a01b038316600090815260208190526040902054818110156126ed5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e1f565b6001600160a01b0384811660008181526020818152604080832087870390559387168083529184902080548701905592518581529092600080516020613911833981519152910160405180910390a3611cec565b6001600160a01b0385166000908152601e6020908152604080832084845290915290205460ff16156127855760405162461bcd60e51b8152600401610e1f9061388a565b60095460ff1661279e576009805460ff19168315151790555b6001600160a01b0385166000908152601e602090815260408083208484529091529020805460ff1916600117905582156127dc576127dc8584612bf0565b83156127ec576127ec8585612c9d565b50505050505050565b6001600160a01b03841660009081526020808052604080832084845290915290205460ff16156128375760405162461bcd60e51b8152600401610e1f9061388a565b6001600160a01b0384166000908152602080805260408083208484529091529020805460ff1916600117905560095460ff166128da576001600160a01b0384166000908152601c60205260409020548310156128c0576001600160a01b0384166000908152601c6020526040812080548592906128b590849061347a565b909155506128da9050565b6001600160a01b0384166000908152601c60205260408120555b82156128ea576128ea8484612c9d565b505050505050565b6001600160a01b038316600090815260256020908152604080832084845290915290205460ff16156129365760405162461bcd60e51b8152600401610e1f9061388a565b6001600160a01b03831660009081526025602090815260408083208484529091529020805460ff191660011790558115611990576119908383612bf0565b6001600160401b03861660009081526007602090815260408083206001600160a01b0387168452825280832084845290915290205460ff16156129c95760405162461bcd60e51b8152600401610e1f9061388a565b6001600160401b0380871660009081526007602090815260408083206001600160a01b038816845282528083208584529091529020805460ff1916600117905584164614612a485760405162461bcd60e51b815260206004820152600c60248201526b31b430b4b71034b21032b93960a11b6044820152606401610e1f565b8115612a5857612a588383612bf0565b604080516001600160401b03881681526001600160a01b0385166020820181905281830152606081018490526080810183905290517f1c632a7a248c29ea7884a8324f916f13dbb7519f10f16833f711879a8aa670d29181900360a00190a1505050505050565b6000808251604103612af55760208301516040840151606085015160001a612ae987828585612d3a565b94509450505050612afd565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b8686604051602401612b2e9291906135b8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612b6c91906138b4565b600060405180830381855afa9150503d8060008114612ba7576040519150601f19603f3d011682016040523d82523d6000602084013e612bac565b606091505b5091509150818015612bc057506020815110155b80156125a557508051630b135d3f60e11b90612be590830160209081019084016135d1565b149695505050505050565b6001600160a01b038216612c465760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610e1f565b8060026000828254612c5891906134c4565b90915550506001600160a01b03821660008181526020818152604080832080548601905551848152600080516020613911833981519152910160405180910390a35050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612cea576040519150601f19603f3d011682016040523d82523d6000602084013e612cef565b606091505b5050905080612cfd83612df4565b604051602001612d0d91906138d0565b60405160208183030381529060405290611cec5760405162461bcd60e51b8152600401610e1f9190612fae565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115612d675750600090506003612deb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612dbb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612de457600060019250925050612deb565b9150600090505b94509492505050565b60606000612e0183612e86565b60010190506000816001600160401b03811115612e2057612e20613159565b6040519080825280601f01601f191660200182016040528015612e4a576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612e5457509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612ec55772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612ef1576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612f0f57662386f26fc10000830492506010015b6305f5e1008310612f27576305f5e100830492506008015b6127108310612f3b57612710830492506004015b60648310612f4d576064830492506002015b600a83106110975760010192915050565b60005b83811015612f79578181015183820152602001612f61565b50506000910152565b60008151808452612f9a816020860160208601612f5e565b601f01601f19169290920160200192915050565b602081526000612fc16020830184612f82565b9392505050565b6001600160a01b0381168114611bd257600080fd5b60008060408385031215612ff057600080fd5b8235612ffb81612fc8565b946020939093013593505050565b60006020828403121561301b57600080fd5b5035919050565b60008060006060848603121561303757600080fd5b83359250602084013561304981612fc8565b929592945050506040919091013590565b8015158114611bd257600080fd5b6000806040838503121561307b57600080fd5b82359150602083013561308d8161305a565b809150509250929050565b6001600160401b0381168114611bd257600080fd5b6000806000606084860312156130c257600080fd5b83356130cd81613098565b9250602084013561304981612fc8565b6000602082840312156130ef57600080fd5b8135612fc18161305a565b60008060006060848603121561310f57600080fd5b83356130cd81612fc8565b60006020828403121561312c57600080fd5b8135612fc181612fc8565b6000806040838503121561314a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b038084111561318957613189613159565b604051601f8501601f19908116603f011681019082821181831017156131b1576131b1613159565b816040528093508581528686860111156131ca57600080fd5b858560208301376000602087830101525050509392505050565b600080600080600060a086880312156131fc57600080fd5b853561320781613098565b9450602086013561321781612fc8565b9350604086013560ff8116811461322d57600080fd5b92506060860135915060808601356001600160401b0381111561324f57600080fd5b8601601f8101881361326057600080fd5b61326f8882356020840161316f565b9150509295509295909350565b60008060006060848603121561329157600080fd5b833592506020840135915060408401356132aa81612fc8565b809150509250925092565b600080604083850312156132c857600080fd5b82359150602083013561308d81612fc8565b600082601f8301126132eb57600080fd5b612fc18383356020850161316f565b6000806000806080858703121561331057600080fd5b84356001600160401b038082111561332757600080fd5b613333888389016132da565b9550602087013591508082111561334957600080fd5b50613356878288016132da565b93505060408501359150606085013561336e81612fc8565b939692955090935050565b6000806040838503121561338c57600080fd5b823561339781612fc8565b9150602083013561308d81612fc8565b6000806000606084860312156133bc57600080fd5b83356133c781612fc8565b95602085013595506040909401359392505050565b600080600080606085870312156133f257600080fd5b84359350602085013561340481612fc8565b925060408501356001600160401b038082111561342057600080fd5b818701915087601f83011261343457600080fd5b81358181111561344357600080fd5b88602082850101111561345557600080fd5b95989497505060200194505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561109757611097613464565b6020808252601e908201527f74686520616d6f756e742063616e6e6f7420626520746f6f20736d616c6c0000604082015260600190565b8082018082111561109757611097613464565b8481528360208201526080604082015260006134f66080830185612f82565b905060018060a01b038316606083015295945050505050565b60006001820161352157613521613464565b5060010190565b600181811c9082168061353c57607f821691505b60208210810361355c57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600d908201526c3a37b5b2b71034b71032b9391760991b604082015260600190565b6020808252601590820152740c4e4d2c8ceca40cccaca40dcdee840cadcdeeaced605b1b604082015260600190565b828152604060208201526000611b546040830184612f82565b6000602082840312156135e357600080fd5b5051919050565b808202811582820484141761109757611097613464565b60008261361e57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561363557600080fd5b8151612fc181612fc8565b6001600160401b038516815260018060a01b03841660208201528260408201526080606082015260006125a56080830184612f82565b6020808252600a90820152697377617020706175736560b01b604082015260600190565b600085516136ac818460208a01612f5e565b8551908301906136c0818360208a01612f5e565b01938452505060601b6bffffffffffffffffffffffff1916602082015260340192915050565b634e487b7160e01b600052602160045260246000fd5b60ff851681526080602082015260006137186080830186612f82565b84604084015282810360608401526137308185612f82565b979650505050505050565b60ff851681526080602082015260006137576080830186612f82565b60ff8516604084015282810360608401526137308185612f82565b600080600080600060a0868803121561378a57600080fd5b85519450602086015161379c81612fc8565b80945050604086015192506060860151915060808601516137bc8161305a565b809150509295509295909350565b600080600080608085870312156137e057600080fd5b8451935060208501516137f281612fc8565b6040860151606090960151949790965092505050565b60008060006060848603121561381d57600080fd5b83519250602084015161382f81612fc8565b80925050604084015190509250925092565b6000806000806080858703121561385757600080fd5b84519350602085015161386981613098565b604086015190935061387a81612fc8565b6060959095015193969295505050565b60208082526010908201526f3737b731b2903932b832ba34ba34b7b760811b604082015260600190565b600082516138c6818460208701612f5e565b9190910192915050565b77283937b23ab1ba102a3930b739b332b9103330b4b632b21760411b815260008251613903816018850160208701612f5e565b919091016018019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122031cf79bb9bc6dcac76ba40156b19c0bb95e5d71c9ca3f01320407cae981d01c064736f6c63430008170033

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

000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000ea7744c4fa1101f9e6df5688fc19e3ee941064390000000000000000000000004cdbc49a24c634d67642de875088a45fec39bf53000000000000000000000000000000000000000000084595161401484a000000000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000066d6c1a80000000000000000000000000000000000000000000000000f43fc2c04ee00000000000000000000000000004d7de41c9e128f8fcfdf479a533987320520fc9f000000000000000000000000ca709ea906207b44521f03ecf5b594d247dffac5000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000245b4c494b5749445d204c696b7769642053686f727461626c6520546f6b656e2064656d6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044c535444000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): [LIKWID] Likwid Shortable Token demo
Arg [1] : _symbol (string): LSTD
Arg [2] : _ownerAddr (address): 0xEA7744c4FA1101f9E6dF5688fc19e3EE94106439
Arg [3] : _factoryAddress (address): 0x4cdBc49a24C634d67642de875088A45fec39bF53
Arg [4] : _omniSupply (uint256): 10000000000000000000000000
Arg [5] : _launchFunds (uint256): 100000000000000000
Arg [6] : _launchTime (uint256): 1725350312
Arg [7] : _launchHardCap (uint256): 1100000000000000000
Arg [8] : _creatorAddr (address): 0x4d7DE41C9e128f8FCfdf479a533987320520fC9f
Arg [9] : _signer (address): 0xca709ea906207B44521f03eCf5B594d247DffAc5
Arg [10] : params (bytes): 0x000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000000

-----Encoded View---------------
21 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [2] : 000000000000000000000000ea7744c4fa1101f9e6df5688fc19e3ee94106439
Arg [3] : 0000000000000000000000004cdbc49a24c634d67642de875088a45fec39bf53
Arg [4] : 000000000000000000000000000000000000000000084595161401484a000000
Arg [5] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [6] : 0000000000000000000000000000000000000000000000000000000066d6c1a8
Arg [7] : 0000000000000000000000000000000000000000000000000f43fc2c04ee0000
Arg [8] : 0000000000000000000000004d7de41c9e128f8fcfdf479a533987320520fc9f
Arg [9] : 000000000000000000000000ca709ea906207b44521f03ecf5b594d247dffac5
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [12] : 5b4c494b5749445d204c696b7769642053686f727461626c6520546f6b656e20
Arg [13] : 64656d6f00000000000000000000000000000000000000000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [15] : 4c53544400000000000000000000000000000000000000000000000000000000
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [17] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [19] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000000


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.