ETH Price: $2,505.06 (+0.26%)

Token

Amplifi (AMPLIFI)
 

Overview

Max Total Supply

100,077,853.974012113488572873 AMPLIFI

Holders

659 (0.00%)

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
*super🪰️.eth
Balance
0 AMPLIFI

Value
$0.00
0x9340e604bd353bd2f90693188c0c829a721dec3b
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

AmpliFi is a net-deflationary Perpetual Yield Protocol based on a decentralized crypto annuity. AmpliFi is backed by Ethereum Network Validators and encourages holders to lock their tokens for competitive yield, entitling them to both native and ETH rewards.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Amplifi

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : Amplifi.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "openzeppelin-contracts/access/Ownable.sol";
import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "./interfaces/IAmplifi.sol";
import "./interfaces/IUniswap.sol";
import "./AmplifiNode.sol";
import "./Types.sol";

/**
 * Amplifi
 * Website: https://perpetualyield.io/
 * Telegram: https://t.me/Amplifi_ERC
 * Twitter: https://twitter.com/amplifidefi
 */
contract Amplifi is IERC20, IAmplifi, Ownable {
    string public constant name = "Amplifi";
    string public constant symbol = "AMPLIFI";
    uint8 public constant decimals = 18;
    uint256 public totalSupply = 121_373e18;

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    IERC20 public immutable WETH;
    IERC20 public immutable USDC;

    IUniswapV2Router02 public immutable router;
    address public immutable pair;

    AmplifiNode public amplifiNode;
    address private amplifiNodeAddress;

    uint256 public maxWallet = type(uint256).max;

    mapping(address => bool) public isDisabledExempt;
    mapping(address => bool) public isFeeExempt;
    mapping(address => bool) public isMaxExempt;
    mapping(address => bool) public isUniswapPair;

    // Fees are charged on swaps
    Types.FeeRecipients public feeRecipients;
    Types.Fees public fees;
    uint16 public feeTotal = 900;

    // Taxes are charged on transfers and burned
    uint16 public tax = 300;

    // Basis for all fee and tax values
    uint16 public constant bps = 10_000;

    bool public contractSellEnabled = true;
    uint256 public contractSellThreshold = 65e18;
    uint256 public minSwapAmountToTriggerContractSell = 0;

    bool public mintingEnabled = true;
    bool public burningEnabled = true;
    bool public tradingEnabled = false;
    bool public isContractSelling = false;

    modifier contractSelling() {
        isContractSelling = true;
        _;
        isContractSelling = false;
    }

    constructor(
        address _router,
        address _usdc,
        address _gampVault
    ) {
        router = IUniswapV2Router02(_router);
        USDC = IERC20(_usdc);

        pair = IUniswapV2Factory(router.factory()).createPair(address(USDC), address(this));

        WETH = IERC20(router.WETH());

        amplifiNode = new AmplifiNode(this, router, USDC, msg.sender);
        amplifiNodeAddress = address(amplifiNode);

        isDisabledExempt[msg.sender] = true;
        isFeeExempt[msg.sender] = true;
        isMaxExempt[msg.sender] = true;
        isDisabledExempt[amplifiNodeAddress] = true;
        isFeeExempt[amplifiNodeAddress] = true;
        isMaxExempt[amplifiNodeAddress] = true;
        isDisabledExempt[address(0)] = true;
        isFeeExempt[address(0)] = true;
        isMaxExempt[address(0)] = true;
        isMaxExempt[address(this)] = true;
        isUniswapPair[pair] = true;

        allowance[address(this)][address(router)] = type(uint256).max;

        feeRecipients = Types.FeeRecipients(
            0xc766B8c9741BC804FCc378FdE75560229CA3AB1E,
            0x682Ce32507D2825A540Ad31dC4C2B18432E0e5Bd,
            0x146f0Af003d2eB9B06a1900F5de9d01708072c3f,
            0x394110aceF86D93b20705d2Df00bE1629ce741De,
            0x8C3F0b1Bd87965bE0dc01A9b7fc3003abec1A3CB,
            0xbE328EAAe2199409a447c4121C7979fFfAaCd4d5,
            _gampVault,
            0x74B605FD7cfC830A862Ee6F2F2e1007608B4b2fF,
            0x5A23C387112e8e213B0755191e7d1cdC26b0C1b2,
            0x6f967da9c0E1764159408988fDcF6c3B7Bf0F9F7,
            0x454cD1e89df17cDB61D868C6D3dBC02bC2c38a17
        );

        fees = Types.Fees(175, 87, 87, 87, 44, 44, 44, 44, 44, 44, 200);

        uint256 toEmissions = 39_000e18;
        uint256 toDeployer = totalSupply - toEmissions;

        balanceOf[msg.sender] = toDeployer;
        emit Transfer(address(0), msg.sender, toDeployer);

        balanceOf[amplifiNodeAddress] = toEmissions;
        emit Transfer(address(0), amplifiNodeAddress, toEmissions);
    }

    function mint(uint256 _amount) external onlyOwner {
        require(mintingEnabled, "Minting is disabled");

        totalSupply += _amount;
        unchecked {
            balanceOf[msg.sender] += _amount;
        }
        emit Transfer(address(0), msg.sender, _amount);
    }

    function burn(address _burnee, uint256 _amount) external onlyOwner returns (bool) {
        require(burningEnabled, "Burning is disabled");
        require(balanceOf[_burnee] >= _amount, "Cannot burn more than an account has");

        totalSupply -= _amount;

        balanceOf[_burnee] -= _amount;
        emit Transfer(_burnee, address(0), _amount);
        return true;
    }

    function burnForAmplifier(address _burnee, uint256 _amount) external returns (bool) {
        require(msg.sender == address(amplifiNode), "Only the Amplifier Node contract can burn");
        require(balanceOf[_burnee] >= _amount, "Cannot burn more than an account has");

        uint256 allowed = allowance[_burnee][msg.sender];
        if (allowed != type(uint256).max) {
            allowance[_burnee][msg.sender] = allowed - _amount;
        }

        totalSupply -= _amount;

        balanceOf[_burnee] -= _amount;
        emit Transfer(_burnee, address(0), _amount);
        return true;
    }

    function approve(address _spender, uint256 _amount) public override returns (bool) {
        allowance[msg.sender][_spender] = _amount;
        emit Approval(msg.sender, _spender, _amount);
        return true;
    }

    function transfer(address _recipient, uint256 _amount) external override returns (bool) {
        return _transferFrom(msg.sender, _recipient, _amount);
    }

    function transferFrom(
        address _sender,
        address _recipient,
        uint256 _amount
    ) external override returns (bool) {
        uint256 allowed = allowance[_sender][msg.sender];
        if (allowed != type(uint256).max) {
            allowance[_sender][msg.sender] = allowed - _amount;
        }

        return _transferFrom(_sender, _recipient, _amount);
    }

    function _transferFrom(
        address _sender,
        address _recipient,
        uint256 _amount
    ) private returns (bool) {
        if (isContractSelling) {
            return _simpleTransfer(_sender, _recipient, _amount);
        }

        require(tradingEnabled || isDisabledExempt[_sender], "Trading is currently disabled");

        bool sell = isUniswapPair[_recipient] || _recipient == address(router);

        if (!sell && !isMaxExempt[_recipient]) {
            require((balanceOf[_recipient] + _amount) <= maxWallet, "Max wallet has been triggered");
        }

        if (
            sell &&
            _amount >= minSwapAmountToTriggerContractSell &&
            !isUniswapPair[msg.sender] &&
            !isContractSelling &&
            contractSellEnabled &&
            balanceOf[address(this)] >= contractSellThreshold
        ) {
            _contractSell();
        }

        balanceOf[_sender] -= _amount;

        uint256 amountAfter = _amount;
        if (
            ((isUniswapPair[_sender] || _sender == address(router)) ||
                (isUniswapPair[_recipient] || _recipient == address(router)))
                ? !isFeeExempt[_sender] && !isFeeExempt[_recipient]
                : false
        ) {
            amountAfter = _collectFee(_sender, _amount);
        } else if (!isFeeExempt[_sender] && !isFeeExempt[_recipient]) {
            amountAfter = _collectTax(_sender, _amount);
        }

        unchecked {
            balanceOf[_recipient] += amountAfter;
        }
        emit Transfer(_sender, _recipient, amountAfter);

        return true;
    }

    function _simpleTransfer(
        address _sender,
        address _recipient,
        uint256 _amount
    ) private returns (bool) {
        balanceOf[_sender] -= _amount;
        unchecked {
            balanceOf[_recipient] += _amount;
        }
        return true;
    }

    function _contractSell() private contractSelling {
        uint256 ethBefore = address(this).balance;

        address[] memory path = new address[](3);
        path[0] = address(this);
        path[1] = address(USDC);
        path[2] = address(WETH);
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            balanceOf[address(this)],
            0,
            path,
            address(this),
            block.timestamp
        );

        uint256 ethAfter = address(this).balance - ethBefore;

        if (ethAfter > bps) {
            bool success;
            (success, ) = feeRecipients.operations.call{value: (ethAfter * fees.operations) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.validatorAcquisition.call{value: (ethAfter * fees.validatorAcquisition) / bps}(
                ""
            );
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.PCR.call{value: (ethAfter * fees.PCR) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.yield.call{value: (ethAfter * fees.yield) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.xChainValidatorAcquisition.call{
                value: (ethAfter * fees.xChainValidatorAcquisition) / bps
            }("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.indexFundPools.call{value: (ethAfter * fees.indexFundPools) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.gAMPRewardsPool.call{value: (ethAfter * fees.gAMPRewardsPool) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.OTCSwap.call{value: (ethAfter * fees.OTCSwap) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.rescueFund.call{value: (ethAfter * fees.rescueFund) / bps}("");
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.protocolImprovement.call{value: (ethAfter * fees.protocolImprovement) / bps}(
                ""
            );
            require(success, "Could not send ETH");
            (success, ) = feeRecipients.developers.call{value: (ethAfter * fees.developers) / bps}("");
            require(success, "Could not send ETH");
        }
    }

    function _collectFee(address _sender, uint256 _amount) private returns (uint256) {
        uint256 feeAmount = (_amount * feeTotal) / bps;

        unchecked {
            balanceOf[address(this)] += feeAmount;
        }
        emit Transfer(_sender, address(this), feeAmount);

        return _amount - feeAmount;
    }

    function _collectTax(address _sender, uint256 _amount) private returns (uint256) {
        uint256 taxAmount = (_amount * tax) / bps;

        totalSupply -= taxAmount;

        emit Transfer(_sender, address(0), _amount);

        return _amount - taxAmount;
    }

    function setMaxWallet(uint256 _maxWallet) external onlyOwner {
        maxWallet = _maxWallet;
    }

    function setIsDisabledExempt(address _holder, bool _exempt) external onlyOwner {
        isDisabledExempt[_holder] = _exempt;
    }

    function setIsFeeExempt(address _holder, bool _exempt) external onlyOwner {
        isFeeExempt[_holder] = _exempt;
    }

    function setIsMaxExempt(address _holder, bool _exempt) external onlyOwner {
        isMaxExempt[_holder] = _exempt;
    }

    function setIsUniswapPair(address _pair, bool _isPair) external onlyOwner {
        isUniswapPair[_pair] = _isPair;
    }

    function setContractSelling(
        bool _contractSellEnabled,
        uint256 _contractSellThreshold,
        uint256 _minSwapAmountToTriggerContractSell
    ) external onlyOwner {
        contractSellEnabled = _contractSellEnabled;
        contractSellThreshold = _contractSellThreshold;
        minSwapAmountToTriggerContractSell = _minSwapAmountToTriggerContractSell;
    }

    function setFees(Types.Fees calldata _fees) external onlyOwner {
        fees = _fees;

        feeTotal =
            _fees.operations +
            _fees.validatorAcquisition +
            _fees.PCR +
            _fees.yield +
            _fees.xChainValidatorAcquisition +
            _fees.indexFundPools +
            _fees.gAMPRewardsPool +
            _fees.OTCSwap +
            _fees.rescueFund +
            _fees.protocolImprovement +
            _fees.developers;
    }

    function setFeeRecipients(Types.FeeRecipients calldata _feeRecipients) external onlyOwner {
        feeRecipients = _feeRecipients;
    }

    function setTax(uint16 _tax) external onlyOwner {
        tax = _tax;
    }

    function setTradingEnabled(bool _enabled) external onlyOwner {
        tradingEnabled = _enabled;
    }

    function setAmplifiNode(AmplifiNode _amplifiNode) external onlyOwner {
        amplifiNode = _amplifiNode;
        amplifiNodeAddress = address(amplifiNode);

        isDisabledExempt[amplifiNodeAddress] = true;
        isFeeExempt[amplifiNodeAddress] = true;
        isMaxExempt[amplifiNodeAddress] = true;
    }

    function permanentlyDisableMinting() external onlyOwner {
        mintingEnabled = false;
    }

    function permanentlyDisableBurning() external onlyOwner {
        burningEnabled = false;
    }

    function withdrawETH(address _recipient) external onlyOwner {
        (bool success, ) = _recipient.call{value: address(this).balance}("");
        require(success, "Could not send ETH");
    }

    function withdrawToken(IERC20 _token, address _recipient) external onlyOwner {
        _token.transfer(_recipient, _token.balanceOf(address(this)));
    }

    receive() external payable {}
}

File 2 of 11 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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 anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public 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 11 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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 4 of 11 : IAmplifi.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "openzeppelin-contracts/token/ERC20/IERC20.sol";

interface IAmplifi is IERC20 {
    function burnForAmplifier(address _burnee, uint256 _amount) external returns (bool);
}

File 5 of 11 : IUniswap.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

interface IUniswapV2Pair {
    event Approval(
        address indexed owner, address indexed spender, uint256 value
    );
    event Transfer(address indexed from, address indexed to, uint256 value);

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value)
        external
        returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        external;

    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(
        address indexed sender,
        uint256 amount0,
        uint256 amount1,
        address indexed to
    );
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to)
        external
        returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    )
        external;

    function skim(address to) external;

    function sync() external;

    function initialize(address, address) external;
}

interface IUniswapV2Factory {
    event PairCreated(
        address indexed token0, address indexed token1, address pair, uint256
    );

    function feeTo() external view returns (address);

    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB)
        external
        view
        returns (address pair);

    function allPairs(uint256) external view returns (address pair);

    function allPairsLength() external view returns (uint256);

    function createPair(address tokenA, address tokenB)
        external
        returns (address pair);

    function setFeeTo(address) external;

    function setFeeToSetter(address) external;
}

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

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (uint256 amountA, uint256 amountB, uint256 liquidity);

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);

    
    function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        returns (uint256 amountETH);

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    )
        external;

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    )
        external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    )
        external
        payable;
}

File 6 of 11 : AmplifiNode.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "openzeppelin-contracts/access/Ownable.sol";
import "openzeppelin-contracts/security/ReentrancyGuard.sol";
import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "./interfaces/IAmplifi.sol";
import "./interfaces/IUniswap.sol";
import "./FusePool.sol";
import "./Types.sol";

contract AmplifiNode is Ownable, ReentrancyGuard {
    uint16 public maxMonths = 6;
    uint16 public maxAmplifiersPerMinter = 96;
    uint256 public gracePeriod = 30 days;
    uint256 public gammaPeriod = 72 days;
    uint256 public fuseWaitPeriod = 90 days;

    uint256 public totalAmplifiers = 0;
    mapping(uint256 => Types.Amplifier) public amplifiers;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(uint256 => uint256)) public ownedAmplifiers;
    mapping(uint256 => uint256) public ownedAmplifiersIndex;

    mapping(Types.FuseProduct => uint256) public fuseLockDurations;
    mapping(Types.FuseProduct => FusePool) public fusePools;
    mapping(Types.FuseProduct => uint256) public boosts;

    uint256 public creationFee = 0;
    uint256 public renewalFee = 0.006 ether;
    uint256 public fuseFee = 0.007 ether;
    uint256 public mintPrice = 20e18;

    uint256[20] public rates = [
        700000000000,
        595000000000,
        505750000000,
        429887500000,
        365404375000,
        310593718750,
        264004660937,
        224403961797,
        190743367527,
        162131862398,
        137812083039,
        117140270583,
        99569229995,
        84633845496,
        71938768672,
        61147953371,
        51975760365,
        44179396311,
        37552486864,
        31919613834
    ];

    IAmplifi public immutable amplifi;
    IUniswapV2Router02 public immutable router;
    IERC20 public immutable USDC;

    Types.AmplifierFeeRecipients public feeRecipients;

    uint16 public claimFee = 600;
    // Basis for above fee values
    uint16 public constant bps = 10_000;

    constructor(
        IAmplifi _amplifi,
        IUniswapV2Router02 _router,
        IERC20 _usdc,
        address _owner
    ) {
        transferOwnership(_owner);
        amplifi = _amplifi;
        router = _router;
        USDC = _usdc;

        feeRecipients = Types.AmplifierFeeRecipients(
            0xc766B8c9741BC804FCc378FdE75560229CA3AB1E,
            0x682Ce32507D2825A540Ad31dC4C2B18432E0e5Bd,
            0x454cD1e89df17cDB61D868C6D3dBC02bC2c38a17
        );

        fuseLockDurations[Types.FuseProduct.OneYear] = 365 days;
        fuseLockDurations[Types.FuseProduct.ThreeYears] = 365 days * 3;
        fuseLockDurations[Types.FuseProduct.FiveYears] = 365 days * 5;

        fusePools[Types.FuseProduct.OneYear] = new FusePool(_owner, 365 days);
        fusePools[Types.FuseProduct.ThreeYears] = new FusePool(_owner, 365 days * 3);
        fusePools[Types.FuseProduct.FiveYears] = new FusePool(_owner, 365 days * 5);

        boosts[Types.FuseProduct.OneYear] = 2e18;
        boosts[Types.FuseProduct.ThreeYears] = 12e18;
        boosts[Types.FuseProduct.FiveYears] = 36e18;
    }

    function createAmplifier(uint256 _months) external payable nonReentrant returns (uint256) {
        require(msg.value == getRenewalFeeForMonths(_months) + creationFee, "Invalid Ether value provided");
        return _createAmplifier(_months);
    }

    function createAmplifierBatch(uint256 _amount, uint256 _months)
        external
        payable
        nonReentrant
        returns (uint256[] memory ids)
    {
        require(msg.value == (getRenewalFeeForMonths(_months) + creationFee) * _amount, "Invalid Ether value provided");
        ids = new uint256[](_amount);
        for (uint256 i = 0; i < _amount; ) {
            ids[i] = _createAmplifier(_months);
            unchecked {
                ++i;
            }
        }
        return ids;
    }

    function _createAmplifier(uint256 _months) internal returns (uint256) {
        require(balanceOf[msg.sender] < maxAmplifiersPerMinter, "Too many amplifiers");
        require(_months > 0 && _months <= maxMonths, "Must be 1-6 months");

        require(amplifi.burnForAmplifier(msg.sender, mintPrice), "Not able to burn");

        (bool success, ) = feeRecipients.validatorAcquisition.call{
            value: getRenewalFeeForMonths(_months) + creationFee
        }("");
        require(success, "Could not send ETH");

        uint256 id;
        uint256 length;
        unchecked {
            id = totalAmplifiers++;
            length = balanceOf[msg.sender]++;
        }

        amplifiers[id] = Types.Amplifier(
            Types.FuseProduct.None,
            msg.sender,
            block.timestamp,
            block.timestamp + 30 days * _months,
            0,
            0,
            0,
            0,
            0
        );
        ownedAmplifiers[msg.sender][length] = id;
        ownedAmplifiersIndex[id] = length;

        return id;
    }

    function renewAmplifier(uint256 _id, uint256 _months) external payable nonReentrant {
        require(msg.value == getRenewalFeeForMonths(_months), "Invalid Ether value provided");
        _renewAmplifier(_id, _months);
    }

    function renewAmplifierBatch(uint256[] calldata _ids, uint256 _months) external payable nonReentrant {
        uint256 length = _ids.length;
        require(msg.value == (getRenewalFeeForMonths(_months)) * length, "Invalid Ether value provided");
        for (uint256 i = 0; i < length; ) {
            _renewAmplifier(_ids[i], _months);
            unchecked {
                ++i;
            }
        }
    }

    function _renewAmplifier(uint256 _id, uint256 _months) internal {
        Types.Amplifier storage amplifier = amplifiers[_id];

        require(amplifier.minter == msg.sender, "Invalid ownership");
        require(amplifier.expires + gracePeriod >= block.timestamp, "Grace period expired");

        uint256 monthsLeft = 0;
        if (block.timestamp > amplifier.expires) {
            monthsLeft = (block.timestamp - amplifier.created) / 30 days;
        }
        require(_months + monthsLeft <= maxMonths, "Too many months");

        (bool success, ) = feeRecipients.validatorAcquisition.call{value: getRenewalFeeForMonths(_months)}("");
        require(success, "Could not send ETH");

        amplifier.expires += 30 days * _months;
    }

    function fuseAmplifier(uint256 _id, Types.FuseProduct fuseProduct) external payable nonReentrant {
        Types.Amplifier storage amplifier = amplifiers[_id];

        require(amplifier.minter == msg.sender, "Invalid ownership");
        require(amplifier.fuseProduct == Types.FuseProduct.None, "Already fused");
        require(amplifier.expires > block.timestamp, "Amplifier expired");

        require(msg.value == fuseFee, "Invalid Ether value provided");

        (bool success, ) = feeRecipients.validatorAcquisition.call{value: msg.value}("");
        require(success, "Could not send ETH");

        INetwork network = fusePools[fuseProduct];
        network.increaseShare(msg.sender, block.timestamp + fuseLockDurations[fuseProduct]);

        amplifier.fuseProduct = fuseProduct;
        amplifier.fused = block.timestamp;
        amplifier.unlocks = block.timestamp + fuseLockDurations[fuseProduct];
    }

    function claimAMPLIFI(uint256 _id) external nonReentrant {
        _claimAMPLIFI(_id);
    }

    function claimAMPLIFIBatch(uint256[] calldata _ids) external nonReentrant {
        uint256 length = _ids.length;
        for (uint256 i = 0; i < length; ) {
            _claimAMPLIFI(_ids[i]);
            unchecked {
                ++i;
            }
        }
    }

    function _claimAMPLIFI(uint256 _id) internal {
        Types.Amplifier storage amplifier = amplifiers[_id];
        require(amplifier.minter == msg.sender, "Invalid ownership");
        require(amplifier.fuseProduct == Types.FuseProduct.None, "Must be unfused");
        require(amplifier.expires > block.timestamp, "Amplifier expired");

        uint256 amount = getPendingAMPLIFI(_id);
        amount = takeClaimFee(amount);
        amplifi.transfer(msg.sender, amount);

        amplifier.numClaims++;
        amplifier.lastClaimed = block.timestamp;
    }

    function claimETH(uint256 _id) external nonReentrant {
        _claimETH(_id);
    }

    function claimETHBatch(uint256[] calldata _ids) external nonReentrant {
        uint256 length = _ids.length;
        for (uint256 i = 0; i < length; ) {
            _claimETH(_ids[i]);
            unchecked {
                ++i;
            }
        }
    }

    function _claimETH(uint256 _id) internal {
        Types.Amplifier storage amplifier = amplifiers[_id];
        require(amplifier.minter == msg.sender, "Invalid ownership");
        require(amplifier.fuseProduct != Types.FuseProduct.None, "Must be fused");
        require(amplifier.expires > block.timestamp, "Amplifier expired");
        require(block.timestamp - amplifier.fused > fuseWaitPeriod, "Cannot claim ETH yet");

        fusePools[amplifier.fuseProduct].distributeDividend(msg.sender);

        if (amplifier.unlocks <= block.timestamp) {
            require(amplifi.transfer(msg.sender, boosts[amplifier.fuseProduct]));

            fusePools[amplifier.fuseProduct].decreaseShare(amplifier.minter);
            amplifier.fuseProduct = Types.FuseProduct.None;
            amplifier.fused = 0;
            amplifier.unlocks = 0;
        }
    }

    function getPendingAMPLIFI(uint256 _id) public view returns (uint256) {
        Types.Amplifier memory amplifier = amplifiers[_id];

        uint256 rate = amplifier.numClaims >= rates.length ? rates[rates.length - 1] : rates[amplifier.numClaims];
        uint256 amount = (block.timestamp - (amplifier.numClaims > 0 ? amplifier.lastClaimed : amplifier.created)) *
            (rate);
        if (amplifier.created < block.timestamp + gammaPeriod) {
            uint256 _seconds = (block.timestamp + gammaPeriod) - amplifier.created;
            uint256 _percent = 100;
            if (_seconds >= 4838400) {
                _percent = 900;
            } else if (_seconds >= 4233600) {
                _percent = 800;
            } else if (_seconds >= 3628800) {
                _percent = 700;
            } else if (_seconds >= 3024000) {
                _percent = 600;
            } else if (_seconds >= 2419200) {
                _percent = 500;
            } else if (_seconds >= 1814400) {
                _percent = 400;
            } else if (_seconds >= 1209600) {
                _percent = 300;
            } else if (_seconds >= 604800) {
                _percent = 200;
            }
            uint256 _divisor = amount * _percent;
            (, uint256 result) = tryDiv(_divisor, 10000);
            amount -= result;
        }

        return amount;
    }

    function takeClaimFee(uint256 amount) internal returns (uint256) {
        uint256 fee = (amount * claimFee) / bps;

        address[] memory path = new address[](2);
        path[0] = address(amplifi);
        path[1] = address(USDC);
        router.swapExactTokensForTokensSupportingFeeOnTransferTokens(fee, 0, path, address(this), block.timestamp);

        uint256 usdcToSend = USDC.balanceOf(address(this)) / 2;

        USDC.transfer(feeRecipients.operations, usdcToSend);
        USDC.transfer(feeRecipients.developers, usdcToSend);

        return amount - fee;
    }

    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) {
                return (false, 0);
            }
            return (true, a / b);
        }
    }

    function getRenewalFeeForMonths(uint256 _months) public view returns (uint256) {
        return renewalFee * _months;
    }

    function airdropAmplifiers(
        address[] calldata _users,
        uint256[] calldata _months,
        Types.FuseProduct[] calldata _fuseProducts
    ) external onlyOwner returns (uint256[] memory ids) {
        require(_users.length == _months.length && _months.length == _fuseProducts.length, "Lengths not aligned");

        uint256 length = _users.length;
        ids = new uint256[](length);
        for (uint256 i = 0; i < length; ) {
            ids[i] = _airdropAmplifier(_users[i], _months[i], _fuseProducts[i]);
            unchecked {
                ++i;
            }
        }

        return ids;
    }

    function _airdropAmplifier(
        address _user,
        uint256 _months,
        Types.FuseProduct _fuseProduct
    ) internal returns (uint256) {
        require(_months <= maxMonths, "Too many months");

        uint256 id;
        uint256 length;
        unchecked {
            id = totalAmplifiers++;
            length = balanceOf[_user]++;
        }

        uint256 fused;
        uint256 unlocks;

        if (_fuseProduct != Types.FuseProduct.None) {
            fused = block.timestamp;
            unlocks = block.timestamp + fuseLockDurations[_fuseProduct];
        }

        amplifiers[id] = Types.Amplifier(
            _fuseProduct,
            _user,
            block.timestamp,
            block.timestamp + 30 days * _months,
            0,
            0,
            fused,
            unlocks,
            0
        );
        ownedAmplifiers[_user][length] = id;
        ownedAmplifiersIndex[id] = length;

        return id;
    }

    function removeAmplifier(uint256 _id) external onlyOwner {
        uint256 lastAmplifierIndex = balanceOf[amplifiers[_id].minter];
        uint256 amplifierIndex = ownedAmplifiersIndex[_id];

        if (amplifierIndex != lastAmplifierIndex) {
            uint256 lastAmplifierId = ownedAmplifiers[amplifiers[_id].minter][lastAmplifierIndex];

            ownedAmplifiers[amplifiers[_id].minter][amplifierIndex] = lastAmplifierId; // Move the last amplifier to the slot of the to-delete token
            ownedAmplifiersIndex[lastAmplifierId] = amplifierIndex; // Update the moved amplifier's index
        }

        // This also deletes the contents at the last position of the array
        delete ownedAmplifiersIndex[_id];
        delete ownedAmplifiers[amplifiers[_id].minter][lastAmplifierIndex];

        balanceOf[amplifiers[_id].minter]--;
        totalAmplifiers--;

        delete amplifiers[_id];
    }

    function setRates(uint256[] calldata _rates) external onlyOwner {
        require(_rates.length == rates.length, "Invalid length");

        uint256 length = _rates.length;
        for (uint256 i = 0; i < length; ) {
            rates[i] = _rates[i];
            unchecked {
                ++i;
            }
        }
    }

    function setMintPrice(uint256 _mintPrice) external onlyOwner {
        mintPrice = _mintPrice;
    }

    function setMaxMonths(uint16 _maxMonths) external onlyOwner {
        maxMonths = _maxMonths;
    }

    function setFees(
        uint256 _creationFee,
        uint256 _renewalFee,
        uint256 _fuseFee,
        uint16 _claimFee
    ) external onlyOwner {
        creationFee = _creationFee;
        renewalFee = _renewalFee;
        fuseFee = _fuseFee;
        claimFee = _claimFee;
    }

    function setFuseLockDurations(Types.FuseProduct _fuseProduct, uint256 _duration) external onlyOwner {
        fuseLockDurations[_fuseProduct] = _duration;
    }

    function setFusePool(Types.FuseProduct _fuseProduct, FusePool _fusePool) external onlyOwner {
        fusePools[_fuseProduct] = _fusePool;
    }

    function setBoosts(Types.FuseProduct _fuseProduct, uint256 _boost) external onlyOwner {
        boosts[_fuseProduct] = _boost;
    }

    function setFeeRecipients(Types.AmplifierFeeRecipients calldata _feeRecipients) external onlyOwner {
        feeRecipients = _feeRecipients;
    }

    function setPeriods(
        uint256 _gracePeriod,
        uint256 _gammaPeriod,
        uint256 _fuseWaitPeriod
    ) external onlyOwner {
        gracePeriod = _gracePeriod;
        gammaPeriod = _gammaPeriod;
        fuseWaitPeriod = _fuseWaitPeriod;
    }

    function approveRouter() external onlyOwner {
        amplifi.approve(address(router), type(uint256).max);
    }

    function withdrawETH(address _recipient) external onlyOwner {
        (bool success, ) = _recipient.call{value: address(this).balance}("");
        require(success, "Could not send ETH");
    }

    function withdrawToken(IERC20 _token, address _recipient) external onlyOwner {
        _token.transfer(_recipient, _token.balanceOf(address(this)));
    }

    receive() external payable {}
}

File 7 of 11 : Types.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

library Types {
    struct FeeRecipients {
        address operations;
        address validatorAcquisition;
        address PCR;
        address yield;
        address xChainValidatorAcquisition;
        address indexFundPools;
        address gAMPRewardsPool;
        address OTCSwap;
        address rescueFund;
        address protocolImprovement;
        address developers;
    }

    struct Fees {
        uint16 operations;
        uint16 validatorAcquisition;
        uint16 PCR;
        uint16 yield;
        uint16 xChainValidatorAcquisition;
        uint16 indexFundPools;
        uint16 gAMPRewardsPool;
        uint16 OTCSwap;
        uint16 rescueFund;
        uint16 protocolImprovement;
        uint16 developers;
    }

    struct Share {
        uint256 amount;
        uint256 totalExcluded;
        uint256 totalRealised;
        uint256 started;
        uint256 unlocks;
    }

    enum FuseProduct {
        None,
        OneYear,
        ThreeYears,
        FiveYears
    }

    struct Amplifier {
        FuseProduct fuseProduct;
        address minter;
        uint256 created;
        uint256 expires;
        uint256 numClaims;
        uint256 lastClaimed;
        uint256 fused;
        uint256 unlocks;
        uint256 lastFuseClaimed;
    }

    struct AmplifierFeeRecipients {
        address operations;
        address validatorAcquisition;
        address developers;
    }
}

File 8 of 11 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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;
    }
}

File 9 of 11 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 10 of 11 : FusePool.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "openzeppelin-contracts/access/Ownable.sol";
import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "./interfaces/IUniswap.sol";
import "./interfaces/INetwork.sol";
import "./Types.sol";

contract FusePool is INetwork, Ownable {
    address immutable token;
    uint256 immutable duration;

    address[] shareholders;
    mapping(address => uint256) shareholderIndexes;
    mapping(address => uint256) shareholderClaims;
    mapping(address => uint256) public totalRewardsToUser;
    mapping(address => Types.Share) public shares;
    uint256 public totalShares;
    uint256 public totalDividends;
    uint256 public totalDistributed;
    uint256 public dividendsPerShare;
    uint256 public dividendsPerShareAccuracyFactor = 10**36;

    modifier onlyToken() {
        require(msg.sender == token);
        _;
    }

    constructor(address _owner, uint256 _duration) {
        _transferOwnership(_owner);

        token = msg.sender;
        duration = _duration;
    }

    function increaseShare(address _shareholder, uint256 _unlocks) external override onlyToken {
        if (shares[_shareholder].amount == 0) {
            addShareholder(_shareholder);
        }

        totalShares++;
        shares[_shareholder].amount++;
        shares[_shareholder].unlocks = _unlocks;
        shares[_shareholder].started = block.timestamp;
        shares[_shareholder].totalExcluded = getCumulativeDividends(
            shares[_shareholder].amount,
            shares[_shareholder].started,
            shares[_shareholder].unlocks
        );
        assert(shares[_shareholder].totalExcluded == 0);
    }

    function decreaseShare(address _shareholder) external override onlyToken {
        if (shares[_shareholder].amount == 1) {
            removeShareholder(_shareholder);
        }

        totalShares--;
        shares[_shareholder].totalExcluded = getCumulativeDividends(
            shares[_shareholder].amount,
            shares[_shareholder].started,
            shares[_shareholder].started
        );
        shares[_shareholder].amount--;
        shares[_shareholder].started = 0;
        shares[_shareholder].unlocks = 0;
    }

    function deposit() external payable override onlyOwner {
        uint256 amount = msg.value;
        totalDividends += amount;
        dividendsPerShare += (dividendsPerShareAccuracyFactor * amount) / totalShares;
    }

    function distributeDividend(address _shareholder) external onlyToken {
        uint256 amount = getPendingDividend(_shareholder);

        if (amount > 0) {
            shares[_shareholder].totalExcluded = getCumulativeDividends(
                shares[_shareholder].amount,
                shares[_shareholder].started,
                shares[_shareholder].unlocks
            );
            shares[_shareholder].totalRealised += amount;
            totalDistributed += amount;

            (bool success, ) = _shareholder.call{value: amount}("");
            require(success, "Could not send ETH");

            totalRewardsToUser[_shareholder] = totalRewardsToUser[_shareholder] + amount;
        }
    }

    function getPendingDividend(address _shareholder) public view returns (uint256) {
        if (shares[_shareholder].amount == 0) {
            return 0;
        }

        uint256 shareholderTotalDividends = getCumulativeDividends(
            shares[_shareholder].amount,
            shares[_shareholder].started,
            shares[_shareholder].unlocks
        );
        uint256 shareholderTotalExcluded = shares[_shareholder].totalExcluded;
        if (shareholderTotalDividends <= shareholderTotalExcluded) {
            return 0;
        }

        return shareholderTotalDividends - shareholderTotalExcluded;
    }

    function getCumulativeDividends(
        uint256 share,
        uint256 started,
        uint256 unlocks
    ) internal view returns (uint256) {
        if (unlocks > block.timestamp) {
            unlocks = block.timestamp;
        }

        uint256 total = (share * dividendsPerShare) / dividendsPerShareAccuracyFactor;

        uint256 end = started + duration;
        uint256 endAbs = end - started;
        uint256 nowAbs = unlocks - started;

        return (total * nowAbs) / endAbs;
    }

    function addShareholder(address shareholder) internal {
        shareholderIndexes[shareholder] = shareholders.length;
        shareholders.push(shareholder);
    }

    function removeShareholder(address shareholder) internal {
        shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length - 1];
        shareholderIndexes[shareholders[shareholders.length - 1]] = shareholderIndexes[shareholder];
        shareholders.pop();
    }

    function withdrawETH(address _recipient) external onlyOwner {
        (bool success, ) = _recipient.call{value: address(this).balance}("");
        require(success, "Could not send ETH");
    }

    function withdrawToken(IERC20 _token, address _recipient) external onlyOwner {
        _token.transfer(_recipient, _token.balanceOf(address(this)));
    }
}

File 11 of 11 : INetwork.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface INetwork {
    function increaseShare(address _shareholder, uint256 _unlocks) external;
    function decreaseShare(address _shareholder) external;

    function deposit() external payable;

    function distributeDividend(address _shareholder) external;
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "solenv/=lib/solenv/src/",
    "solidity-stringutils/=lib/solenv/lib/solidity-stringutils/src/",
    "src/=src/",
    "test/=test/",
    "script/=script/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_usdc","type":"address"},{"internalType":"address","name":"_gampVault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amplifiNode","outputs":[{"internalType":"contract AmplifiNode","name":"","type":"address"}],"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":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_burnee","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_burnee","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnForAmplifier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burningEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractSellEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractSellThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipients","outputs":[{"internalType":"address","name":"operations","type":"address"},{"internalType":"address","name":"validatorAcquisition","type":"address"},{"internalType":"address","name":"PCR","type":"address"},{"internalType":"address","name":"yield","type":"address"},{"internalType":"address","name":"xChainValidatorAcquisition","type":"address"},{"internalType":"address","name":"indexFundPools","type":"address"},{"internalType":"address","name":"gAMPRewardsPool","type":"address"},{"internalType":"address","name":"OTCSwap","type":"address"},{"internalType":"address","name":"rescueFund","type":"address"},{"internalType":"address","name":"protocolImprovement","type":"address"},{"internalType":"address","name":"developers","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTotal","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"uint16","name":"operations","type":"uint16"},{"internalType":"uint16","name":"validatorAcquisition","type":"uint16"},{"internalType":"uint16","name":"PCR","type":"uint16"},{"internalType":"uint16","name":"yield","type":"uint16"},{"internalType":"uint16","name":"xChainValidatorAcquisition","type":"uint16"},{"internalType":"uint16","name":"indexFundPools","type":"uint16"},{"internalType":"uint16","name":"gAMPRewardsPool","type":"uint16"},{"internalType":"uint16","name":"OTCSwap","type":"uint16"},{"internalType":"uint16","name":"rescueFund","type":"uint16"},{"internalType":"uint16","name":"protocolImprovement","type":"uint16"},{"internalType":"uint16","name":"developers","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isContractSelling","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isDisabledExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFeeExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isMaxExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isUniswapPair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSwapAmountToTriggerContractSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permanentlyDisableBurning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"permanentlyDisableMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AmplifiNode","name":"_amplifiNode","type":"address"}],"name":"setAmplifiNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_contractSellEnabled","type":"bool"},{"internalType":"uint256","name":"_contractSellThreshold","type":"uint256"},{"internalType":"uint256","name":"_minSwapAmountToTriggerContractSell","type":"uint256"}],"name":"setContractSelling","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"operations","type":"address"},{"internalType":"address","name":"validatorAcquisition","type":"address"},{"internalType":"address","name":"PCR","type":"address"},{"internalType":"address","name":"yield","type":"address"},{"internalType":"address","name":"xChainValidatorAcquisition","type":"address"},{"internalType":"address","name":"indexFundPools","type":"address"},{"internalType":"address","name":"gAMPRewardsPool","type":"address"},{"internalType":"address","name":"OTCSwap","type":"address"},{"internalType":"address","name":"rescueFund","type":"address"},{"internalType":"address","name":"protocolImprovement","type":"address"},{"internalType":"address","name":"developers","type":"address"}],"internalType":"struct Types.FeeRecipients","name":"_feeRecipients","type":"tuple"}],"name":"setFeeRecipients","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"operations","type":"uint16"},{"internalType":"uint16","name":"validatorAcquisition","type":"uint16"},{"internalType":"uint16","name":"PCR","type":"uint16"},{"internalType":"uint16","name":"yield","type":"uint16"},{"internalType":"uint16","name":"xChainValidatorAcquisition","type":"uint16"},{"internalType":"uint16","name":"indexFundPools","type":"uint16"},{"internalType":"uint16","name":"gAMPRewardsPool","type":"uint16"},{"internalType":"uint16","name":"OTCSwap","type":"uint16"},{"internalType":"uint16","name":"rescueFund","type":"uint16"},{"internalType":"uint16","name":"protocolImprovement","type":"uint16"},{"internalType":"uint16","name":"developers","type":"uint16"}],"internalType":"struct Types.Fees","name":"_fees","type":"tuple"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"},{"internalType":"bool","name":"_exempt","type":"bool"}],"name":"setIsDisabledExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"},{"internalType":"bool","name":"_exempt","type":"bool"}],"name":"setIsFeeExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"},{"internalType":"bool","name":"_exempt","type":"bool"}],"name":"setIsMaxExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"bool","name":"_isPair","type":"bool"}],"name":"setIsUniswapPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxWallet","type":"uint256"}],"name":"setMaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_tax","type":"uint16"}],"name":"setTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setTradingEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tax","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","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":"address","name":"_recipient","type":"address"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101006040526919b3a4bd56491e540000600155600019600655601780546401012c038464ffffffffff199091161790556803860e639d806400006018556000601955601a805463ffffffff19166101011790553480156200006057600080fd5b506040516200827238038062008272833981016040819052620000839162000cba565b6200008e3362000c3f565b6001600160a01b0380841660c081905290831660a0526040805163c45a015560e01b8152905163c45a0155916004808201926020929091908290030181865afa158015620000e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000106919062000d04565b60a0516040516364e329cb60e11b81526001600160a01b03918216600482015230602482015291169063c9c65396906044016020604051808303816000875af115801562000158573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200017e919062000d04565b6001600160a01b031660e0816001600160a01b03168152505060c0516001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fe919062000d04565b6001600160a01b031660805260c05160a051604051309291903390620002249062000c8f565b6001600160a01b039485168152928416602084015290831660408301529091166060820152608001604051809103906000f08015801562000269573d6000803e3d6000fd5b50600460006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600460009054906101000a90046001600160a01b0316600560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600160076000336001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160086000336001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160096000336001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160076000600560009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160086000600560009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160096000600560009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160076000806001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160086000806001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160096000806001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600160096000306001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600a600060e0516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060001960036000306001600160a01b03166001600160a01b03168152602001908152602001600020600060c0516001600160a01b03166001600160a01b031681526020019081526020016000208190555060405180610160016040528073c766b8c9741bc804fcc378fde75560229ca3ab1e6001600160a01b0316815260200173682ce32507d2825a540ad31dc4c2b18432e0e5bd6001600160a01b0316815260200173146f0af003d2eb9b06a1900f5de9d01708072c3f6001600160a01b0316815260200173394110acef86d93b20705d2df00be1629ce741de6001600160a01b03168152602001738c3f0b1bd87965be0dc01a9b7fc3003abec1a3cb6001600160a01b0316815260200173be328eaae2199409a447c4121c7979fffaacd4d56001600160a01b03168152602001826001600160a01b031681526020017374b605fd7cfc830a862ee6f2f2e1007608b4b2ff6001600160a01b03168152602001735a23c387112e8e213b0755191e7d1cdc26b0c1b26001600160a01b03168152602001736f967da9c0e1764159408988fdcf6c3b7bf0f9f76001600160a01b0316815260200173454cd1e89df17cdb61d868c6d3dbc02bc2c38a176001600160a01b0316815250600b60008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160040160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160080160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101208201518160090160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061014082015181600a0160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555090505060405180610160016040528060af61ffff168152602001605761ffff168152602001605761ffff168152602001605761ffff168152602001602c61ffff168152602001602c61ffff168152602001602c61ffff168152602001602c61ffff168152602001602c61ffff168152602001602c61ffff16815260200160c861ffff16815250601660008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a81548161ffff021916908361ffff16021790555060408201518160000160046101000a81548161ffff021916908361ffff16021790555060608201518160000160066101000a81548161ffff021916908361ffff16021790555060808201518160000160086101000a81548161ffff021916908361ffff16021790555060a082015181600001600a6101000a81548161ffff021916908361ffff16021790555060c082015181600001600c6101000a81548161ffff021916908361ffff16021790555060e082015181600001600e6101000a81548161ffff021916908361ffff1602179055506101008201518160000160106101000a81548161ffff021916908361ffff1602179055506101208201518160000160126101000a81548161ffff021916908361ffff1602179055506101408201518160000160146101000a81548161ffff021916908361ffff160217905550905050600069084231b97924ea600000905060008160015462000ba3919062000d29565b33600081815260026020526040808220849055519293509091600080516020620082528339815191529062000bdb9085815260200190565b60405180910390a3600580546001600160a01b03908116600090815260026020526040808220869055925492519290911691600080516020620082528339815191529062000c2c9086815260200190565b60405180910390a3505050505062000d4f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61495480620038fe83390190565b80516001600160a01b038116811462000cb557600080fd5b919050565b60008060006060848603121562000cd057600080fd5b62000cdb8462000c9d565b925062000ceb6020850162000c9d565b915062000cfb6040850162000c9d565b90509250925092565b60006020828403121562000d1757600080fd5b62000d228262000c9d565b9392505050565b60008282101562000d4a57634e487b7160e01b600052601160045260246000fd5b500390565b60805160a05160c05160e051612b4b62000db36000396000610a15015260008181610bab0152818161166e01528181611819015281816118770152611b8f01526000818161078b0152611ad0015260008181610a690152611b240152612b4b6000f3fe6080604052600436106103035760003560e01c8063880934fd11610190578063a8aa1b31116100dc578063dd395c6311610095578063ea5293881161006f578063ea52938814610b59578063f2fde38b14610b79578063f887ea4014610b99578063f8b45b0514610bcd57600080fd5b8063dd395c6314610aeb578063dd62ed3e14610b0b578063e35a3d7c14610b4357600080fd5b8063a8aa1b3114610a03578063a9059cbb14610a37578063ad5c464814610a57578063af06795a14610a8b578063c2e5ec0414610aab578063cdae6b7a14610acb57600080fd5b806399c8d556116101495780639dc29fac116101235780639dc29fac146109895780639fd6db12146109a9578063a0712d68146109c3578063a0d27584146109e357600080fd5b806399c8d5561461084e5780639af1d35a1461086f5780639cece12e1461095957600080fd5b8063880934fd1461075957806389a30271146107795780638da5cb5b146107ad57806390bca2fb146107cb5780639571a07d146107eb57806395d89b411461081b57600080fd5b80633f4218e01161024f578063658d4b7f11610208578063690d8320116101e2578063690d8320146106c757806370a08231146106e7578063715018a614610714578063807fb8c51461072957600080fd5b8063658d4b7f1461067c57806366c4390d1461069c57806368237329146106b157600080fd5b80633f4218e0146105aa5780633fc645b5146105da57806348b98ef5146105fb5780634ada218b1461061d5780634d7547151461063d5780635d0044ca1461065c57600080fd5b806323b872dd116102bc57806332f29fc11161029657806332f29fc11461050f57806336203f481461054757806337bfc1ef1461055c5780633aeac4e11461058a57600080fd5b806323b872dd146104a8578063313ce567146104c8578063319f5f6a146104ef57600080fd5b8063069f22ec1461030f57806306fdde0314610338578063095ea7b3146103785780630adfdcb9146103a857806318160ddd146104705780631ff7637f1461048657600080fd5b3661030a57005b600080fd5b34801561031b57600080fd5b5061032560185481565b6040519081526020015b60405180910390f35b34801561034457600080fd5b5061036b60405180604001604052806007815260200166416d706c69666960c81b81525081565b60405161032f91906123ac565b34801561038457600080fd5b50610398610393366004612416565b610be3565b604051901515815260200161032f565b3480156103b457600080fd5b50600b54600c54600d54600e54600f546010546011546012546013546014546015546104059a6001600160a01b039081169a811699811698811697811696811695811694811693811692811691168b565b604080516001600160a01b039c8d1681529a8c1660208c0152988b16988a01989098529589166060890152938816608088015291871660a0870152861660c0860152851660e0850152841661010084015283166101208301529091166101408201526101600161032f565b34801561047c57600080fd5b5061032560015481565b34801561049257600080fd5b506104a66104a136600461245b565b610c4f565b005b3480156104b457600080fd5b506103986104c3366004612478565b610c69565b3480156104d457600080fd5b506104dd601281565b60405160ff909116815260200161032f565b3480156104fb57600080fd5b506104a661050a3660046124c9565b610cdb565b34801561051b57600080fd5b5060045461052f906001600160a01b031681565b6040516001600160a01b03909116815260200161032f565b34801561055357600080fd5b506104a6610d03565b34801561056857600080fd5b506017546105779061ffff1681565b60405161ffff909116815260200161032f565b34801561059657600080fd5b506104a66105a53660046124e6565b610d18565b3480156105b657600080fd5b506103986105c536600461251f565b60086020526000908152604090205460ff1681565b3480156105e657600080fd5b50601a54610398906301000000900460ff1681565b34801561060757600080fd5b5060175461039890640100000000900460ff1681565b34801561062957600080fd5b50601a546103989062010000900460ff1681565b34801561064957600080fd5b50601a5461039890610100900460ff1681565b34801561066857600080fd5b506104a661067736600461253c565b610e01565b34801561068857600080fd5b506104a6610697366004612563565b610e0e565b3480156106a857600080fd5b506104a6610e41565b3480156106bd57600080fd5b5061057761271081565b3480156106d357600080fd5b506104a66106e236600461251f565b610e55565b3480156106f357600080fd5b5061032561070236600461251f565b60026020526000908152604090205481565b34801561072057600080fd5b506104a6610edd565b34801561073557600080fd5b5061039861074436600461251f565b60096020526000908152604090205460ff1681565b34801561076557600080fd5b506104a661077436600461245b565b610ef1565b34801561078557600080fd5b5061052f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107b957600080fd5b506000546001600160a01b031661052f565b3480156107d757600080fd5b506103986107e6366004612416565b61103a565b3480156107f757600080fd5b5061039861080636600461251f565b60076020526000908152604090205460ff1681565b34801561082757600080fd5b5061036b60405180604001604052806007815260200166414d504c49464960c81b81525081565b34801561085a57600080fd5b506017546105779062010000900461ffff1681565b34801561087b57600080fd5b506016546108f39061ffff80821691620100008104821691640100000000820481169166010000000000008104821691600160401b8204811691600160501b8104821691600160601b8204811691600160701b8104821691600160801b8204811691600160901b8104821691600160a01b909104168b565b6040805161ffff9c8d1681529a8c1660208c0152988b16988a01989098529589166060890152938816608088015291871660a0870152861660c0860152851660e0850152841661010084015283166101208301529091166101408201526101600161032f565b34801561096557600080fd5b5061039861097436600461251f565b600a6020526000908152604090205460ff1681565b34801561099557600080fd5b506103986109a4366004612416565b6111ba565b3480156109b557600080fd5b50601a546103989060ff1681565b3480156109cf57600080fd5b506104a66109de36600461253c565b6112b9565b3480156109ef57600080fd5b506104a66109fe366004612591565b611358565b348015610a0f57600080fd5b5061052f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a4357600080fd5b50610398610a52366004612416565b611387565b348015610a6357600080fd5b5061052f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a9757600080fd5b506104a6610aa6366004612563565b611394565b348015610ab757600080fd5b506104a6610ac63660046125c6565b6113c7565b348015610ad757600080fd5b506104a6610ae6366004612563565b6113eb565b348015610af757600080fd5b506104a6610b06366004612563565b61141e565b348015610b1757600080fd5b50610325610b263660046124e6565b600360209081526000928352604080842090915290825290205481565b348015610b4f57600080fd5b5061032560195481565b348015610b6557600080fd5b506104a6610b7436600461251f565b611451565b348015610b8557600080fd5b506104a6610b9436600461251f565b6114d5565b348015610ba557600080fd5b5061052f7f000000000000000000000000000000000000000000000000000000000000000081565b348015610bd957600080fd5b5061032560065481565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610c3e9086815260200190565b60405180910390a350600192915050565b610c5761154e565b80600b610c648282612616565b505050565b6001600160a01b03831660009081526003602090815260408083203384529091528120546000198114610cc557610ca08382612731565b6001600160a01b03861660009081526003602090815260408083203384529091529020555b610cd08585856115a8565b9150505b9392505050565b610ce361154e565b6017805461ffff909216620100000263ffff000019909216919091179055565b610d0b61154e565b601a805461ff0019169055565b610d2061154e565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d929190612748565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c649190612761565b610e0961154e565b600655565b610e1661154e565b6001600160a01b03919091166000908152600860205260409020805460ff1916911515919091179055565b610e4961154e565b601a805460ff19169055565b610e5d61154e565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610eaa576040519150601f19603f3d011682016040523d82523d6000602084013e610eaf565b606091505b5050905080610ed95760405162461bcd60e51b8152600401610ed09061277e565b60405180910390fd5b5050565b610ee561154e565b610eef60006119ba565b565b610ef961154e565b806016610f0682826127b7565b50610f1b9050610160820161014083016124c9565b610f2d610140830161012084016124c9565b610f3f610120840161010085016124c9565b610f50610100850160e086016124c9565b610f6060e0860160c087016124c9565b610f7060c0870160a088016124c9565b610f8060a08801608089016124c9565b610f906080890160608a016124c9565b610fa060608a0160408b016124c9565b610fb060408b0160208c016124c9565b610fbd60208c018c6124c9565b610fc791906129ab565b610fd191906129ab565b610fdb91906129ab565b610fe591906129ab565b610fef91906129ab565b610ff991906129ab565b61100391906129ab565b61100d91906129ab565b61101791906129ab565b61102191906129ab565b6017805461ffff191661ffff9290921691909117905550565b6004546000906001600160a01b031633146110a95760405162461bcd60e51b815260206004820152602960248201527f4f6e6c792074686520416d706c6966696572204e6f646520636f6e74726163746044820152681031b0b710313ab93760b91b6064820152608401610ed0565b6001600160a01b0383166000908152600260205260409020548211156110e15760405162461bcd60e51b8152600401610ed0906129d1565b6001600160a01b0383166000908152600360209081526040808320338452909152902054600019811461113d576111188382612731565b6001600160a01b03851660009081526003602090815260408083203384529091529020555b826001600082825461114f9190612731565b90915550506001600160a01b0384166000908152600260205260408120805485929061117c908490612731565b90915550506040518381526000906001600160a01b03861690600080516020612af68339815191529060200160405180910390a35060019392505050565b60006111c461154e565b601a54610100900460ff166112115760405162461bcd60e51b8152602060048201526013602482015272109d5c9b9a5b99c81a5cc8191a5cd8589b1959606a1b6044820152606401610ed0565b6001600160a01b0383166000908152600260205260409020548211156112495760405162461bcd60e51b8152600401610ed0906129d1565b816001600082825461125b9190612731565b90915550506001600160a01b03831660009081526002602052604081208054849290611288908490612731565b90915550506040518281526000906001600160a01b03851690600080516020612af683398151915290602001610c3e565b6112c161154e565b601a5460ff166113095760405162461bcd60e51b8152602060048201526013602482015272135a5b9d1a5b99c81a5cc8191a5cd8589b1959606a1b6044820152606401610ed0565b806001600082825461131b9190612a15565b909155505033600081815260026020908152604080832080548601905551848152600080516020612af6833981519152910160405180910390a350565b61136061154e565b601780549315156401000000000264ff000000001990941693909317909255601855601955565b6000610cd43384846115a8565b61139c61154e565b6001600160a01b03919091166000908152600760205260409020805460ff1916911515919091179055565b6113cf61154e565b601a8054911515620100000262ff000019909216919091179055565b6113f361154e565b6001600160a01b03919091166000908152600a60205260409020805460ff1916911515919091179055565b61142661154e565b6001600160a01b03919091166000908152600960205260409020805460ff1916911515919091179055565b61145961154e565b600480546001600160a01b039283166001600160a01b0319918216811790925560058054909116821781556000918252600760209081526040808420805460ff19908116600190811790925584548716865260088452828620805482168317905593549095168452600990915290912080549091169091179055565b6114dd61154e565b6001600160a01b0381166115425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ed0565b61154b816119ba565b50565b6000546001600160a01b03163314610eef5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ed0565b601a546000906301000000900460ff16156115cf576115c8848484611a0a565b9050610cd4565b601a5462010000900460ff16806115fe57506001600160a01b03841660009081526007602052604090205460ff165b61164a5760405162461bcd60e51b815260206004820152601d60248201527f54726164696e672069732063757272656e746c792064697361626c65640000006044820152606401610ed0565b6001600160a01b0383166000908152600a602052604081205460ff16806116a257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9050801580156116cb57506001600160a01b03841660009081526009602052604090205460ff16155b15611745576006546001600160a01b0385166000908152600260205260409020546116f7908590612a15565b11156117455760405162461bcd60e51b815260206004820152601d60248201527f4d61782077616c6c657420686173206265656e207472696767657265640000006044820152606401610ed0565b80801561175457506019548310155b80156117705750336000908152600a602052604090205460ff16155b80156117865750601a546301000000900460ff16155b801561179c5750601754640100000000900460ff165b80156117b957506018543060009081526002602052604090205410155b156117c6576117c6611a61565b6001600160a01b038516600090815260026020526040812080548592906117ee908490612731565b90915550506001600160a01b0385166000908152600a6020526040902054839060ff168061184d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b0316145b806118ab57506001600160a01b0385166000908152600a602052604090205460ff16806118ab57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b6118b65760006118f8565b6001600160a01b03861660009081526008602052604090205460ff161580156118f857506001600160a01b03851660009081526008602052604090205460ff16155b1561190e5761190786856122bb565b9050611962565b6001600160a01b03861660009081526008602052604090205460ff1615801561195057506001600160a01b03851660009081526008602052604090205460ff16155b156119625761195f868561233d565b90505b6001600160a01b0380861660008181526002602052604090819020805485019055519091881690600080516020612af6833981519152906119a69085815260200190565b60405180910390a350600195945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038316600090815260026020526040812080548391908390611a34908490612731565b9091555050506001600160a01b038216600090815260026020526040902080548201905560019392505050565b601a805463ff0000001916630100000017905560408051600380825260808201909252479160009190602082016060803683370190505090503081600081518110611aae57611aae612a2d565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611b0257611b02612a2d565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600281518110611b5657611b56612a2d565b6001600160a01b039283166020918202929092018101919091523060008181526002909252604080832054905163791ac94760e01b81527f00000000000000000000000000000000000000000000000000000000000000009094169363791ac94793611bcb9390918791904290600401612a43565b600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b5050505060008247611c0b9190612731565b90506127108111156122a957600b546016546000916001600160a01b03169061271090611c3c9061ffff1685612ab4565b611c469190612ad3565b604051600081818185875af1925050503d8060008114611c82576040519150601f19603f3d011682016040523d82523d6000602084013e611c87565b606091505b50508091505080611caa5760405162461bcd60e51b8152600401610ed09061277e565b600c546016546001600160a01b039091169061271090611cd49062010000900461ffff1685612ab4565b611cde9190612ad3565b604051600081818185875af1925050503d8060008114611d1a576040519150601f19603f3d011682016040523d82523d6000602084013e611d1f565b606091505b50508091505080611d425760405162461bcd60e51b8152600401610ed09061277e565b600d546016546001600160a01b039091169061271090611d6e90640100000000900461ffff1685612ab4565b611d789190612ad3565b604051600081818185875af1925050503d8060008114611db4576040519150601f19603f3d011682016040523d82523d6000602084013e611db9565b606091505b50508091505080611ddc5760405162461bcd60e51b8152600401610ed09061277e565b600e546016546001600160a01b039091169061271090611e0a906601000000000000900461ffff1685612ab4565b611e149190612ad3565b604051600081818185875af1925050503d8060008114611e50576040519150601f19603f3d011682016040523d82523d6000602084013e611e55565b606091505b50508091505080611e785760405162461bcd60e51b8152600401610ed09061277e565b600f546016546001600160a01b039091169061271090611ea390600160401b900461ffff1685612ab4565b611ead9190612ad3565b604051600081818185875af1925050503d8060008114611ee9576040519150601f19603f3d011682016040523d82523d6000602084013e611eee565b606091505b50508091505080611f115760405162461bcd60e51b8152600401610ed09061277e565b6010546016546001600160a01b039091169061271090611f3c90600160501b900461ffff1685612ab4565b611f469190612ad3565b604051600081818185875af1925050503d8060008114611f82576040519150601f19603f3d011682016040523d82523d6000602084013e611f87565b606091505b50508091505080611faa5760405162461bcd60e51b8152600401610ed09061277e565b6011546016546001600160a01b039091169061271090611fd590600160601b900461ffff1685612ab4565b611fdf9190612ad3565b604051600081818185875af1925050503d806000811461201b576040519150601f19603f3d011682016040523d82523d6000602084013e612020565b606091505b505080915050806120435760405162461bcd60e51b8152600401610ed09061277e565b6012546016546001600160a01b03909116906127109061206e90600160701b900461ffff1685612ab4565b6120789190612ad3565b604051600081818185875af1925050503d80600081146120b4576040519150601f19603f3d011682016040523d82523d6000602084013e6120b9565b606091505b505080915050806120dc5760405162461bcd60e51b8152600401610ed09061277e565b6013546016546001600160a01b03909116906127109061210790600160801b900461ffff1685612ab4565b6121119190612ad3565b604051600081818185875af1925050503d806000811461214d576040519150601f19603f3d011682016040523d82523d6000602084013e612152565b606091505b505080915050806121755760405162461bcd60e51b8152600401610ed09061277e565b6014546016546001600160a01b0390911690612710906121a090600160901b900461ffff1685612ab4565b6121aa9190612ad3565b604051600081818185875af1925050503d80600081146121e6576040519150601f19603f3d011682016040523d82523d6000602084013e6121eb565b606091505b5050809150508061220e5760405162461bcd60e51b8152600401610ed09061277e565b6015546016546001600160a01b03909116906127109061223990600160a01b900461ffff1685612ab4565b6122439190612ad3565b604051600081818185875af1925050503d806000811461227f576040519150601f19603f3d011682016040523d82523d6000602084013e612284565b606091505b505080915050806122a75760405162461bcd60e51b8152600401610ed09061277e565b505b5050601a805463ff0000001916905550565b6017546000908190612710906122d59061ffff1685612ab4565b6122df9190612ad3565b306000818152600260205260409081902080548401905551919250906001600160a01b03861690600080516020612af6833981519152906123239085815260200190565b60405180910390a36123358184612731565b949350505050565b60175460009081906127109061235d9062010000900461ffff1685612ab4565b6123679190612ad3565b9050806001600082825461237b9190612731565b90915550506040518381526000906001600160a01b03861690600080516020612af683398151915290602001612323565b600060208083528351808285015260005b818110156123d9578581018301518582016040015282016123bd565b818111156123eb576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461154b57600080fd5b6000806040838503121561242957600080fd5b823561243481612401565b946020939093013593505050565b6000610160828403121561245557600080fd5b50919050565b6000610160828403121561246e57600080fd5b610cd48383612442565b60008060006060848603121561248d57600080fd5b833561249881612401565b925060208401356124a881612401565b929592945050506040919091013590565b61ffff8116811461154b57600080fd5b6000602082840312156124db57600080fd5b8135610cd4816124b9565b600080604083850312156124f957600080fd5b823561250481612401565b9150602083013561251481612401565b809150509250929050565b60006020828403121561253157600080fd5b8135610cd481612401565b60006020828403121561254e57600080fd5b5035919050565b801515811461154b57600080fd5b6000806040838503121561257657600080fd5b823561258181612401565b9150602083013561251481612555565b6000806000606084860312156125a657600080fd5b83356125b181612555565b95602085013595506040909401359392505050565b6000602082840312156125d857600080fd5b8135610cd481612555565b600081356125f081612401565b92915050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b612628612622836125e3565b826125f6565b612640612637602084016125e3565b600183016125f6565b61265861264f604084016125e3565b600283016125f6565b612670612667606084016125e3565b600383016125f6565b61268861267f608084016125e3565b600483016125f6565b6126a061269760a084016125e3565b600583016125f6565b6126b86126af60c084016125e3565b600683016125f6565b6126d06126c760e084016125e3565b600783016125f6565b6126e96126e061010084016125e3565b600883016125f6565b6127026126f961012084016125e3565b600983016125f6565b610ed961271261014084016125e3565b600a83016125f6565b634e487b7160e01b600052601160045260246000fd5b6000828210156127435761274361271b565b500390565b60006020828403121561275a57600080fd5b5051919050565b60006020828403121561277357600080fd5b8151610cd481612555565b602080825260129082015271086deead8c840dcdee840e6cadcc8408aa8960731b604082015260600190565b600081356125f0816124b9565b81356127c2816124b9565b61ffff811661ffff19835416178255506127fb6127e1602084016127aa565b825463ffff0000191660109190911b63ffff000016178255565b61282861280a604084016127aa565b825465ffff00000000191660209190911b65ffff0000000016178255565b612859612837606084016127aa565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b61288e612868608084016127aa565b825469ffff0000000000000000191660409190911b69ffff000000000000000016178255565b6128bd61289d60a084016127aa565b82805461ffff60501b191660509290921b61ffff60501b16919091179055565b6128ec6128cc60c084016127aa565b82805461ffff60601b191660609290921b61ffff60601b16919091179055565b61291b6128fb60e084016127aa565b82805461ffff60701b191660709290921b61ffff60701b16919091179055565b61294b61292b61010084016127aa565b82805461ffff60801b191660809290921b61ffff60801b16919091179055565b61297b61295b61012084016127aa565b82805461ffff60901b191660909290921b61ffff60901b16919091179055565b610ed961298b61014084016127aa565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b600061ffff8083168185168083038211156129c8576129c861271b565b01949350505050565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207468616e20616e206163636f756e746040820152632068617360e01b606082015260800190565b60008219821115612a2857612a2861271b565b500190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015612a935784516001600160a01b031683529383019391830191600101612a6e565b50506001600160a01b03969096166060850152505050608001529392505050565b6000816000190483118215151615612ace57612ace61271b565b500290565b600082612af057634e487b7160e01b600052601260045260246000fd5b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122079b280b8dc1549faf4a3cc31a7d4e85fe2c1c4675815c0b7f7c78d15a086770e64736f6c634300080e00336002805463ffffffff19166260000617905562278d00600355625eec006004556276a70060055560006006819055600e55661550f7dca70000600f556618de76816d80006010556801158e460913d0000060115561036060405264a2fb40580060e0908152648a88c37e00610100526475c10c9180610120526464174aaee061014052645513cc47d861016052644850d409de61018052643d77e76ec96101a05264343f84b7c56101c052642c6930cf676101e0526425bfcfe37e610200526420163d815f61022052641b461aadf76102405264172ec9e0ab610260526413b491fef8610280526410bfe27f206102a052640e3cb3b8db6102c052640c19ff29ed6102e052640a494c16d7610300526408be4d79d06103205264076e8ea78a610340526200013290601290601462000619565b506029805461ffff19166102581790553480156200014f57600080fd5b5060405162004954380380620049548339810160408190526200017291620006a0565b6200017d33620004e8565b600180556200018c8162000538565b6001600160a01b0384811660805283811660a052821660c0526040805160608101825273c766b8c9741bc804fcc378fde75560229ca3ab1e80825273682ce32507d2825a540ad31dc4c2b18432e0e5bd602080840182905273454cd1e89df17cdb61d868c6d3dbc02bc2c38a17938501849052602680546001600160a01b03199081169094179055602780548416909217909155602880549092169092179055600b90526301e133807f72c6bfb7988af3a1efa6568f02a999bc52252641c659d85961ca3d372b57d5cf8190556305a39a807fa50eece07c7db1631545c0069bd8f5f54d5935e215d59097edf258a44ba9163455600360005263096601807f64c15cc42be7899b001f818cf4433057002112c418d1d3a67cd5cb453051d33e559051829190620002bc9062000665565b6001600160a01b0390921682526020820152604001604051809103906000f080158015620002ee573d6000803e3d6000fd5b506001600052600c6020527fd421a5181c571bba3f01190c922c3b2a896fc1d84e86c9f17ac10e67ebef8b5c80546001600160a01b0319166001600160a01b039290921691909117905560405181906305a39a80906200034e9062000665565b6001600160a01b0390921682526020820152604001604051809103906000f08015801562000380573d6000803e3d6000fd5b506002600052600c6020527f5d6016397a73f5e079297ac5a36fef17b4d9c3831618e63ab105738020ddd72080546001600160a01b0319166001600160a01b03929092169190911790556040518190630966018090620003e09062000665565b6001600160a01b0390921682526020820152604001604051809103906000f08015801562000412573d6000803e3d6000fd5b507fc0da782485e77ae272268ae0a3ff44c1552ecb60b3743924de17a815e0a3cfd780546001600160a01b0319166001600160a01b03929092169190911790555050600d6020525050671bc16d674ec800007ffd54ff1ed53f34a900b24c5ba64f85761163b5d82d98a47b9bd80e45466993c55567a688906bd8b000007f10a81eed9d63d16face5e76357905348e6253d3394086026bb2bf2145d7cc2495560036000526801f399b1438a1000007f26b4a10d0f0b04925c23bd4480ee147c916e5e87a7d68206a533dad160ac81e25562000708565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b62000542620005bb565b6001600160a01b038116620005ad5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620005b881620004e8565b50565b6000546001600160a01b03163314620006175760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620005a4565b565b826014810192821562000653579160200282015b8281111562000653578251829064ffffffffff169055916020019190600101906200062d565b506200066192915062000673565b5090565b610fba806200399a83390190565b5b8082111562000661576000815560010162000674565b6001600160a01b0381168114620005b857600080fd5b60008060008060808587031215620006b757600080fd5b8451620006c4816200068a565b6020860151909450620006d7816200068a565b6040860151909350620006ea816200068a565b6060860151909250620006fd816200068a565b939692955090935050565b60805160a05160c0516132156200078560003960008181610728015281816127ec015281816128d8015281816129790152612a100152600081816109300152818161129e015261284301526000818161085a015281816112ce01528181611b8e015281816120b701528181612391015261279801526132156000f3fe6080604052600436106103035760003560e01c8063715018a611610190578063d904ecd9116100dc578063f4a0a52811610095578063f9b1be781161006f578063f9b1be7814610968578063fa8711aa146109ef578063fe0e6ee914610a0f578063fe96973a14610a3c57600080fd5b8063f4a0a528146108fe578063f887ea401461091e578063f98d4a881461095257600080fd5b8063d904ecd914610848578063dce0b4e41461087c578063dd418ae214610892578063de1f0713146108b2578063ed8c5e83146108c8578063f2fde38b146108de57600080fd5b8063a06db7dc11610149578063ac597cb211610123578063ac597cb2146107d9578063b6ed9d6f146107ec578063bbb7a42914610807578063c71fcd271461082857600080fd5b8063a06db7dc14610783578063a3a742d514610799578063ab98f4ae146107b957600080fd5b8063715018a6146106ce5780637586e3f9146106e35780637eed4a391461070357806389a30271146107165780638da5cb5b1461074a57806399d32fc41461076857600080fd5b80633db590931161024f5780635f8ee8641161020857806368237329116101e25780636823732914610643578063690d83201461066c5780636991b45c1461068c57806370a08231146106a157600080fd5b80635f8ee864146105ed578063601ea3311461060d5780636817c76c1461062d57600080fd5b80633db59093146105205780633f0609b414610540578063417314591461056057806343840c52146105805780634c20f90a146105a05780635bf3df4e146105c057600080fd5b8063208e831a116102bc57806332d4268a1161029657806332d4268a1461047c578063388fdd0c146104925780633aeac4e1146104e05780633b9738021461050057600080fd5b8063208e831a1461041e57806325627b54146104315780632f346b691461044457600080fd5b8063080b301e1461030f5780630adfdcb9146103385780630cf4680e1461038f5780630d06279e146103b15780630f3ac4a3146103d157806317b2e40a146103f157600080fd5b3661030a57005b600080fd5b34801561031b57600080fd5b50610325600f5481565b6040519081526020015b60405180910390f35b34801561034457600080fd5b50602654602754602854610365926001600160a01b03908116928116911683565b604080516001600160a01b039485168152928416602084015292169181019190915260600161032f565b34801561039b57600080fd5b506103af6103aa366004612aaa565b610a5c565b005b3480156103bd57600080fd5b506103af6103cc366004612adb565b610a7c565b3480156103dd57600080fd5b506103256103ec366004612b05565b610ac1565b3480156103fd57600080fd5b5061032561040c366004612b1e565b600d6020526000908152604090205481565b61032561042c366004612b05565b610ad7565b6103af61043f366004612b7e565b610b50565b34801561045057600080fd5b5061032561045f366004612bdf565b600960209081526000928352604080842090915290825290205481565b34801561048857600080fd5b5061032560105481565b34801561049e57600080fd5b506104c86104ad366004612b1e565b600c602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161032f565b3480156104ec57600080fd5b506103af6104fb366004612bfd565b610bea565b34801561050c57600080fd5b506103af61051b366004612b05565b610cd8565b34801561052c57600080fd5b506103af61053b366004612b05565b610e28565b34801561054c57600080fd5b506103af61055b366004612c36565b610e5f565b34801561056c57600080fd5b506103af61057b366004612c75565b610e8d565b34801561058c57600080fd5b506103af61059b366004612adb565b610ea3565b3480156105ac57600080fd5b506103af6105bb366004612ca1565b610ec2565b3480156105cc57600080fd5b506103256105db366004612b05565b600a6020526000908152604090205481565b3480156105f957600080fd5b50610325610608366004612b05565b610ed7565b61062061061b366004612cb9565b61110e565b60405161032f9190612cdb565b34801561063957600080fd5b5061032560115481565b34801561064f57600080fd5b5061065961271081565b60405161ffff909116815260200161032f565b34801561067857600080fd5b506103af610687366004612d1f565b611200565b34801561069857600080fd5b506103af61127f565b3480156106ad57600080fd5b506103256106bc366004612d1f565b60086020526000908152604090205481565b3480156106da57600080fd5b506103af61133e565b3480156106ef57600080fd5b506103af6106fe366004612d3c565b611352565b6103af610711366004612d7e565b6113b8565b34801561072257600080fd5b506104c87f000000000000000000000000000000000000000000000000000000000000000081565b34801561075657600080fd5b506000546001600160a01b03166104c8565b34801561077457600080fd5b506029546106599061ffff1681565b34801561078f57600080fd5b5061032560035481565b3480156107a557600080fd5b506106206107b4366004612daa565b611693565b3480156107c557600080fd5b506103af6107d4366004612d3c565b6117de565b6103af6107e7366004612cb9565b61186f565b3480156107f857600080fd5b506002546106599061ffff1681565b34801561081357600080fd5b506002546106599062010000900461ffff1681565b34801561083457600080fd5b506103af610843366004612d3c565b6118cf565b34801561085457600080fd5b506104c87f000000000000000000000000000000000000000000000000000000000000000081565b34801561088857600080fd5b50610325600e5481565b34801561089e57600080fd5b506103256108ad366004612b05565b61192b565b3480156108be57600080fd5b5061032560055481565b3480156108d457600080fd5b5061032560065481565b3480156108ea57600080fd5b506103af6108f9366004612d1f565b611942565b34801561090a57600080fd5b506103af610919366004612b05565b6119b8565b34801561092a57600080fd5b506104c87f000000000000000000000000000000000000000000000000000000000000000081565b34801561095e57600080fd5b5061032560045481565b34801561097457600080fd5b506109da610983366004612b05565b60076020819052600091825260409091208054600182015460028301546003840154600485015460058601546006870154969097015460ff8616976101009096046001600160a01b03169694959394929391929089565b60405161032f99989796959493929190612e5a565b3480156109fb57600080fd5b506103af610a0a366004612ec2565b6119c5565b348015610a1b57600080fd5b50610325610a2a366004612b1e565b600b6020526000908152604090205481565b348015610a4857600080fd5b506103af610a57366004612b05565b611a2b565b610a64611a5b565b6002805461ffff191661ffff92909216919091179055565b610a84611a5b565b80600b6000846003811115610a9b57610a9b612e44565b6003811115610aac57610aac612e44565b81526020810191909152604001600020555050565b600081600f54610ad19190612ef4565b92915050565b6000600260015403610b045760405162461bcd60e51b8152600401610afb90612f13565b60405180910390fd5b6002600155600e54610b1583610ac1565b610b1f9190612f4a565b3414610b3d5760405162461bcd60e51b8152600401610afb90612f62565b610b4682611ab5565b6001805592915050565b600260015403610b725760405162461bcd60e51b8152600401610afb90612f13565b60026001558180610b8283610ac1565b610b8c9190612ef4565b3414610baa5760405162461bcd60e51b8152600401610afb90612f62565b60005b81811015610bdf57610bd7858583818110610bca57610bca612f99565b9050602002013584611e12565b600101610bad565b505060018055505050565b610bf2611a5b565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610c40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c649190612faf565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd39190612fc8565b505050565b610ce0611a5b565b60008181526007602090815260408083205461010090046001600160a01b031683526008825280832054848452600a90925290912054808214610d655760008381526007602090815260408083205461010090046001600160a01b03168352600982528083208584528252808320548484528184208190558352600a90915290208190555b6000838152600a602090815260408083208390556007825280832080546001600160a01b03610100918290048116865260098552838620888752855283862086905591540416835260089091528120805491610dc083612fea565b909155505060068054906000610dd583612fea565b909155505050600091825250600760208190526040822080546001600160a81b03191681556001810183905560028101839055600381018390556004810183905560058101839055600681018390550155565b600260015403610e4a5760405162461bcd60e51b8152600401610afb90612f13565b6002600155610e5881611fcc565b5060018055565b610e67611a5b565b600e93909355600f919091556010556029805461ffff191661ffff909216919091179055565b610e95611a5b565b600392909255600455600555565b610eab611a5b565b80600d6000846003811115610a9b57610a9b612e44565b610eca611a5b565b806026610cd38282613021565b60008181526007602052604080822081516101208101909252805483929190829060ff166003811115610f0c57610f0c612e44565b6003811115610f1d57610f1d612e44565b815281546001600160a01b036101009182900416602083015260018301546040830152600283015460608301526003830154608080840191909152600484015460a0840152600584015460c0840152600684015460e084015260079093015491015281015190915060009060141115610fae576012826080015160148110610fa757610fa7612f99565b0154610fcf565b6012610fbc6001601461306e565b60148110610fcc57610fcc612f99565b01545b90506000816000846080015111610fea578360400151610ff0565b8360a001515b610ffa904261306e565b6110049190612ef4565b9050600454426110149190612f4a565b836040015110156111065760008360400151600454426110349190612f4a565b61103e919061306e565b905060646249d400821061105557506103846110d5565b62409980821061106857506103206110d5565b62375f00821061107b57506102bc6110d5565b622e2480821061108e57506102586110d5565b6224ea0082106110a157506101f46110d5565b621baf8082106110b457506101906110d5565b6212750082106110c7575061012c6110d5565b62093a8082106110d5575060c85b60006110e18285612ef4565b905060006110f182612710612152565b91506110ff9050818661306e565b9450505050505b949350505050565b60606002600154036111325760405162461bcd60e51b8152600401610afb90612f13565b6002600155600e54839061114584610ac1565b61114f9190612f4a565b6111599190612ef4565b34146111775760405162461bcd60e51b8152600401610afb90612f62565b8267ffffffffffffffff81111561119057611190613085565b6040519080825280602002602001820160405280156111b9578160200160208202803683370190505b50905060005b838110156111f5576111d083611ab5565b8282815181106111e2576111e2612f99565b60209081029190910101526001016111bf565b506001805592915050565b611208611a5b565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114611255576040519150601f19603f3d011682016040523d82523d6000602084013e61125a565b606091505b505090508061127b5760405162461bcd60e51b8152600401610afb9061309b565b5050565b611287611a5b565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015611317573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133b9190612fc8565b50565b611346611a5b565b6113506000612186565b565b6002600154036113745760405162461bcd60e51b8152600401610afb90612f13565b60026001558060005b818110156113ae576113a684848381811061139a5761139a612f99565b905060200201356121d6565b60010161137d565b5050600180555050565b6002600154036113da5760405162461bcd60e51b8152600401610afb90612f13565b60026001556000828152600760205260409020805461010090046001600160a01b0316331461141b5760405162461bcd60e51b8152600401610afb906130c7565b6000815460ff16600381111561143357611433612e44565b146114705760405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e48199d5cd959609a1b6044820152606401610afb565b428160020154116114935760405162461bcd60e51b8152600401610afb906130f2565b60105434146114b45760405162461bcd60e51b8152600401610afb90612f62565b6027546040516000916001600160a01b03169034908381818185875af1925050503d8060008114611501576040519150601f19603f3d011682016040523d82523d6000602084013e611506565b606091505b50509050806115275760405162461bcd60e51b8152600401610afb9061309b565b6000600c600085600381111561153f5761153f612e44565b600381111561155057611550612e44565b815260208101919091526040016000908120546001600160a01b0316915081906339d4d686903390600b9088600381111561158d5761158d612e44565b600381111561159e5761159e612e44565b815260200190815260200160002054426115b89190612f4a565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156115fe57600080fd5b505af1158015611612573d6000803e3d6000fd5b5050845486925085915060ff1916600183600381111561163457611634612e44565b0217905550426005840155600b600085600381111561165557611655612e44565b600381111561166657611666612e44565b815260200190815260200160002054426116809190612f4a565b6006909301929092555050600180555050565b606061169d611a5b565b85841480156116ab57508382145b6116ed5760405162461bcd60e51b815260206004820152601360248201527213195b99dd1a1cc81b9bdd08185b1a59db9959606a1b6044820152606401610afb565b858067ffffffffffffffff81111561170757611707613085565b604051908082528060200260200182016040528015611730578160200160208202803683370190505b50915060005b818110156117d2576117ad89898381811061175357611753612f99565b90506020020160208101906117689190612d1f565b88888481811061177a5761177a612f99565b9050602002013587878581811061179357611793612f99565b90506020020160208101906117a89190612b1e565b61252c565b8382815181106117bf576117bf612f99565b6020908102919091010152600101611736565b50509695505050505050565b6117e6611a5b565b601481146118275760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840d8cadccee8d60931b6044820152606401610afb565b8060005b818110156118695783838281811061184557611845612f99565b905060200201356012826014811061185f5761185f612f99565b015560010161182b565b50505050565b6002600154036118915760405162461bcd60e51b8152600401610afb90612f13565b600260015561189f81610ac1565b34146118bd5760405162461bcd60e51b8152600401610afb90612f62565b6118c78282611e12565b505060018055565b6002600154036118f15760405162461bcd60e51b8152600401610afb90612f13565b60026001558060005b818110156113ae5761192384848381811061191757611917612f99565b90506020020135611fcc565b6001016118fa565b6012816014811061193b57600080fd5b0154905081565b61194a611a5b565b6001600160a01b0381166119af5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610afb565b61133b81612186565b6119c0611a5b565b601155565b6119cd611a5b565b80600c60008460038111156119e4576119e4612e44565b60038111156119f5576119f5612e44565b815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b600260015403611a4d5760405162461bcd60e51b8152600401610afb90612f13565b6002600155610e58816121d6565b6000546001600160a01b031633146113505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610afb565b60025433600090815260086020526040812054909162010000900461ffff1611611b175760405162461bcd60e51b8152602060048201526013602482015272546f6f206d616e7920616d706c69666965727360681b6044820152606401610afb565b600082118015611b2d575060025461ffff168211155b611b6e5760405162461bcd60e51b81526020600482015260126024820152714d75737420626520312d36206d6f6e74687360701b6044820152606401610afb565b6011546040516390bca2fb60e01b815233600482015260248101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906390bca2fb906044016020604051808303816000875af1158015611bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c039190612fc8565b611c425760405162461bcd60e51b815260206004820152601060248201526f2737ba1030b13632903a3790313ab93760811b6044820152606401610afb565b602754600e546000916001600160a01b031690611c5e85610ac1565b611c689190612f4a565b604051600081818185875af1925050503d8060008114611ca4576040519150601f19603f3d011682016040523d82523d6000602084013e611ca9565b606091505b5050905080611cca5760405162461bcd60e51b8152600401610afb9061309b565b6006805460018082019092553360009081526008602052604080822080549485019055805161012081019091529192919081908152336020820152426040820152606001611d1b8762278d00612ef4565b611d259042612f4a565b8152600060208083018290526040808401839052606084018390526080840183905260a0909301829052858252600790522081518154829060ff19166001836003811115611d7557611d75612e44565b02179055506020828101518254610100600160a81b0319166101006001600160a01b0390921682021783556040808501516001850155606085015160028501556080850151600385015560a0850151600485015560c0850151600585015560e08501516006850155930151600790920191909155336000908152600982528281208482528252828120859055848152600a90915220559392505050565b6000828152600760205260409020805461010090046001600160a01b03163314611e4e5760405162461bcd60e51b8152600401610afb906130c7565b426003548260020154611e619190612f4a565b1015611ea65760405162461bcd60e51b815260206004820152601460248201527311dc9858d9481c195c9a5bd908195e1c1a5c995960621b6044820152606401610afb565b60008160020154421115611ed55762278d00826001015442611ec8919061306e565b611ed29190613133565b90505b60025461ffff16611ee68285612f4a565b1115611f265760405162461bcd60e51b815260206004820152600f60248201526e546f6f206d616e79206d6f6e74687360881b6044820152606401610afb565b6027546000906001600160a01b0316611f3e85610ac1565b604051600081818185875af1925050503d8060008114611f7a576040519150601f19603f3d011682016040523d82523d6000602084013e611f7f565b606091505b5050905080611fa05760405162461bcd60e51b8152600401610afb9061309b565b611fad8462278d00612ef4565b836002016000828254611fc09190612f4a565b90915550505050505050565b6000818152600760205260409020805461010090046001600160a01b031633146120085760405162461bcd60e51b8152600401610afb906130c7565b6000815460ff16600381111561202057612020612e44565b1461205f5760405162461bcd60e51b815260206004820152600f60248201526e135d5cdd081899481d5b999d5cd959608a1b6044820152606401610afb565b428160020154116120825760405162461bcd60e51b8152600401610afb906130f2565b600061208d83610ed7565b90506120988161274c565b60405163a9059cbb60e01b8152336004820152602481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015612108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212c9190612fc8565b5060038201805490600061213f83613155565b9190505550428260040181905550505050565b600080826000036121685750600090508061217f565b60018385816121795761217961311d565b04915091505b9250929050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000818152600760205260409020805461010090046001600160a01b031633146122125760405162461bcd60e51b8152600401610afb906130c7565b6000815460ff16600381111561222a5761222a612e44565b036122675760405162461bcd60e51b815260206004820152600d60248201526c135d5cdd08189948199d5cd959609a1b6044820152606401610afb565b4281600201541161228a5760405162461bcd60e51b8152600401610afb906130f2565b60055481600501544261229d919061306e565b116122e15760405162461bcd60e51b815260206004820152601460248201527310d85b9b9bdd0818db185a5b48115512081e595d60621b6044820152606401610afb565b8054600c9060009060ff1660038111156122fd576122fd612e44565b600381111561230e5761230e612e44565b81526020810191909152604090810160002054905163298ca82560e11b81523360048201526001600160a01b0390911690635319504a90602401600060405180830381600087803b15801561236257600080fd5b505af1158015612376573d6000803e3d6000fd5b505050504281600601541161127b5780546001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb903390600d9060009060ff1660038111156123d4576123d4612e44565b60038111156123e5576123e5612e44565b8152602001908152602001600020546040518363ffffffff1660e01b81526004016124259291906001600160a01b03929092168252602082015260400190565b6020604051808303816000875af1158015612444573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124689190612fc8565b61247157600080fd5b8054600c9060009060ff16600381111561248d5761248d612e44565b600381111561249e5761249e612e44565b81526020810191909152604090810160002054825491516322179b6160e21b81526101009092046001600160a01b039081166004840152169063885e6d8490602401600060405180830381600087803b1580156124fa57600080fd5b505af115801561250e573d6000803e3d6000fd5b5050825460ff19168355505060006005820181905560069091015550565b60025460009061ffff168311156125775760405162461bcd60e51b815260206004820152600f60248201526e546f6f206d616e79206d6f6e74687360881b6044820152606401610afb565b6006805460018082019092556001600160a01b03861660009081526008602052604081208054938401905590919080808660038111156125b9576125b9612e44565b1461260557429150600b60008760038111156125d7576125d7612e44565b60038111156125e8576125e8612e44565b815260200190815260200160002054426126029190612f4a565b90505b60405180610120016040528087600381111561262357612623612e44565b81526001600160a01b038a16602082015242604082015260600161264a8962278d00612ef4565b6126549042612f4a565b8152600060208083018290526040808401839052606084018790526080840186905260a0909301829052878252600790522081518154829060ff191660018360038111156126a4576126a4612e44565b02179055506020828101518254610100600160a81b0319166101006001600160a01b0392831681029190911784556040808601516001860155606086015160028601556080860151600386015560a0860151600486015560c0860151600586015560e086015160068601559401516007909301929092559916600090815260098a528181208582528a52818120869055858152600a9099529097209190915550949350505050565b6029546000908190612710906127669061ffff1685612ef4565b6127709190613133565b60408051600280825260608201835292935060009290916020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106127ca576127ca612f99565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061281e5761281e612f99565b6001600160a01b039283166020918202929092010152604051635c11d79560e01b81527f000000000000000000000000000000000000000000000000000000000000000090911690635c11d7959061288390859060009086903090429060040161316e565b600060405180830381600087803b15801561289d57600080fd5b505af11580156128b1573d6000803e3d6000fd5b50506040516370a0823160e01b815230600482015260009250600291506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561291f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129439190612faf565b61294d9190613133565b60265460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529192507f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156129c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e69190612fc8565b5060285460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015612a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7f9190612fc8565b50612a8a838661306e565b95945050505050565b803561ffff81168114612aa557600080fd5b919050565b600060208284031215612abc57600080fd5b612ac582612a93565b9392505050565b803560048110612aa557600080fd5b60008060408385031215612aee57600080fd5b612af783612acc565b946020939093013593505050565b600060208284031215612b1757600080fd5b5035919050565b600060208284031215612b3057600080fd5b612ac582612acc565b60008083601f840112612b4b57600080fd5b50813567ffffffffffffffff811115612b6357600080fd5b6020830191508360208260051b850101111561217f57600080fd5b600080600060408486031215612b9357600080fd5b833567ffffffffffffffff811115612baa57600080fd5b612bb686828701612b39565b909790965060209590950135949350505050565b6001600160a01b038116811461133b57600080fd5b60008060408385031215612bf257600080fd5b8235612af781612bca565b60008060408385031215612c1057600080fd5b8235612c1b81612bca565b91506020830135612c2b81612bca565b809150509250929050565b60008060008060808587031215612c4c57600080fd5b843593506020850135925060408501359150612c6a60608601612a93565b905092959194509250565b600080600060608486031215612c8a57600080fd5b505081359360208301359350604090920135919050565b600060608284031215612cb357600080fd5b50919050565b60008060408385031215612ccc57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b81811015612d1357835183529284019291840191600101612cf7565b50909695505050505050565b600060208284031215612d3157600080fd5b8135612ac581612bca565b60008060208385031215612d4f57600080fd5b823567ffffffffffffffff811115612d6657600080fd5b612d7285828601612b39565b90969095509350505050565b60008060408385031215612d9157600080fd5b82359150612da160208401612acc565b90509250929050565b60008060008060008060608789031215612dc357600080fd5b863567ffffffffffffffff80821115612ddb57600080fd5b612de78a838b01612b39565b90985096506020890135915080821115612e0057600080fd5b612e0c8a838b01612b39565b90965094506040890135915080821115612e2557600080fd5b50612e3289828a01612b39565b979a9699509497509295939492505050565b634e487b7160e01b600052602160045260246000fd5b610120810160048b10612e7d57634e487b7160e01b600052602160045260246000fd5b9981526001600160a01b0398909816602089015260408801969096526060870194909452608086019290925260a085015260c084015260e08301526101009091015290565b60008060408385031215612ed557600080fd5b612c1b83612acc565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615612f0e57612f0e612ede565b500290565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008219821115612f5d57612f5d612ede565b500190565b6020808252601c908201527f496e76616c69642045746865722076616c75652070726f766964656400000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fc157600080fd5b5051919050565b600060208284031215612fda57600080fd5b81518015158114612ac557600080fd5b600081612ff957612ff9612ede565b506000190190565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813561302c81612bca565b6130368183613001565b50602082013561304581612bca565b6130528160018401613001565b50604082013561306181612bca565b610cd38160028401613001565b60008282101561308057613080612ede565b500390565b634e487b7160e01b600052604160045260246000fd5b602080825260129082015271086deead8c840dcdee840e6cadcc8408aa8960731b604082015260600190565b6020808252601190820152700496e76616c6964206f776e65727368697607c1b604082015260600190565b602080825260119082015270105b5c1b1a599a595c88195e1c1a5c9959607a1b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b60008261315057634e487b7160e01b600052601260045260246000fd5b500490565b60006001820161316757613167612ede565b5060010190565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156131be5784516001600160a01b031683529383019391830191600101613199565b50506001600160a01b0396909616606085015250505060800152939250505056fea26469706673582212203cb6e20475b6d04fbfc48bc6bc047f6048f14a799522fe0744b5166904d6fce564736f6c634300080e003360c06040526ec097ce7bc90715b34b9f1000000000600a5534801561002357600080fd5b50604051610fba380380610fba833981016040819052610042916100b1565b61004b33610061565b61005482610061565b3360805260a052506100eb565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156100c457600080fd5b82516001600160a01b03811681146100db57600080fd5b6020939093015192949293505050565b60805160a051610e9c61011e6000396000610a740152600081816103550152818161059301526107ee0152610e9c6000f3fe6080604052600436106100fe5760003560e01c8063885e6d8411610095578063ce7c2ac211610064578063ce7c2ac214610284578063d0e30db0146102f6578063e2d2e219146102fe578063efca2eed14610314578063f2fde38b1461032a57600080fd5b8063885e6d84146102065780638da5cb5b14610226578063997664d71461024e578063a5978c661461026457600080fd5b80635319504a116100d15780635319504a14610184578063690d8320146101a4578063715018a6146101c457806377dd2037146101d957600080fd5b806311ce023d1461010357806339d4d6861461012c5780633a98ef391461014e5780633aeac4e114610164575b600080fd5b34801561010f57600080fd5b50610119600a5481565b6040519081526020015b60405180910390f35b34801561013857600080fd5b5061014c610147366004610caa565b61034a565b005b34801561015a57600080fd5b5061011960065481565b34801561017057600080fd5b5061014c61017f366004610cd6565b61049a565b34801561019057600080fd5b5061014c61019f366004610d0f565b610588565b3480156101b057600080fd5b5061014c6101bf366004610d0f565b61072f565b3480156101d057600080fd5b5061014c6107cf565b3480156101e557600080fd5b506101196101f4366004610d0f565b60046020526000908152604090205481565b34801561021257600080fd5b5061014c610221366004610d0f565b6107e3565b34801561023257600080fd5b506000546040516001600160a01b039091168152602001610123565b34801561025a57600080fd5b5061011960075481565b34801561027057600080fd5b5061011961027f366004610d0f565b6108d7565b34801561029057600080fd5b506102ce61029f366004610d0f565b600560205260009081526040902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a001610123565b61014c61096f565b34801561030a57600080fd5b5061011960095481565b34801561032057600080fd5b5061011960085481565b34801561033657600080fd5b5061014c610345366004610d0f565b6109c7565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461037f57600080fd5b6001600160a01b03821660009081526005602052604081205490036103fa57600180546001600160a01b03841660008181526002602052604081208390558284018455929092527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191690911790555b6006805490600061040a83610d49565b90915550506001600160a01b038216600090815260056020526040812080549161043383610d49565b90915550506001600160a01b0382166000908152600560205260409020600481018290554260038201819055905461046b9183610a40565b6001600160a01b03831660009081526005602052604090206001018190551561049657610496610d62565b5050565b6104a2610ad8565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa1580156104f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105149190610d78565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af115801561055f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105839190610d91565b505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105bd57600080fd5b60006105c8826108d7565b90508015610496576001600160a01b0382166000908152600560205260409020805460038201546004909201546105ff9290610a40565b6001600160a01b0383166000908152600560205260408120600181019290925560029091018054839290610634908490610db3565b92505081905550806008600082825461064d9190610db3565b90915550506040516000906001600160a01b0384169083908381818185875af1925050503d806000811461069d576040519150601f19603f3d011682016040523d82523d6000602084013e6106a2565b606091505b50509050806106ed5760405162461bcd60e51b8152602060048201526012602482015271086deead8c840dcdee840e6cadcc8408aa8960731b60448201526064015b60405180910390fd5b6001600160a01b038316600090815260046020526040902054610711908390610db3565b6001600160a01b038416600090815260046020526040902055505050565b610737610ad8565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610784576040519150601f19603f3d011682016040523d82523d6000602084013e610789565b606091505b50509050806104965760405162461bcd60e51b8152602060048201526012602482015271086deead8c840dcdee840e6cadcc8408aa8960731b60448201526064016106e4565b6107d7610ad8565b6107e16000610b32565b565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461081857600080fd5b6001600160a01b0381166000908152600560205260409020546001036108415761084181610b82565b6006805490600061085183610dcb565b90915550506001600160a01b03811660009081526005602052604090208054600390910154610881919080610a40565b6001600160a01b03821660009081526005602052604081206001810192909255815491906108ae83610dcb565b90915550506001600160a01b031660009081526005602052604081206003810182905560040155565b6001600160a01b03811660009081526005602052604081205481036108fe57506000919050565b6001600160a01b03821660009081526005602052604081208054600382015460049092015461092d9290610a40565b6001600160a01b03841660009081526005602052604090206001015490915080821161095d575060009392505050565b6109678183610de2565b949350505050565b610977610ad8565b6000349050806007600082825461098e9190610db3565b9091555050600654600a546109a4908390610df9565b6109ae9190610e18565b600960008282546109bf9190610db3565b909155505050565b6109cf610ad8565b6001600160a01b038116610a345760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106e4565b610a3d81610b32565b50565b600042821115610a4e574291505b6000600a5460095486610a619190610df9565b610a6b9190610e18565b90506000610a997f000000000000000000000000000000000000000000000000000000000000000086610db3565b90506000610aa78683610de2565b90506000610ab58787610de2565b905081610ac28286610df9565b610acc9190610e18565b98975050505050505050565b6000546001600160a01b031633146107e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60018054610b91908290610de2565b81548110610ba157610ba1610e3a565b60009182526020808320909101546001600160a01b0384811684526002909252604090922054600180549290931692918110610bdf57610bdf610e3a565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918316815260029182905260408120546001805491939291610c2a908290610de2565b81548110610c3a57610c3a610e3a565b60009182526020808320909101546001600160a01b031683528201929092526040019020556001805480610c7057610c70610e50565b600082815260209020810160001990810180546001600160a01b031916905501905550565b6001600160a01b0381168114610a3d57600080fd5b60008060408385031215610cbd57600080fd5b8235610cc881610c95565b946020939093013593505050565b60008060408385031215610ce957600080fd5b8235610cf481610c95565b91506020830135610d0481610c95565b809150509250929050565b600060208284031215610d2157600080fd5b8135610d2c81610c95565b9392505050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5b57610d5b610d33565b5060010190565b634e487b7160e01b600052600160045260246000fd5b600060208284031215610d8a57600080fd5b5051919050565b600060208284031215610da357600080fd5b81518015158114610d2c57600080fd5b60008219821115610dc657610dc6610d33565b500190565b600081610dda57610dda610d33565b506000190190565b600082821015610df457610df4610d33565b500390565b6000816000190483118215151615610e1357610e13610d33565b500290565b600082610e3557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfea26469706673582212207f0cb9de5878f336782a847edb2c02593e8ffe8c84dabe442038653657cf864664736f6c634300080e0033ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000069fa7c7198cb4eb1a032d0555104220b193370ab

Deployed Bytecode

0x6080604052600436106103035760003560e01c8063880934fd11610190578063a8aa1b31116100dc578063dd395c6311610095578063ea5293881161006f578063ea52938814610b59578063f2fde38b14610b79578063f887ea4014610b99578063f8b45b0514610bcd57600080fd5b8063dd395c6314610aeb578063dd62ed3e14610b0b578063e35a3d7c14610b4357600080fd5b8063a8aa1b3114610a03578063a9059cbb14610a37578063ad5c464814610a57578063af06795a14610a8b578063c2e5ec0414610aab578063cdae6b7a14610acb57600080fd5b806399c8d556116101495780639dc29fac116101235780639dc29fac146109895780639fd6db12146109a9578063a0712d68146109c3578063a0d27584146109e357600080fd5b806399c8d5561461084e5780639af1d35a1461086f5780639cece12e1461095957600080fd5b8063880934fd1461075957806389a30271146107795780638da5cb5b146107ad57806390bca2fb146107cb5780639571a07d146107eb57806395d89b411461081b57600080fd5b80633f4218e01161024f578063658d4b7f11610208578063690d8320116101e2578063690d8320146106c757806370a08231146106e7578063715018a614610714578063807fb8c51461072957600080fd5b8063658d4b7f1461067c57806366c4390d1461069c57806368237329146106b157600080fd5b80633f4218e0146105aa5780633fc645b5146105da57806348b98ef5146105fb5780634ada218b1461061d5780634d7547151461063d5780635d0044ca1461065c57600080fd5b806323b872dd116102bc57806332f29fc11161029657806332f29fc11461050f57806336203f481461054757806337bfc1ef1461055c5780633aeac4e11461058a57600080fd5b806323b872dd146104a8578063313ce567146104c8578063319f5f6a146104ef57600080fd5b8063069f22ec1461030f57806306fdde0314610338578063095ea7b3146103785780630adfdcb9146103a857806318160ddd146104705780631ff7637f1461048657600080fd5b3661030a57005b600080fd5b34801561031b57600080fd5b5061032560185481565b6040519081526020015b60405180910390f35b34801561034457600080fd5b5061036b60405180604001604052806007815260200166416d706c69666960c81b81525081565b60405161032f91906123ac565b34801561038457600080fd5b50610398610393366004612416565b610be3565b604051901515815260200161032f565b3480156103b457600080fd5b50600b54600c54600d54600e54600f546010546011546012546013546014546015546104059a6001600160a01b039081169a811699811698811697811696811695811694811693811692811691168b565b604080516001600160a01b039c8d1681529a8c1660208c0152988b16988a01989098529589166060890152938816608088015291871660a0870152861660c0860152851660e0850152841661010084015283166101208301529091166101408201526101600161032f565b34801561047c57600080fd5b5061032560015481565b34801561049257600080fd5b506104a66104a136600461245b565b610c4f565b005b3480156104b457600080fd5b506103986104c3366004612478565b610c69565b3480156104d457600080fd5b506104dd601281565b60405160ff909116815260200161032f565b3480156104fb57600080fd5b506104a661050a3660046124c9565b610cdb565b34801561051b57600080fd5b5060045461052f906001600160a01b031681565b6040516001600160a01b03909116815260200161032f565b34801561055357600080fd5b506104a6610d03565b34801561056857600080fd5b506017546105779061ffff1681565b60405161ffff909116815260200161032f565b34801561059657600080fd5b506104a66105a53660046124e6565b610d18565b3480156105b657600080fd5b506103986105c536600461251f565b60086020526000908152604090205460ff1681565b3480156105e657600080fd5b50601a54610398906301000000900460ff1681565b34801561060757600080fd5b5060175461039890640100000000900460ff1681565b34801561062957600080fd5b50601a546103989062010000900460ff1681565b34801561064957600080fd5b50601a5461039890610100900460ff1681565b34801561066857600080fd5b506104a661067736600461253c565b610e01565b34801561068857600080fd5b506104a6610697366004612563565b610e0e565b3480156106a857600080fd5b506104a6610e41565b3480156106bd57600080fd5b5061057761271081565b3480156106d357600080fd5b506104a66106e236600461251f565b610e55565b3480156106f357600080fd5b5061032561070236600461251f565b60026020526000908152604090205481565b34801561072057600080fd5b506104a6610edd565b34801561073557600080fd5b5061039861074436600461251f565b60096020526000908152604090205460ff1681565b34801561076557600080fd5b506104a661077436600461245b565b610ef1565b34801561078557600080fd5b5061052f7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b3480156107b957600080fd5b506000546001600160a01b031661052f565b3480156107d757600080fd5b506103986107e6366004612416565b61103a565b3480156107f757600080fd5b5061039861080636600461251f565b60076020526000908152604090205460ff1681565b34801561082757600080fd5b5061036b60405180604001604052806007815260200166414d504c49464960c81b81525081565b34801561085a57600080fd5b506017546105779062010000900461ffff1681565b34801561087b57600080fd5b506016546108f39061ffff80821691620100008104821691640100000000820481169166010000000000008104821691600160401b8204811691600160501b8104821691600160601b8204811691600160701b8104821691600160801b8204811691600160901b8104821691600160a01b909104168b565b6040805161ffff9c8d1681529a8c1660208c0152988b16988a01989098529589166060890152938816608088015291871660a0870152861660c0860152851660e0850152841661010084015283166101208301529091166101408201526101600161032f565b34801561096557600080fd5b5061039861097436600461251f565b600a6020526000908152604090205460ff1681565b34801561099557600080fd5b506103986109a4366004612416565b6111ba565b3480156109b557600080fd5b50601a546103989060ff1681565b3480156109cf57600080fd5b506104a66109de36600461253c565b6112b9565b3480156109ef57600080fd5b506104a66109fe366004612591565b611358565b348015610a0f57600080fd5b5061052f7f000000000000000000000000df527342aaedfc0683f4c75ad791a51e8aafaf4a81565b348015610a4357600080fd5b50610398610a52366004612416565b611387565b348015610a6357600080fd5b5061052f7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b348015610a9757600080fd5b506104a6610aa6366004612563565b611394565b348015610ab757600080fd5b506104a6610ac63660046125c6565b6113c7565b348015610ad757600080fd5b506104a6610ae6366004612563565b6113eb565b348015610af757600080fd5b506104a6610b06366004612563565b61141e565b348015610b1757600080fd5b50610325610b263660046124e6565b600360209081526000928352604080842090915290825290205481565b348015610b4f57600080fd5b5061032560195481565b348015610b6557600080fd5b506104a6610b7436600461251f565b611451565b348015610b8557600080fd5b506104a6610b9436600461251f565b6114d5565b348015610ba557600080fd5b5061052f7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b348015610bd957600080fd5b5061032560065481565b3360008181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610c3e9086815260200190565b60405180910390a350600192915050565b610c5761154e565b80600b610c648282612616565b505050565b6001600160a01b03831660009081526003602090815260408083203384529091528120546000198114610cc557610ca08382612731565b6001600160a01b03861660009081526003602090815260408083203384529091529020555b610cd08585856115a8565b9150505b9392505050565b610ce361154e565b6017805461ffff909216620100000263ffff000019909216919091179055565b610d0b61154e565b601a805461ff0019169055565b610d2061154e565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d929190612748565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c649190612761565b610e0961154e565b600655565b610e1661154e565b6001600160a01b03919091166000908152600860205260409020805460ff1916911515919091179055565b610e4961154e565b601a805460ff19169055565b610e5d61154e565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610eaa576040519150601f19603f3d011682016040523d82523d6000602084013e610eaf565b606091505b5050905080610ed95760405162461bcd60e51b8152600401610ed09061277e565b60405180910390fd5b5050565b610ee561154e565b610eef60006119ba565b565b610ef961154e565b806016610f0682826127b7565b50610f1b9050610160820161014083016124c9565b610f2d610140830161012084016124c9565b610f3f610120840161010085016124c9565b610f50610100850160e086016124c9565b610f6060e0860160c087016124c9565b610f7060c0870160a088016124c9565b610f8060a08801608089016124c9565b610f906080890160608a016124c9565b610fa060608a0160408b016124c9565b610fb060408b0160208c016124c9565b610fbd60208c018c6124c9565b610fc791906129ab565b610fd191906129ab565b610fdb91906129ab565b610fe591906129ab565b610fef91906129ab565b610ff991906129ab565b61100391906129ab565b61100d91906129ab565b61101791906129ab565b61102191906129ab565b6017805461ffff191661ffff9290921691909117905550565b6004546000906001600160a01b031633146110a95760405162461bcd60e51b815260206004820152602960248201527f4f6e6c792074686520416d706c6966696572204e6f646520636f6e74726163746044820152681031b0b710313ab93760b91b6064820152608401610ed0565b6001600160a01b0383166000908152600260205260409020548211156110e15760405162461bcd60e51b8152600401610ed0906129d1565b6001600160a01b0383166000908152600360209081526040808320338452909152902054600019811461113d576111188382612731565b6001600160a01b03851660009081526003602090815260408083203384529091529020555b826001600082825461114f9190612731565b90915550506001600160a01b0384166000908152600260205260408120805485929061117c908490612731565b90915550506040518381526000906001600160a01b03861690600080516020612af68339815191529060200160405180910390a35060019392505050565b60006111c461154e565b601a54610100900460ff166112115760405162461bcd60e51b8152602060048201526013602482015272109d5c9b9a5b99c81a5cc8191a5cd8589b1959606a1b6044820152606401610ed0565b6001600160a01b0383166000908152600260205260409020548211156112495760405162461bcd60e51b8152600401610ed0906129d1565b816001600082825461125b9190612731565b90915550506001600160a01b03831660009081526002602052604081208054849290611288908490612731565b90915550506040518281526000906001600160a01b03851690600080516020612af683398151915290602001610c3e565b6112c161154e565b601a5460ff166113095760405162461bcd60e51b8152602060048201526013602482015272135a5b9d1a5b99c81a5cc8191a5cd8589b1959606a1b6044820152606401610ed0565b806001600082825461131b9190612a15565b909155505033600081815260026020908152604080832080548601905551848152600080516020612af6833981519152910160405180910390a350565b61136061154e565b601780549315156401000000000264ff000000001990941693909317909255601855601955565b6000610cd43384846115a8565b61139c61154e565b6001600160a01b03919091166000908152600760205260409020805460ff1916911515919091179055565b6113cf61154e565b601a8054911515620100000262ff000019909216919091179055565b6113f361154e565b6001600160a01b03919091166000908152600a60205260409020805460ff1916911515919091179055565b61142661154e565b6001600160a01b03919091166000908152600960205260409020805460ff1916911515919091179055565b61145961154e565b600480546001600160a01b039283166001600160a01b0319918216811790925560058054909116821781556000918252600760209081526040808420805460ff19908116600190811790925584548716865260088452828620805482168317905593549095168452600990915290912080549091169091179055565b6114dd61154e565b6001600160a01b0381166115425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ed0565b61154b816119ba565b50565b6000546001600160a01b03163314610eef5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ed0565b601a546000906301000000900460ff16156115cf576115c8848484611a0a565b9050610cd4565b601a5462010000900460ff16806115fe57506001600160a01b03841660009081526007602052604090205460ff165b61164a5760405162461bcd60e51b815260206004820152601d60248201527f54726164696e672069732063757272656e746c792064697361626c65640000006044820152606401610ed0565b6001600160a01b0383166000908152600a602052604081205460ff16806116a257507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b0316846001600160a01b0316145b9050801580156116cb57506001600160a01b03841660009081526009602052604090205460ff16155b15611745576006546001600160a01b0385166000908152600260205260409020546116f7908590612a15565b11156117455760405162461bcd60e51b815260206004820152601d60248201527f4d61782077616c6c657420686173206265656e207472696767657265640000006044820152606401610ed0565b80801561175457506019548310155b80156117705750336000908152600a602052604090205460ff16155b80156117865750601a546301000000900460ff16155b801561179c5750601754640100000000900460ff165b80156117b957506018543060009081526002602052604090205410155b156117c6576117c6611a61565b6001600160a01b038516600090815260026020526040812080548592906117ee908490612731565b90915550506001600160a01b0385166000908152600a6020526040902054839060ff168061184d57507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b0316866001600160a01b0316145b806118ab57506001600160a01b0385166000908152600a602052604090205460ff16806118ab57507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b0316856001600160a01b0316145b6118b65760006118f8565b6001600160a01b03861660009081526008602052604090205460ff161580156118f857506001600160a01b03851660009081526008602052604090205460ff16155b1561190e5761190786856122bb565b9050611962565b6001600160a01b03861660009081526008602052604090205460ff1615801561195057506001600160a01b03851660009081526008602052604090205460ff16155b156119625761195f868561233d565b90505b6001600160a01b0380861660008181526002602052604090819020805485019055519091881690600080516020612af6833981519152906119a69085815260200190565b60405180910390a350600195945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038316600090815260026020526040812080548391908390611a34908490612731565b9091555050506001600160a01b038216600090815260026020526040902080548201905560019392505050565b601a805463ff0000001916630100000017905560408051600380825260808201909252479160009190602082016060803683370190505090503081600081518110611aae57611aae612a2d565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881600181518110611b0257611b02612a2d565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600281518110611b5657611b56612a2d565b6001600160a01b039283166020918202929092018101919091523060008181526002909252604080832054905163791ac94760e01b81527f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d9094169363791ac94793611bcb9390918791904290600401612a43565b600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b5050505060008247611c0b9190612731565b90506127108111156122a957600b546016546000916001600160a01b03169061271090611c3c9061ffff1685612ab4565b611c469190612ad3565b604051600081818185875af1925050503d8060008114611c82576040519150601f19603f3d011682016040523d82523d6000602084013e611c87565b606091505b50508091505080611caa5760405162461bcd60e51b8152600401610ed09061277e565b600c546016546001600160a01b039091169061271090611cd49062010000900461ffff1685612ab4565b611cde9190612ad3565b604051600081818185875af1925050503d8060008114611d1a576040519150601f19603f3d011682016040523d82523d6000602084013e611d1f565b606091505b50508091505080611d425760405162461bcd60e51b8152600401610ed09061277e565b600d546016546001600160a01b039091169061271090611d6e90640100000000900461ffff1685612ab4565b611d789190612ad3565b604051600081818185875af1925050503d8060008114611db4576040519150601f19603f3d011682016040523d82523d6000602084013e611db9565b606091505b50508091505080611ddc5760405162461bcd60e51b8152600401610ed09061277e565b600e546016546001600160a01b039091169061271090611e0a906601000000000000900461ffff1685612ab4565b611e149190612ad3565b604051600081818185875af1925050503d8060008114611e50576040519150601f19603f3d011682016040523d82523d6000602084013e611e55565b606091505b50508091505080611e785760405162461bcd60e51b8152600401610ed09061277e565b600f546016546001600160a01b039091169061271090611ea390600160401b900461ffff1685612ab4565b611ead9190612ad3565b604051600081818185875af1925050503d8060008114611ee9576040519150601f19603f3d011682016040523d82523d6000602084013e611eee565b606091505b50508091505080611f115760405162461bcd60e51b8152600401610ed09061277e565b6010546016546001600160a01b039091169061271090611f3c90600160501b900461ffff1685612ab4565b611f469190612ad3565b604051600081818185875af1925050503d8060008114611f82576040519150601f19603f3d011682016040523d82523d6000602084013e611f87565b606091505b50508091505080611faa5760405162461bcd60e51b8152600401610ed09061277e565b6011546016546001600160a01b039091169061271090611fd590600160601b900461ffff1685612ab4565b611fdf9190612ad3565b604051600081818185875af1925050503d806000811461201b576040519150601f19603f3d011682016040523d82523d6000602084013e612020565b606091505b505080915050806120435760405162461bcd60e51b8152600401610ed09061277e565b6012546016546001600160a01b03909116906127109061206e90600160701b900461ffff1685612ab4565b6120789190612ad3565b604051600081818185875af1925050503d80600081146120b4576040519150601f19603f3d011682016040523d82523d6000602084013e6120b9565b606091505b505080915050806120dc5760405162461bcd60e51b8152600401610ed09061277e565b6013546016546001600160a01b03909116906127109061210790600160801b900461ffff1685612ab4565b6121119190612ad3565b604051600081818185875af1925050503d806000811461214d576040519150601f19603f3d011682016040523d82523d6000602084013e612152565b606091505b505080915050806121755760405162461bcd60e51b8152600401610ed09061277e565b6014546016546001600160a01b0390911690612710906121a090600160901b900461ffff1685612ab4565b6121aa9190612ad3565b604051600081818185875af1925050503d80600081146121e6576040519150601f19603f3d011682016040523d82523d6000602084013e6121eb565b606091505b5050809150508061220e5760405162461bcd60e51b8152600401610ed09061277e565b6015546016546001600160a01b03909116906127109061223990600160a01b900461ffff1685612ab4565b6122439190612ad3565b604051600081818185875af1925050503d806000811461227f576040519150601f19603f3d011682016040523d82523d6000602084013e612284565b606091505b505080915050806122a75760405162461bcd60e51b8152600401610ed09061277e565b505b5050601a805463ff0000001916905550565b6017546000908190612710906122d59061ffff1685612ab4565b6122df9190612ad3565b306000818152600260205260409081902080548401905551919250906001600160a01b03861690600080516020612af6833981519152906123239085815260200190565b60405180910390a36123358184612731565b949350505050565b60175460009081906127109061235d9062010000900461ffff1685612ab4565b6123679190612ad3565b9050806001600082825461237b9190612731565b90915550506040518381526000906001600160a01b03861690600080516020612af683398151915290602001612323565b600060208083528351808285015260005b818110156123d9578581018301518582016040015282016123bd565b818111156123eb576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461154b57600080fd5b6000806040838503121561242957600080fd5b823561243481612401565b946020939093013593505050565b6000610160828403121561245557600080fd5b50919050565b6000610160828403121561246e57600080fd5b610cd48383612442565b60008060006060848603121561248d57600080fd5b833561249881612401565b925060208401356124a881612401565b929592945050506040919091013590565b61ffff8116811461154b57600080fd5b6000602082840312156124db57600080fd5b8135610cd4816124b9565b600080604083850312156124f957600080fd5b823561250481612401565b9150602083013561251481612401565b809150509250929050565b60006020828403121561253157600080fd5b8135610cd481612401565b60006020828403121561254e57600080fd5b5035919050565b801515811461154b57600080fd5b6000806040838503121561257657600080fd5b823561258181612401565b9150602083013561251481612555565b6000806000606084860312156125a657600080fd5b83356125b181612555565b95602085013595506040909401359392505050565b6000602082840312156125d857600080fd5b8135610cd481612555565b600081356125f081612401565b92915050565b80546001600160a01b0319166001600160a01b0392909216919091179055565b612628612622836125e3565b826125f6565b612640612637602084016125e3565b600183016125f6565b61265861264f604084016125e3565b600283016125f6565b612670612667606084016125e3565b600383016125f6565b61268861267f608084016125e3565b600483016125f6565b6126a061269760a084016125e3565b600583016125f6565b6126b86126af60c084016125e3565b600683016125f6565b6126d06126c760e084016125e3565b600783016125f6565b6126e96126e061010084016125e3565b600883016125f6565b6127026126f961012084016125e3565b600983016125f6565b610ed961271261014084016125e3565b600a83016125f6565b634e487b7160e01b600052601160045260246000fd5b6000828210156127435761274361271b565b500390565b60006020828403121561275a57600080fd5b5051919050565b60006020828403121561277357600080fd5b8151610cd481612555565b602080825260129082015271086deead8c840dcdee840e6cadcc8408aa8960731b604082015260600190565b600081356125f0816124b9565b81356127c2816124b9565b61ffff811661ffff19835416178255506127fb6127e1602084016127aa565b825463ffff0000191660109190911b63ffff000016178255565b61282861280a604084016127aa565b825465ffff00000000191660209190911b65ffff0000000016178255565b612859612837606084016127aa565b825467ffff000000000000191660309190911b67ffff00000000000016178255565b61288e612868608084016127aa565b825469ffff0000000000000000191660409190911b69ffff000000000000000016178255565b6128bd61289d60a084016127aa565b82805461ffff60501b191660509290921b61ffff60501b16919091179055565b6128ec6128cc60c084016127aa565b82805461ffff60601b191660609290921b61ffff60601b16919091179055565b61291b6128fb60e084016127aa565b82805461ffff60701b191660709290921b61ffff60701b16919091179055565b61294b61292b61010084016127aa565b82805461ffff60801b191660809290921b61ffff60801b16919091179055565b61297b61295b61012084016127aa565b82805461ffff60901b191660909290921b61ffff60901b16919091179055565b610ed961298b61014084016127aa565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b600061ffff8083168185168083038211156129c8576129c861271b565b01949350505050565b60208082526024908201527f43616e6e6f74206275726e206d6f7265207468616e20616e206163636f756e746040820152632068617360e01b606082015260800190565b60008219821115612a2857612a2861271b565b500190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015612a935784516001600160a01b031683529383019391830191600101612a6e565b50506001600160a01b03969096166060850152505050608001529392505050565b6000816000190483118215151615612ace57612ace61271b565b500290565b600082612af057634e487b7160e01b600052601260045260246000fd5b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122079b280b8dc1549faf4a3cc31a7d4e85fe2c1c4675815c0b7f7c78d15a086770e64736f6c634300080e0033

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

0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000069fa7c7198cb4eb1a032d0555104220b193370ab

-----Decoded View---------------
Arg [0] : _router (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [1] : _usdc (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [2] : _gampVault (address): 0x69FA7c7198CB4EB1A032D0555104220B193370aB

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [1] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [2] : 00000000000000000000000069fa7c7198cb4eb1a032d0555104220b193370ab


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.