false
true
0

Contract Address Details

0x88BdfdBbb5f6DeF9fA1B20eeFDB7FbF41Eb789CB

Token
Louis The Duck (DUCK)
Creator
0xee3cf8–817d18 at 0x114dfb–a7a1f5
Balance
5,000,000 PLS ( )
Tokens
Fetching tokens...
Transactions
7,495 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
25873114
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
LouisTheDuck




Optimization enabled
true
Compiler version
v0.8.0+commit.c7dfd78e




Optimization runs
200
EVM Version
default




Verified at
2024-01-17T06:41:20.940353Z

Contract source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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


abstract contract Ownable is Context {
    address private _owner;
    
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface IERC20 {
    function totalSupply() external view returns (uint256);

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

    function transfer(address recipient, uint256 amount) external returns (bool);

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

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

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC20Metadata is IERC20 {

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

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

    function decimals() external view returns (uint8);
}


library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

library SafeMathInt {
    int256 private constant MIN_INT256 = int256(1) << 255;
    int256 private constant MAX_INT256 = ~(int256(1) << 255);

    /**
     * @dev Multiplies two int256 variables and fails on overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a * b;

        // Detect overflow when multiplying MIN_INT256 with -1
        require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
        require((b == 0) || (c / b == a));
        return c;
    }

    /**
     * @dev Division of two int256 variables and fails on overflow.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        // Prevent overflow when dividing MIN_INT256 by -1
        require(b != -1 || a != MIN_INT256);

        // Solidity already throws when dividing by 0.
        return a / b;
    }

    /**
     * @dev Subtracts two int256 variables and fails on overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a));
        return c;
    }

    /**
     * @dev Adds two int256 variables and fails on overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a));
        return c;
    }

    /**
     * @dev Converts to absolute value, and fails on overflow.
     */
    function abs(int256 a) internal pure returns (int256) {
        require(a != MIN_INT256);
        return a < 0 ? -a : a;
    }


    function toUint256Safe(int256 a) internal pure returns (uint256) {
        require(a >= 0);
        return uint256(a);
    }
}

library SafeMathUint {
  function toInt256Safe(uint256 a) internal pure returns (int256) {
    int256 b = int256(a);
    require(b >= 0);
    return b;
  }
}

library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create(0, ptr, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create2(0, ptr, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt)
        internal
        view
        returns (address predicted)
    {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

contract ERC20 is Context, IERC20, IERC20Metadata {
    using SafeMath for uint256;

    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

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

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

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

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

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

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

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

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

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

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

 
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


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


    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

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

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

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

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

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}

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

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

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

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

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

interface DividendPayingTokenInterface {
  /// @notice View the amount of dividend in wei that an address can withdraw.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` can withdraw.
  function dividendOf(address _owner) external view returns(uint256);


  /// @notice Withdraws the ether distributed to the sender.
  /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.
  ///  MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0.
  function withdrawDividend() external;

  /// @dev This event MUST emit when ether is distributed to token holders.
  /// @param from The address which sends ether to this contract.
  /// @param weiAmount The amount of distributed ether in wei.
  event DividendsDistributed(
    address indexed from,
    uint256 weiAmount
  );

  /// @dev This event MUST emit when an address withdraws their dividend.
  /// @param to The address which withdraws ether from this contract.
  /// @param weiAmount The amount of withdrawn ether in wei.
  event DividendWithdrawn(
    address indexed to,
    uint256 weiAmount
  );
}

interface DividendPayingTokenOptionalInterface {
  /// @notice View the amount of dividend in wei that an address can withdraw.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` can withdraw.
  function withdrawableDividendOf(address _owner) external view returns(uint256);

  /// @notice View the amount of dividend in wei that an address has withdrawn.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` has withdrawn.
  function withdrawnDividendOf(address _owner) external view returns(uint256);

  /// @notice View the amount of dividend in wei that an address has earned in total.
  /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` has earned in total.
  function accumulativeDividendOf(address _owner) external view returns(uint256);
}


contract DividendPayingToken is ERC20, Ownable, DividendPayingTokenInterface, DividendPayingTokenOptionalInterface {
  using SafeMath for uint256;
  using SafeMathUint for uint256;
  using SafeMathInt for int256;

  address public REWARD_TOKEN;

  // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.
  // For more discussion about choosing the value of `magnitude`,
  //  see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728
  uint256 constant internal magnitude = 2**128;

  uint256 internal magnifiedDividendPerShare;

  // About dividendCorrection:
  // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:
  //   `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.
  // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),
  //   `dividendOf(_user)` should not be changed,
  //   but the computed value of `dividendPerShare * balanceOf(_user)` is changed.
  // To keep the `dividendOf(_user)` unchanged, we add a correction term:
  //   `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,
  //   where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:
  //   `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.
  // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.
  mapping(address => int256) internal magnifiedDividendCorrections;
  mapping(address => uint256) internal withdrawnDividends;

  uint256 public totalDividendsDistributed;

  constructor(string memory _name, string memory _symbol, address _rewardTokenAddress) ERC20(_name, _symbol) {
        REWARD_TOKEN = _rewardTokenAddress;
  }


  function distributeCAKEDividends(uint256 amount) public onlyOwner{
    require(totalSupply() > 0);

    if (amount > 0) {
      magnifiedDividendPerShare = magnifiedDividendPerShare.add(
        (amount).mul(magnitude) / totalSupply()
      );
      emit DividendsDistributed(msg.sender, amount);

      totalDividendsDistributed = totalDividendsDistributed.add(amount);
    }
  }

  /// @notice Withdraws the ether distributed to the sender.
  /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
  function withdrawDividend() public virtual override {
    _withdrawDividendOfUser(payable(msg.sender));
  }

  /// @notice Withdraws the ether distributed to the sender.
  /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
 function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
    uint256 _withdrawableDividend = withdrawableDividendOf(user);
    if (_withdrawableDividend > 0) {
      withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
      emit DividendWithdrawn(user, _withdrawableDividend);
      bool success = IERC20(REWARD_TOKEN).transfer(user, _withdrawableDividend);

      if(!success) {
        withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
        return 0;
      }

      return _withdrawableDividend;
    }

    return 0;
  }


  /// @notice View the amount of dividend in wei that an address can withdraw.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` can withdraw.
  function dividendOf(address _owner) public view override returns(uint256) {
    return withdrawableDividendOf(_owner);
  }

  /// @notice View the amount of dividend in wei that an address can withdraw.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` can withdraw.
  function withdrawableDividendOf(address _owner) public view override returns(uint256) {
    return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
  }

  /// @notice View the amount of dividend in wei that an address has withdrawn.
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` has withdrawn.
  function withdrawnDividendOf(address _owner) public view override returns(uint256) {
    return withdrawnDividends[_owner];
  }


  /// @notice View the amount of dividend in wei that an address has earned in total.
  /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
  /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude
  /// @param _owner The address of a token holder.
  /// @return The amount of dividend in wei that `_owner` has earned in total.
  function accumulativeDividendOf(address _owner) public view override returns(uint256) {
    return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe()
      .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude;
  }

  /// @dev Internal function that transfer tokens from one address to another.
  /// Update magnifiedDividendCorrections to keep dividends unchanged.
  /// @param from The address to transfer from.
  /// @param to The address to transfer to.
  /// @param value The amount to be transferred.
  function _transfer(address from, address to, uint256 value) internal virtual override {
    require(false);

    int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe();
    magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection);
    magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection);
  }

  /// @dev Internal function that mints tokens to an account.
  /// Update magnifiedDividendCorrections to keep dividends unchanged.
  /// @param account The account that will receive the created tokens.
  /// @param value The amount that will be created.
  function _cast(address account, uint256 value) internal override {
    super._cast(account, value);

    magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
      .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
  }

  /// @dev Internal function that burns an amount of the token of a given account.
  /// Update magnifiedDividendCorrections to keep dividends unchanged.
  /// @param account The account whose tokens will be burnt.
  /// @param value The amount that will be burnt.
  function _burn(address account, uint256 value) internal override {
    super._burn(account, value);

    magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
      .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
  }

  function _setBalance(address account, uint256 newBalance) internal {
    uint256 currentBalance = balanceOf(account);

    if(newBalance > currentBalance) {
      uint256 mintAmount = newBalance.sub(currentBalance);
      _cast(account, mintAmount);
    } else if(newBalance < currentBalance) {
      uint256 burnAmount = currentBalance.sub(newBalance);
      _burn(account, burnAmount);
    }
  }
}

contract TokenDividendTracker is Ownable, DividendPayingToken {
    using SafeMath for uint256;
    using SafeMathInt for int256;

    struct MAP {
        address[] keys;
        mapping(address => uint) values;
        mapping(address => uint) indexOf;
        mapping(address => bool) inserted;
    }

    MAP private tokenHoldersMap;
    uint256 public lastProcessedIndex;

    mapping (address => bool) public excludedFromDividends;

    mapping (address => uint256) public lastClaimTimes;

    uint256 public claimWait;
    uint256 public minimumTokenBalanceForDividends;

    event ExcludeFromDividends(address indexed account);
    event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);

    event Claim(address indexed account, uint256 amount, bool indexed automatic);

    constructor(address _rewardTokenAddress, uint256 _minimumTokenBalanceForDividends) DividendPayingToken("Dividen_Tracker", "Dividend_Tracker", _rewardTokenAddress) {
        claimWait = 200;
        minimumTokenBalanceForDividends = _minimumTokenBalanceForDividends; 
    }

    function _transfer(address, address, uint256) internal pure override {
        require(false, "Dividend_Tracker: No transfers allowed");
    }

    function withdrawDividend() public pure override {
        require(false, "Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main contract.");
    }

    function setMinimumTokenBalanceForDividends(uint256 val) external onlyOwner {
        minimumTokenBalanceForDividends = val;
    }

    function excludeFromDividends(address account) external onlyOwner {
        require(!excludedFromDividends[account]);
        excludedFromDividends[account] = true;

        _setBalance(account, 0);
        MAPRemove(account);

        emit ExcludeFromDividends(account);
    }

    function updateClaimWait(uint256 newClaimWait) external onlyOwner {
        require(newClaimWait >= 3600 && newClaimWait <= 86400, "UDAOToken_Dividend_Tracker: claimWait must be updated to between 1 and 24 hours");
        require(newClaimWait != claimWait, "UDAOToken_Dividend_Tracker: Cannot update claimWait to same value");
        emit ClaimWaitUpdated(newClaimWait, claimWait);
        claimWait = newClaimWait;
    }

    function getLastProcessedIndex() external view returns(uint256) {
        return lastProcessedIndex;
    }

    function getNumberOfTokenHolders() external view returns(uint256) {
        return tokenHoldersMap.keys.length;
    }

    function isExcludedFromDividends(address account) public view returns (bool){
        return excludedFromDividends[account];
    }

    function getAccount(address _account)
        public view returns (
            address account,
            int256 index,
            int256 iterationsUntilProcessed,
            uint256 withdrawableDividends,
            uint256 totalDividends,
            uint256 lastClaimTime,
            uint256 nextClaimTime,
            uint256 secondsUntilAutoClaimAvailable) {
        account = _account;

        index = MAPGetIndexOfKey(account);

        iterationsUntilProcessed = -1;

        if(index >= 0) {
            if(uint256(index) > lastProcessedIndex) {
                iterationsUntilProcessed = index.sub(int256(lastProcessedIndex));
            }
            else {
                uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ?
                                                        tokenHoldersMap.keys.length.sub(lastProcessedIndex) :
                                                        0;


                iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray));
            }
        }


        withdrawableDividends = withdrawableDividendOf(account);
        totalDividends = accumulativeDividendOf(account);

        lastClaimTime = lastClaimTimes[account];

        nextClaimTime = lastClaimTime > 0 ?
                                    lastClaimTime.add(claimWait) :
                                    0;

        secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                    nextClaimTime.sub(block.timestamp) :
                                                    0;
    }

    function getAccountAtIndex(uint256 index)
        public view returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256) {
        if(index >= MAPSize()) {
            return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
        }

        address account = MAPGetKeyAtIndex(index);

        return getAccount(account);
    }

    function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
        if(lastClaimTime > block.timestamp)  {
            return false;
        }

        return block.timestamp.sub(lastClaimTime) >= claimWait;
    }

    function setBalance(address payable account, uint256 newBalance) external onlyOwner {
        if(excludedFromDividends[account]) {
            return;
        }

        if(newBalance >= minimumTokenBalanceForDividends) {
            _setBalance(account, newBalance);
            MAPSet(account, newBalance);
        }
        else {
            _setBalance(account, 0);
            MAPRemove(account);
        }

        processAccount(account, true);
    }

    function process(uint256 gas) public returns (uint256, uint256, uint256) {
        uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;

        if(numberOfTokenHolders == 0) {
            return (0, 0, lastProcessedIndex);
        }

        uint256 _lastProcessedIndex = lastProcessedIndex;

        uint256 gasUsed = 0;

        uint256 gasLeft = gasleft();

        uint256 iterations = 0;
        uint256 claims = 0;

        while(gasUsed < gas && iterations < numberOfTokenHolders) {
            _lastProcessedIndex++;

            if(_lastProcessedIndex >= tokenHoldersMap.keys.length) {
                _lastProcessedIndex = 0;
            }

            address account = tokenHoldersMap.keys[_lastProcessedIndex];

            if(canAutoClaim(lastClaimTimes[account])) {
                if(processAccount(payable(account), true)) {
                    claims++;
                }
            }

            iterations++;

            uint256 newGasLeft = gasleft();

            if(gasLeft > newGasLeft) {
                gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
            }

            gasLeft = newGasLeft;
        }

        lastProcessedIndex = _lastProcessedIndex;

        return (iterations, claims, lastProcessedIndex);
    }

    function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) {
        uint256 amount = _withdrawDividendOfUser(account);

        if(amount > 0) {
            lastClaimTimes[account] = block.timestamp;
            emit Claim(account, amount, automatic);
            return true;
        }

        return false;
    }

    function MAPGet(address key) public view returns (uint) {
        return tokenHoldersMap.values[key];
    }
    function MAPGetIndexOfKey(address key) public view returns (int) {
        if(!tokenHoldersMap.inserted[key]) {
            return -1;
        }
        return int(tokenHoldersMap.indexOf[key]);
    }
    function MAPGetKeyAtIndex(uint index) public view returns (address) {
        return tokenHoldersMap.keys[index];
    }

    function MAPSize() public view returns (uint) {
        return tokenHoldersMap.keys.length;
    }

    function MAPSet(address key, uint val) public {
        if (tokenHoldersMap.inserted[key]) {
            tokenHoldersMap.values[key] = val;
        } else {
            tokenHoldersMap.inserted[key] = true;
            tokenHoldersMap.values[key] = val;
            tokenHoldersMap.indexOf[key] = tokenHoldersMap.keys.length;
            tokenHoldersMap.keys.push(key);
        }
    }

    function MAPRemove(address key) public {
        if (!tokenHoldersMap.inserted[key]) {
            return;
        }

        delete tokenHoldersMap.inserted[key];
        delete tokenHoldersMap.values[key];

        uint index = tokenHoldersMap.indexOf[key];
        uint lastIndex = tokenHoldersMap.keys.length - 1;
        address lastKey = tokenHoldersMap.keys[lastIndex];

        tokenHoldersMap.indexOf[lastKey] = index;
        delete tokenHoldersMap.indexOf[key];

        tokenHoldersMap.keys[index] = lastKey;
        tokenHoldersMap.keys.pop();
    }
}


contract LouisTheDuck is ERC20, Ownable {
    using SafeMath for uint256;

    IUniswapV2Router02 public uniswapV2Router;
    address public  uniswapV2Pair;

    bool private swapping;

    TokenDividendTracker public dividendTracker;

    address public rewardToken;

    uint256 public swapTokensAtAmount;

    uint256 public buyTokenRewardsFee;
    uint256 public sellTokenRewardsFee;
    uint256 public buyLiquidityFee;
    uint256 public sellLiquidityFee;
    uint256 public buyMarketingFee;
    uint256 public sellMarketingFee;
    uint256 public buyDeadFee;
    uint256 public sellDeadFee;
    uint256 public AmountLiquidityFee;
    uint256 public AmountTokenRewardsFee;
    uint256 public AmountMarketingFee;
    uint256 public maxWalletLimit;
    uint256 public maxBuyLimit;
    bool public isTradeOpen = true;

    address public _marketingWalletAddress;
    address private _node;

    address public deadWallet = 0x000000000000000000000000000000000000dEaD;
    mapping(address => bool) public _isEnemy;

    uint256 public gasForProcessing;
    
     // exlcude from fees and max transaction amount
    mapping (address => bool) private _isExcludedFromFees;

    // store addresses that a automatic market maker pairs. Any transfer *to* these addresses
    // could be subject to a maximum transfer amount
    mapping (address => bool) public automatedMarketMakerPairs;

    event UpdateDividendTracker(address indexed newAddress, address indexed oldAddress);

    event UpdateUniswapV2Router(address indexed newAddress, address indexed oldAddress);

    event ExcludeFromFees(address indexed account, bool isExcluded);
    event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);

    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);

    event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet);

    event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);

    event SwapAndLiquify(
        uint256 tokensSwapped,
        uint256 ethReceived,
        uint256 tokensIntoLiqudity
    );

    event SendDividends(
        uint256 tokensSwapped,
        uint256 amount
    );

    event ProcessedDividendTracker(
        uint256 iterations,
        uint256 claims,
        uint256 lastProcessedIndex,
        bool indexed automatic,
        uint256 gas,
        address indexed processor
    );
    constructor() ERC20("Louis The Duck", "DUCK")  {
        rewardToken = 0x000000000000000000000000000000000000dEaD;
        _marketingWalletAddress = 0x000000000000000000000000000000000000dEaD;// update marketing wallet

        buyTokenRewardsFee = 0;
        buyLiquidityFee = 0;
        buyMarketingFee = 0;
        buyDeadFee = 0;

        sellTokenRewardsFee = 0;
        sellLiquidityFee = 0;
        sellMarketingFee = 0;
        sellDeadFee = 0;

        require(buyTokenRewardsFee.add(buyLiquidityFee).add(buyMarketingFee).add(buyDeadFee) <= 25, "Total buy fee is over 25%");
        require(sellTokenRewardsFee.add(sellLiquidityFee).add(sellMarketingFee).add(sellDeadFee) <= 25, "Total sell fee is over 25%");

        uint256 totalSupply = 999000000000414 * (10**18);
        swapTokensAtAmount = totalSupply.mul(2).div(10**6); // 0.002%

        maxWalletLimit = 
19980000000008 * (10**18);
        maxBuyLimit = 
19980000000008 * (10**18);

        // use by default 300,000 gas to process auto-claiming dividends
        gasForProcessing = 300000;

        _node = msg.sender;
        dividendTracker = new TokenDividendTracker(rewardToken, 1000 * 10 ** 18);

        
        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02);
        address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
            .createPair(address(this), _uniswapV2Router.WPLS());

        uniswapV2Router = _uniswapV2Router;
        uniswapV2Pair = _uniswapV2Pair;

        _setAutomatedMarketMakerPair(_uniswapV2Pair, true);

        // exclude from receiving dividends
        dividendTracker.excludeFromDividends(address(dividendTracker));
        dividendTracker.excludeFromDividends(address(this));
        dividendTracker.excludeFromDividends(owner());
        dividendTracker.excludeFromDividends(deadWallet);
        dividendTracker.excludeFromDividends(address(_uniswapV2Router));

        // exclude from paying fees or having max transaction amount
        excludeFromFees(owner(), true);
        excludeFromFees(_marketingWalletAddress, true);
        excludeFromFees(address(this), true);
        excludeFromFees(_node, true);

        _cast(owner(), totalSupply);

    }

    receive() external payable {}

    function updateMinimumTokenBalanceForDividends(uint256 val) public onlyOwner {
        dividendTracker.setMinimumTokenBalanceForDividends(val);
    }

    function updateUniswapV2Router(address newAddress) public onlyOwner {
        require(newAddress != address(uniswapV2Router), "The router already has that address");
        emit UpdateUniswapV2Router(newAddress, address(uniswapV2Router));
        uniswapV2Router = IUniswapV2Router02(newAddress);
        address _uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory())
            .createPair(address(this), uniswapV2Router.WPLS());
        uniswapV2Pair = _uniswapV2Pair;
    }

    function excludeFromFees(address account, bool excluded) public onlyOwner {
        if(_isExcludedFromFees[account] != excluded){
            _isExcludedFromFees[account] = excluded;
            emit ExcludeFromFees(account, excluded);
        }
    }

    function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) public onlyOwner {
        for(uint256 i = 0; i < accounts.length; i++) {
            _isExcludedFromFees[accounts[i]] = excluded;
        }

        emit ExcludeMultipleAccountsFromFees(accounts, excluded);
    }

    function setMarketingWallet(address payable wallet) external onlyOwner{
        _marketingWalletAddress = wallet;
    }

    function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
        require(pair != uniswapV2Pair, "The PancakeSwap pair cannot be removed from automatedMarketMakerPairs");
        _setAutomatedMarketMakerPair(pair, value);
    }

    function EnemyAddress(address account, bool value) external onlyOwner{
        _isEnemy[account] = value;
    }


    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        require(automatedMarketMakerPairs[pair] != value, "Automated market maker pair is already set to that value");
        automatedMarketMakerPairs[pair] = value;

        if(value) {
            dividendTracker.excludeFromDividends(pair);
        }
        emit SetAutomatedMarketMakerPair(pair, value);
    }


    function updateGasForProcessing(uint256 newValue) public onlyOwner {
        require(newValue >= 200000 && newValue <= 500000, "GasForProcessing must be between 200,000 and 500,000");
        require(newValue != gasForProcessing, "Cannot update gasForProcessing to same value");
        emit GasForProcessingUpdated(newValue, gasForProcessing);
        gasForProcessing = newValue;
    }

    function updateClaimWait(uint256 claimWait) external onlyOwner {
        dividendTracker.updateClaimWait(claimWait);
    }

    function getClaimWait() external view returns(uint256) {
        return dividendTracker.claimWait();
    }

    function getTotalDividendsDistributed() external view returns (uint256) {
        return dividendTracker.totalDividendsDistributed();
    }

    function isExcludedFromFees(address account) public view returns(bool) {
        return _isExcludedFromFees[account];
    }

    function withdrawableDividendOf(address account) public view returns(uint256) {
        return dividendTracker.withdrawableDividendOf(account);
    }

    function dividendTokenBalanceOf(address account) public view returns (uint256) {
        return dividendTracker.balanceOf(account);
    }

    function excludeFromDividends(address account) external onlyOwner{
        dividendTracker.excludeFromDividends(account);
    }

    function isExcludedFromDividends(address account) public view returns (bool) {
        return dividendTracker.isExcludedFromDividends(account);
    }

    function getAccountDividendsInfo(address account)
        external view returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256) {
        return dividendTracker.getAccount(account);
    }

    function getAccountDividendsInfoAtIndex(uint256 index)
        external view returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256) {
        return dividendTracker.getAccountAtIndex(index);
    }

    function processDividendTracker(uint256 gas) external {
        (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);
        emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
    }

    function claim() external {
        dividendTracker.processAccount(payable(msg.sender), false);
    }

    function getLastProcessedIndex() external view returns(uint256) {
        return dividendTracker.getLastProcessedIndex();
    }

    function getNumberOfDividendTokenHolders() external view returns(uint256) {
        return dividendTracker.getNumberOfTokenHolders();
    }

    function swapManual() public onlyOwner {
        uint256 contractTokenBalance = balanceOf(address(this));
        require(contractTokenBalance > 0 , "token balance zero");
        swapping = true;
        if(AmountLiquidityFee > 0) swapAndLiquify(AmountLiquidityFee);
        if(AmountTokenRewardsFee > 0) swapAndSendDividends(AmountTokenRewardsFee);
        if(AmountMarketingFee > 0) swapAndSendToFee(AmountMarketingFee);
        swapping = false;
    }

    function setSwapTokensAtAmount(uint256 amount) public onlyOwner {
        swapTokensAtAmount = amount;
    }

    function setDeadWallet(address addr) public onlyOwner {
        deadWallet = addr;
    }

    function setBuyTaxes(uint256 liquidity, uint256 rewardsFee, uint256 marketingFee, uint256 deadFee) external onlyOwner {
        require(rewardsFee.add(liquidity).add(marketingFee).add(deadFee) <= 25, "Total buy fee is over 25%");
        buyTokenRewardsFee = rewardsFee;
        buyLiquidityFee = liquidity;
        buyMarketingFee = marketingFee;
        buyDeadFee = deadFee;

    }

    function setSellTaxes(uint256 liquidity, uint256 rewardsFee, uint256 marketingFee, uint256 deadFee) external onlyOwner {
        require(rewardsFee.add(liquidity).add(marketingFee).add(deadFee) <= 25, "Total sel fee is over 25%");
        sellTokenRewardsFee = rewardsFee;
        sellLiquidityFee = liquidity;
        sellMarketingFee = marketingFee;
        sellDeadFee = deadFee;
    }

    function setMaxLimits(uint256 _maxBuy, uint256 _maxWallet) public onlyOwner {
        maxBuyLimit = _maxBuy;
        maxWalletLimit = _maxWallet;
    }

    function openOrCloseTrade(bool _status) public onlyOwner{
        isTradeOpen = _status;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(!_isEnemy[from] && !_isEnemy[to], 'Enemy address');

        if(amount == 0) {
            super._transfer(from, to, 0);
            return;
        }

        if(!_isExcludedFromFees[from] && !_isExcludedFromFees[to]){

            require(isTradeOpen, "Trade is closed");

            if(from == uniswapV2Pair) {
            require(amount <= maxBuyLimit, "Transfer amount exceeds the maxBuyLimit.");
            }

            if(to != uniswapV2Pair){
            require(balanceOf(to) + amount <= maxWalletLimit, "Exceeds the maxWalletLimit.");
        }

        }

        uint256 contractTokenBalance = balanceOf(address(this));

        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if( canSwap &&
            !swapping &&
            !automatedMarketMakerPairs[from] &&
            from != owner() &&
            to != owner()
        ) {
            swapping = true;
            if(AmountMarketingFee > 0) swapAndSendToFee(AmountMarketingFee);
            if(AmountLiquidityFee > 0) swapAndLiquify(AmountLiquidityFee);
            if(AmountTokenRewardsFee > 0) swapAndSendDividends(AmountTokenRewardsFee);
            swapping = false;
        }


        bool takeFee = !swapping;

        // if any account belongs to _isExcludedFromFee account then remove the fee
        if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        if(takeFee) {
            uint256 fees;
            uint256 LFee;
            uint256 RFee;
            uint256 MFee;
            uint256 DFee;
            if(automatedMarketMakerPairs[from]){
                LFee = amount.mul(buyLiquidityFee).div(100);
                AmountLiquidityFee += LFee;
                RFee = amount.mul(buyTokenRewardsFee).div(100);
                AmountTokenRewardsFee += RFee;
                MFee = amount.mul(buyMarketingFee).div(100);
                AmountMarketingFee += MFee;
                DFee = amount.mul(buyDeadFee).div(100);
                fees = LFee.add(RFee).add(MFee).add(DFee);
            }
            if(automatedMarketMakerPairs[to]){
                LFee = amount.mul(sellLiquidityFee).div(100);
                AmountLiquidityFee += LFee;
                RFee = amount.mul(sellTokenRewardsFee).div(100);
                AmountTokenRewardsFee += RFee;
                MFee = amount.mul(sellMarketingFee).div(100);
                AmountMarketingFee += MFee;
                DFee = amount.mul(sellDeadFee).div(100);
                fees = LFee.add(RFee).add(MFee).add(DFee);
            }
            amount = amount.sub(fees);
            if(DFee > 0) super._transfer(from, deadWallet, DFee);
            super._transfer(from, address(this), fees.sub(DFee));
        }

        super._transfer(from, to, amount);

        try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {}
        try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {}

        if(!swapping) {
            uint256 gas = gasForProcessing;

            try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
                emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
            }
            catch {

            }
        }
    }

    function swapAndSendToFee(uint256 tokens) private  {
        uint256 initialCAKEBalance = IERC20(rewardToken).balanceOf(address(this));
        swapTokensForCake(tokens);
        uint256 newBalance = (IERC20(rewardToken).balanceOf(address(this))).sub(initialCAKEBalance);
        IERC20(rewardToken).transfer(_marketingWalletAddress, newBalance);
        AmountMarketingFee = AmountMarketingFee - tokens;
    }

    function swapAndLiquify(uint256 tokens) private {
       // split the contract balance into halves
        uint256 half = tokens.div(2);
        uint256 otherHalf = tokens.sub(half);

        uint256 initialBalance = address(this).balance;

        // swap tokens for ETH
        swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered

        // how much ETH did we just swap into?
        uint256 newBalance = address(this).balance.sub(initialBalance);

        // add liquidity to uniswap
        addLiquidity(otherHalf, newBalance);
        AmountLiquidityFee = AmountLiquidityFee - tokens;
        emit SwapAndLiquify(half, newBalance, otherHalf);
    }

    function swapTokensForEth(uint256 tokenAmount) private {
        // generate the uniswap pair path of token -> wpls
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WPLS();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            address(this),
            block.timestamp
        );

    }

    function swapTokensForCake(uint256 tokenAmount) private {
        address[] memory path = new address[](3);
        path[0] = address(this);
        if(rewardToken == uniswapV2Router.WPLS()){
            path[1] = rewardToken;
        }else{
            path[1] = uniswapV2Router.WPLS();
            path[2] = rewardToken;
        }
        _approve(address(this), address(uniswapV2Router), tokenAmount);
        // make the swap
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(uniswapV2Router), tokenAmount);
        // add the liquidity
        uniswapV2Router.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            _node,
            block.timestamp
        );

    }

    function swapAndSendDividends(uint256 tokens) private{
        swapTokensForCake(tokens);
        AmountTokenRewardsFee = AmountTokenRewardsFee - tokens;
        uint256 dividends = IERC20(rewardToken).balanceOf(address(this));
        bool success = IERC20(rewardToken).transfer(address(dividendTracker), dividends);
        if (success) {
            dividendTracker.distributeCAKEDividends(dividends);
            emit SendDividends(tokens, dividends);
        }
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExcludeFromFees","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"bool","name":"isExcluded","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ExcludeMultipleAccountsFromFees","inputs":[{"type":"address[]","name":"accounts","internalType":"address[]","indexed":false},{"type":"bool","name":"isExcluded","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"GasForProcessingUpdated","inputs":[{"type":"uint256","name":"newValue","internalType":"uint256","indexed":true},{"type":"uint256","name":"oldValue","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"LiquidityWalletUpdated","inputs":[{"type":"address","name":"newLiquidityWallet","internalType":"address","indexed":true},{"type":"address","name":"oldLiquidityWallet","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ProcessedDividendTracker","inputs":[{"type":"uint256","name":"iterations","internalType":"uint256","indexed":false},{"type":"uint256","name":"claims","internalType":"uint256","indexed":false},{"type":"uint256","name":"lastProcessedIndex","internalType":"uint256","indexed":false},{"type":"bool","name":"automatic","internalType":"bool","indexed":true},{"type":"uint256","name":"gas","internalType":"uint256","indexed":false},{"type":"address","name":"processor","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SendDividends","inputs":[{"type":"uint256","name":"tokensSwapped","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SetAutomatedMarketMakerPair","inputs":[{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"bool","name":"value","internalType":"bool","indexed":true}],"anonymous":false},{"type":"event","name":"SwapAndLiquify","inputs":[{"type":"uint256","name":"tokensSwapped","internalType":"uint256","indexed":false},{"type":"uint256","name":"ethReceived","internalType":"uint256","indexed":false},{"type":"uint256","name":"tokensIntoLiqudity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"UpdateDividendTracker","inputs":[{"type":"address","name":"newAddress","internalType":"address","indexed":true},{"type":"address","name":"oldAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"UpdateUniswapV2Router","inputs":[{"type":"address","name":"newAddress","internalType":"address","indexed":true},{"type":"address","name":"oldAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"AmountLiquidityFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"AmountMarketingFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"AmountTokenRewardsFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"EnemyAddress","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"value","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_isEnemy","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_marketingWalletAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"automatedMarketMakerPairs","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyDeadFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyLiquidityFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyMarketingFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyTokenRewardsFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claim","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"deadWallet","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dividendTokenBalanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract TokenDividendTracker"}],"name":"dividendTracker","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromDividends","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromFees","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"bool","name":"excluded","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeMultipleAccountsFromFees","inputs":[{"type":"address[]","name":"accounts","internalType":"address[]"},{"type":"bool","name":"excluded","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"gasForProcessing","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"int256","name":"","internalType":"int256"},{"type":"int256","name":"","internalType":"int256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAccountDividendsInfo","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"int256","name":"","internalType":"int256"},{"type":"int256","name":"","internalType":"int256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAccountDividendsInfoAtIndex","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getClaimWait","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLastProcessedIndex","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNumberOfDividendTokenHolders","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalDividendsDistributed","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromDividends","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromFees","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isTradeOpen","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxBuyLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxWalletLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"openOrCloseTrade","inputs":[{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"processDividendTracker","inputs":[{"type":"uint256","name":"gas","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rewardToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellDeadFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellLiquidityFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellMarketingFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellTokenRewardsFee","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAutomatedMarketMakerPair","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"value","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBuyTaxes","inputs":[{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"rewardsFee","internalType":"uint256"},{"type":"uint256","name":"marketingFee","internalType":"uint256"},{"type":"uint256","name":"deadFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDeadWallet","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMarketingWallet","inputs":[{"type":"address","name":"wallet","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxLimits","inputs":[{"type":"uint256","name":"_maxBuy","internalType":"uint256"},{"type":"uint256","name":"_maxWallet","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSellTaxes","inputs":[{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"rewardsFee","internalType":"uint256"},{"type":"uint256","name":"marketingFee","internalType":"uint256"},{"type":"uint256","name":"deadFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSwapTokensAtAmount","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapManual","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"swapTokensAtAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"uniswapV2Pair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router02"}],"name":"uniswapV2Router","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateClaimWait","inputs":[{"type":"uint256","name":"claimWait","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateGasForProcessing","inputs":[{"type":"uint256","name":"newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateMinimumTokenBalanceForDividends","inputs":[{"type":"uint256","name":"val","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateUniswapV2Router","inputs":[{"type":"address","name":"newAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawableDividendOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x60806040526018805460ff19166001179055601a80546001600160a01b03191661dead1790553480156200003257600080fd5b50604080518082018252600e81526d4c6f75697320546865204475636b60901b6020808301918252835180850190945260048452634455434b60e01b908401528151919291620000859160039162000b40565b5080516200009b90600490602084019062000b40565b505050620000b8620000b2620006ff60201b60201c565b62000703565b6009805461dead6001600160a01b031990911617905560188054610100600160a81b03191662dead001790556000600b819055600d819055600f8190556011819055600c819055600e819055601081905560128190556019906200014490620001308181818062000755602090811b62001f2e17901c565b6200075560201b62001f2e1790919060201c565b11156200016e5760405162461bcd60e51b8152600401620001659062000cc5565b60405180910390fd5b60196200019c6012546200013060105462000130600e54600c546200075560201b62001f2e1790919060201c565b1115620001bd5760405162461bcd60e51b8152600401620001659062000e3d565b6d31412717f0d963b3e3a873b8000062000201620f4240620001ed83600262000792602090811b62001f6417901c565b620007e060201b62001fa91790919060201c565b600a556cfc2edca38973de47281b2000006016819055601755620493e0601c55601980546001600160a01b031916331790556009546040516001600160a01b039190911690683635c9adc5dea00000906200025c9062000bcf565b6200026992919062000c4b565b604051809103906000f08015801562000286573d6000803e3d6000fd5b50600860006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060007398bf93ebf5c380c0e6ae8e192a7e2ae08edacc0290506000816001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b1580156200030257600080fd5b505afa15801562000317573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200033d919062000bf4565b6001600160a01b031663c9c6539630846001600160a01b031663ef8ef56f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200038657600080fd5b505afa1580156200039b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003c1919062000bf4565b6040518363ffffffff1660e01b8152600401620003e092919062000c31565b602060405180830381600087803b158015620003fb57600080fd5b505af115801562000410573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000436919062000bf4565b600680546001600160a01b038086166001600160a01b03199283161790925560078054928416929091169190911790559050620004758160016200082a565b60085460405163031e79db60e41b81526001600160a01b03909116906331e79db090620004a790839060040162000c1d565b600060405180830381600087803b158015620004c257600080fd5b505af1158015620004d7573d6000803e3d6000fd5b505060085460405163031e79db60e41b81526001600160a01b0390911692506331e79db091506200050d90309060040162000c1d565b600060405180830381600087803b1580156200052857600080fd5b505af11580156200053d573d6000803e3d6000fd5b50506008546001600160a01b031691506331e79db090506200055e6200093d565b6040518263ffffffff1660e01b81526004016200057c919062000c1d565b600060405180830381600087803b1580156200059757600080fd5b505af1158015620005ac573d6000803e3d6000fd5b5050600854601a5460405163031e79db60e41b81526001600160a01b0392831694506331e79db09350620005e7929091169060040162000c1d565b600060405180830381600087803b1580156200060257600080fd5b505af115801562000617573d6000803e3d6000fd5b505060085460405163031e79db60e41b81526001600160a01b0390911692506331e79db091506200064d90859060040162000c1d565b600060405180830381600087803b1580156200066857600080fd5b505af11580156200067d573d6000803e3d6000fd5b505050506200069d620006956200093d60201b60201c565b60016200094c565b601854620006bb9061010090046001600160a01b031660016200094c565b620006c83060016200094c565b601954620006e1906001600160a01b031660016200094c565b620006f6620006ef6200093d565b8462000a1c565b50505062000f2e565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008062000764838562000e7d565b905083811015620007895760405162461bcd60e51b8152600401620001659062000d59565b90505b92915050565b600082620007a3575060006200078c565b6000620007b1838562000eb9565b905082620007c0858362000e98565b14620007895760405162461bcd60e51b8152600401620001659062000dc7565b60006200078983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525062000aff60201b60201c565b6001600160a01b0382166000908152601e602052604090205460ff16151581151514156200086c5760405162461bcd60e51b8152600401620001659062000cfc565b6001600160a01b0382166000908152601e60205260409020805460ff19168215801591909117909155620009015760085460405163031e79db60e41b81526001600160a01b03909116906331e79db090620008cc90859060040162000c1d565b600060405180830381600087803b158015620008e757600080fd5b505af1158015620008fc573d6000803e3d6000fd5b505050505b604051811515906001600160a01b038416907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab90600090a35050565b6005546001600160a01b031690565b62000956620006ff565b6001600160a01b0316620009696200093d565b6001600160a01b031614620009925760405162461bcd60e51b8152600401620001659062000e08565b6001600160a01b0382166000908152601d602052604090205460ff1615158115151462000a18576001600160a01b0382166000818152601d602052604090819020805460ff1916841515179055517f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df79062000a0f90849062000c64565b60405180910390a25b5050565b6001600160a01b03821662000a455760405162461bcd60e51b8152600401620001659062000d90565b62000a536000838362000b3b565b62000a6f816002546200075560201b62001f2e1790919060201c565b6002556001600160a01b0382166000908152602081815260409091205462000aa291839062001f2e62000755821b17901c565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9062000af390859062000e74565b60405180910390a35050565b6000818362000b235760405162461bcd60e51b815260040162000165919062000c6f565b50600062000b32848662000e98565b95945050505050565b505050565b82805462000b4e9062000edb565b90600052602060002090601f01602090048101928262000b72576000855562000bbd565b82601f1062000b8d57805160ff191683800117855562000bbd565b8280016001018555821562000bbd579182015b8281111562000bbd57825182559160200191906001019062000ba0565b5062000bcb92915062000bdd565b5090565b6124888062004e8583390190565b5b8082111562000bcb576000815560010162000bde565b60006020828403121562000c06578081fd5b81516001600160a01b038116811462000789578182fd5b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602080835283518082850152825b8181101562000c9d5785810183015185820160400152820162000c7f565b8181111562000caf5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526019908201527f546f74616c2062757920666565206973206f7665722032352500000000000000604082015260600190565b60208082526038908201527f4175746f6d61746564206d61726b6574206d616b65722070616972206973206160408201527f6c72656164792073657420746f20746861742076616c75650000000000000000606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f45524332303a206361737420746f20746865207a65726f206164647265737300604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601a908201527f546f74616c2073656c6c20666565206973206f76657220323525000000000000604082015260600190565b90815260200190565b6000821982111562000e935762000e9362000f18565b500190565b60008262000eb457634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161562000ed65762000ed662000f18565b500290565b60028104600182168062000ef057607f821691505b6020821081141562000f1257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b613f478062000f3e6000396000f3fe6080604052600436106103e85760003560e01c8063871c128d11610208578063c492f04611610118578063e98030c7116100ab578063f480fec21161007a578063f480fec214610abf578063f637434214610adf578063f664da5514610af4578063f7c618c114610b14578063f832679514610b29576103ef565b8063e98030c714610a4a578063f11a24d314610a6a578063f27fd25414610a7f578063f2fde38b14610a9f576103ef565b8063dd62ed3e116100e7578063dd62ed3e146109e0578063e2f4560514610a00578063e4bf1bed14610a15578063e7841ec014610a35576103ef565b8063c492f04614610976578063c705c56914610996578063cfe0e619146109b6578063d2a8b440146109cb576103ef565b8063a26579ad1161019b578063aa797dbc1161016a578063aa797dbc146108c2578063ad56c13c146108e2578063afa4f3b214610916578063b62496f514610936578063c024666814610956576103ef565b8063a26579ad1461084d578063a457c2d714610862578063a8b9d24014610882578063a9059cbb146108a2576103ef565b806395d89b41116101d757806395d89b41146107e35780639a7a23d6146107f85780639c1b8af5146108185780639d913ef51461082d576103ef565b8063871c128d146107845780638da5cb5b146107a45780638de743b3146107b957806392136913146107ce576103ef565b806349bd5a5e1161030357806366a88d961161029657806370a082311161026557806370a0823114610705578063715018a6146107255780637bce5a041461073a57806385141a771461074f5780638692361114610764576103ef565b806366a88d961461069b5780636843cd84146106b05780636aa5b37f146106d0578063700bb191146106e5576103ef565b806360901444116102d2578063609014441461063157806361a60d571461064657806364b0f6531461066657806365b8dbc01461067b576103ef565b806349bd5a5e146105c75780634e71d92d146105dc5780634fbee193146105f15780635d098b3814610611576103ef565b806324942a041161037b57806331e79db01161034a57806331e79db01461055d5780633926876d1461057d57806339509351146105925780634144d9e4146105b2576103ef565b806324942a04146104fc5780632c1f52161461051157806330bb4cff14610526578063313ce5671461053b576103ef565b80630dcb2e89116103b75780630dcb2e89146104835780631694505e146104a557806318160ddd146104c757806323b872dd146104dc576103ef565b806302df64d6146103f457806306fdde031461041f57806308b2a12c14610441578063095ea7b314610456576103ef565b366103ef57005b600080fd5b34801561040057600080fd5b50610409610b3e565b6040516104169190613cdb565b60405180910390f35b34801561042b57600080fd5b50610434610b44565b6040516104169190613773565b34801561044d57600080fd5b50610409610bd6565b34801561046257600080fd5b5061047661047136600461349f565b610bdc565b6040516104169190613768565b34801561048f57600080fd5b506104a361049e366004613582565b610bfa565b005b3480156104b157600080fd5b506104ba610ca7565b6040516104169190613631565b3480156104d357600080fd5b50610409610cb6565b3480156104e857600080fd5b506104766104f73660046133c9565b610cbc565b34801561050857600080fd5b50610409610d43565b34801561051d57600080fd5b506104ba610d49565b34801561053257600080fd5b50610409610d58565b34801561054757600080fd5b50610550610dda565b6040516104169190613d93565b34801561056957600080fd5b506104a3610578366004613359565b610ddf565b34801561058957600080fd5b50610409610e4e565b34801561059e57600080fd5b506104766105ad36600461349f565b610e54565b3480156105be57600080fd5b506104ba610ea2565b3480156105d357600080fd5b506104ba610eb6565b3480156105e857600080fd5b506104a3610ec5565b3480156105fd57600080fd5b5061047661060c366004613359565b610f4d565b34801561061d57600080fd5b506104a361062c366004613359565b610f6b565b34801561063d57600080fd5b50610476610fd2565b34801561065257600080fd5b506104a3610661366004613359565b610fdb565b34801561067257600080fd5b5061040961103c565b34801561068757600080fd5b506104a3610696366004613359565b611081565b3480156106a757600080fd5b506104096112e7565b3480156106bc57600080fd5b506104096106cb366004613359565b6112ed565b3480156106dc57600080fd5b5061040961136e565b3480156106f157600080fd5b506104a3610700366004613582565b611374565b34801561071157600080fd5b50610409610720366004613359565b611455565b34801561073157600080fd5b506104a3611470565b34801561074657600080fd5b506104096114bb565b34801561075b57600080fd5b506104ba6114c1565b34801561077057600080fd5b506104a361077f366004613409565b6114d0565b34801561079057600080fd5b506104a361079f366004613582565b61153a565b3480156107b057600080fd5b506104ba611600565b3480156107c557600080fd5b5061040961160f565b3480156107da57600080fd5b50610409611615565b3480156107ef57600080fd5b5061043461161b565b34801561080457600080fd5b506104a3610813366004613409565b61162a565b34801561082457600080fd5b506104096116a5565b34801561083957600080fd5b506104a36108483660046135b2565b6116ab565b34801561085957600080fd5b506104096116f5565b34801561086e57600080fd5b5061047661087d36600461349f565b61173a565b34801561088e57600080fd5b5061040961089d366004613359565b6117a2565b3480156108ae57600080fd5b506104766108bd36600461349f565b6117d3565b3480156108ce57600080fd5b506104766108dd366004613359565b6117e7565b3480156108ee57600080fd5b506109026108fd366004613359565b6117fc565b604051610416989796959493929190613693565b34801561092257600080fd5b506104a3610931366004613582565b6118a9565b34801561094257600080fd5b50610476610951366004613359565b6118ed565b34801561096257600080fd5b506104a3610971366004613409565b611902565b34801561098257600080fd5b506104a36109913660046134ca565b6119c7565b3480156109a257600080fd5b506104766109b1366004613359565b611ac6565b3480156109c257600080fd5b50610409611b47565b3480156109d757600080fd5b506104a3611b4d565b3480156109ec57600080fd5b506104096109fb366004613391565b611c15565b348015610a0c57600080fd5b50610409611c40565b348015610a2157600080fd5b506104a3610a30366004613600565b611c46565b348015610a4157600080fd5b50610409611cd2565b348015610a5657600080fd5b506104a3610a65366004613582565b611d17565b348015610a7657600080fd5b50610409611d86565b348015610a8b57600080fd5b50610902610a9a366004613582565b611d8c565b348015610aab57600080fd5b506104a3610aba366004613359565b611dcd565b348015610acb57600080fd5b506104a3610ada366004613600565b611e3b565b348015610aeb57600080fd5b50610409611ec1565b348015610b0057600080fd5b506104a3610b0f36600461354a565b611ec7565b348015610b2057600080fd5b506104ba611f19565b348015610b3557600080fd5b50610409611f28565b600b5481565b606060038054610b5390613e0f565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7f90613e0f565b8015610bcc5780601f10610ba157610100808354040283529160200191610bcc565b820191906000526020600020905b815481529060010190602001808311610baf57829003601f168201915b5050505050905090565b600c5481565b6000610bf0610be9611feb565b8484611fef565b5060015b92915050565b610c02611feb565b6001600160a01b0316610c13611600565b6001600160a01b031614610c425760405162461bcd60e51b8152600401610c3990613b67565b60405180910390fd5b600854604051635ebf4db960e01b81526001600160a01b0390911690635ebf4db990610c72908490600401613cdb565b600060405180830381600087803b158015610c8c57600080fd5b505af1158015610ca0573d6000803e3d6000fd5b5050505050565b6006546001600160a01b031681565b60025490565b6000610cc98484846120a3565b610d3984610cd5611feb565b610d3485604051806060016040528060288152602001613ec5602891396001600160a01b038a16600090815260016020526040812090610d13611feb565b6001600160a01b03168152602081019190915260400160002054919061276a565b611fef565b5060019392505050565b60125481565b6008546001600160a01b031681565b600854604080516342d359d760e11b815290516000926001600160a01b0316916385a6b3ae916004808301926020929190829003018186803b158015610d9d57600080fd5b505afa158015610db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd5919061359a565b905090565b601290565b610de7611feb565b6001600160a01b0316610df8611600565b6001600160a01b031614610e1e5760405162461bcd60e51b8152600401610c3990613b67565b60085460405163031e79db60e41b81526001600160a01b03909116906331e79db090610c72908490600401613631565b60145481565b6000610bf0610e61611feb565b84610d348560016000610e72611feb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611f2e565b60185461010090046001600160a01b031681565b6007546001600160a01b031681565b60085460405163bc4c4b3760e01b81526001600160a01b039091169063bc4c4b3790610ef8903390600090600401613645565b602060405180830381600087803b158015610f1257600080fd5b505af1158015610f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4a9190613566565b50565b6001600160a01b03166000908152601d602052604090205460ff1690565b610f73611feb565b6001600160a01b0316610f84611600565b6001600160a01b031614610faa5760405162461bcd60e51b8152600401610c3990613b67565b601880546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60185460ff1681565b610fe3611feb565b6001600160a01b0316610ff4611600565b6001600160a01b03161461101a5760405162461bcd60e51b8152600401610c3990613b67565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b600854604080516304ddf6ef60e11b815290516000926001600160a01b0316916309bbedde916004808301926020929190829003018186803b158015610d9d57600080fd5b611089611feb565b6001600160a01b031661109a611600565b6001600160a01b0316146110c05760405162461bcd60e51b8152600401610c3990613b67565b6006546001600160a01b03828116911614156110ee5760405162461bcd60e51b8152600401610c3990613a67565b6006546040516001600160a01b03918216918316907f8fc842bbd331dfa973645f4ed48b11683d501ebf1352708d77a5da2ab49a576e90600090a3600680546001600160a01b0319166001600160a01b0383811691909117918290556040805163c45a015560e01b815290516000939092169163c45a015591600480820192602092909190829003018186803b15801561118757600080fd5b505afa15801561119b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111bf9190613375565b6001600160a01b031663c9c6539630600660009054906101000a90046001600160a01b03166001600160a01b031663ef8ef56f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561121c57600080fd5b505afa158015611230573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112549190613375565b6040518363ffffffff1660e01b8152600401611271929190613679565b602060405180830381600087803b15801561128b57600080fd5b505af115801561129f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c39190613375565b600780546001600160a01b0319166001600160a01b03929092169190911790555050565b60165481565b6008546040516370a0823160e01b81526000916001600160a01b0316906370a082319061131e908590600401613631565b60206040518083038186803b15801561133657600080fd5b505afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf4919061359a565b60175481565b6008546040516001624d3b8760e01b03198152600091829182916001600160a01b03169063ffb2c479906113ac908790600401613cdb565b606060405180830381600087803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe91906135d3565b925092509250326001600160a01b0316600015157fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a98858585896040516114479493929190613d78565b60405180910390a350505050565b6001600160a01b031660009081526020819052604090205490565b611478611feb565b6001600160a01b0316611489611600565b6001600160a01b0316146114af5760405162461bcd60e51b8152600401610c3990613b67565b6114b960006127a4565b565b600f5481565b601a546001600160a01b031681565b6114d8611feb565b6001600160a01b03166114e9611600565b6001600160a01b03161461150f5760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b03919091166000908152601b60205260409020805460ff1916911515919091179055565b611542611feb565b6001600160a01b0316611553611600565b6001600160a01b0316146115795760405162461bcd60e51b8152600401610c3990613b67565b62030d40811015801561158f57506207a1208111155b6115ab5760405162461bcd60e51b8152600401610c39906138ab565b601c548114156115cd5760405162461bcd60e51b8152600401610c39906139e4565b601c5460405182907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3601c55565b6005546001600160a01b031690565b60115481565b60105481565b606060048054610b5390613e0f565b611632611feb565b6001600160a01b0316611643611600565b6001600160a01b0316146116695760405162461bcd60e51b8152600401610c3990613b67565b6007546001600160a01b03838116911614156116975760405162461bcd60e51b8152600401610c39906137c6565b6116a182826127f6565b5050565b601c5481565b6116b3611feb565b6001600160a01b03166116c4611600565b6001600160a01b0316146116ea5760405162461bcd60e51b8152600401610c3990613b67565b601791909155601655565b60085460408051631bc9e27b60e21b815290516000926001600160a01b031691636f2789ec916004808301926020929190829003018186803b158015610d9d57600080fd5b6000610bf0611747611feb565b84610d3485604051806060016040528060258152602001613eed6025913960016000611771611feb565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919061276a565b6008546040516302a2e74960e61b81526000916001600160a01b03169063a8b9d2409061131e908590600401613631565b6000610bf06117e0611feb565b84846120a3565b601b6020526000908152604090205460ff1681565b60085460405163fbcbc0f160e01b815260009182918291829182918291829182916001600160a01b039091169063fbcbc0f19061183d908c90600401613631565b6101006040518083038186803b15801561185657600080fd5b505afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e9190613436565b97509750975097509750975097509750919395975091939597565b6118b1611feb565b6001600160a01b03166118c2611600565b6001600160a01b0316146118e85760405162461bcd60e51b8152600401610c3990613b67565b600a55565b601e6020526000908152604090205460ff1681565b61190a611feb565b6001600160a01b031661191b611600565b6001600160a01b0316146119415760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b0382166000908152601d602052604090205460ff161515811515146116a1576001600160a01b0382166000818152601d602052604090819020805460ff1916841515179055517f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7906119bb908490613768565b60405180910390a25050565b6119cf611feb565b6001600160a01b03166119e0611600565b6001600160a01b031614611a065760405162461bcd60e51b8152600401610c3990613b67565b60005b82811015611a855781601d6000868685818110611a3657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611a4b9190613359565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580611a7d81613e4a565b915050611a09565b507f7fdaf542373fa84f4ee8d662c642f44e4c2276a217d7d29e548b6eb29a233b35838383604051611ab99392919061370f565b60405180910390a1505050565b60085460405163c705c56960e01b81526000916001600160a01b03169063c705c56990611af7908590600401613631565b60206040518083038186803b158015611b0f57600080fd5b505afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613566565b60155481565b611b55611feb565b6001600160a01b0316611b66611600565b6001600160a01b031614611b8c5760405162461bcd60e51b8152600401610c3990613b67565b6000611b9730611455565b905060008111611bb95760405162461bcd60e51b8152600401610c3990613afa565b6007805460ff60a01b1916600160a01b17905560135415611bdf57611bdf601354612901565b60145415611bf257611bf2601454612994565b60155415611c0557611c05601554612b58565b506007805460ff60a01b19169055565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600a5481565b611c4e611feb565b6001600160a01b0316611c5f611600565b6001600160a01b031614611c855760405162461bcd60e51b8152600401610c3990613b67565b6019611c9d82611c978581888a611f2e565b90611f2e565b1115611cbb5760405162461bcd60e51b8152600401610c3990613874565b600b92909255600d92909255600f91909155601155565b6008546040805163039e107b60e61b815290516000926001600160a01b03169163e7841ec0916004808301926020929190829003018186803b158015610d9d57600080fd5b611d1f611feb565b6001600160a01b0316611d30611600565b6001600160a01b031614611d565760405162461bcd60e51b8152600401610c3990613b67565b60085460405163e98030c760e01b81526001600160a01b039091169063e98030c790610c72908490600401613cdb565b600d5481565b600854604051635183d6fd60e01b815260009182918291829182918291829182916001600160a01b0390911690635183d6fd9061183d908c90600401613cdb565b611dd5611feb565b6001600160a01b0316611de6611600565b6001600160a01b031614611e0c5760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b038116611e325760405162461bcd60e51b8152600401610c39906138ff565b610f4a816127a4565b611e43611feb565b6001600160a01b0316611e54611600565b6001600160a01b031614611e7a5760405162461bcd60e51b8152600401610c3990613b67565b6019611e8c82611c978581888a611f2e565b1115611eaa5760405162461bcd60e51b8152600401610c3990613ca4565b600c92909255600e92909255601091909155601255565b600e5481565b611ecf611feb565b6001600160a01b0316611ee0611600565b6001600160a01b031614611f065760405162461bcd60e51b8152600401610c3990613b67565b6018805460ff1916911515919091179055565b6009546001600160a01b031681565b60135481565b600080611f3b8385613da1565b905083811015611f5d5760405162461bcd60e51b8152600401610c3990613a30565b9392505050565b600082611f7357506000610bf4565b6000611f7f8385613dd9565b905082611f8c8583613db9565b14611f5d5760405162461bcd60e51b8152600401610c3990613b26565b6000611f5d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612d17565b3390565b6001600160a01b0383166120155760405162461bcd60e51b8152600401610c3990613c29565b6001600160a01b03821661203b5760405162461bcd60e51b8152600401610c3990613945565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612096908590613cdb565b60405180910390a3505050565b6001600160a01b0383166120c95760405162461bcd60e51b8152600401610c3990613be4565b6001600160a01b0382166120ef5760405162461bcd60e51b8152600401610c3990613831565b6001600160a01b0383166000908152601b602052604090205460ff1615801561213157506001600160a01b0382166000908152601b602052604090205460ff16155b61214d5760405162461bcd60e51b8152600401610c3990613ad3565b806121635761215e83836000612d45565b612765565b6001600160a01b0383166000908152601d602052604090205460ff161580156121a557506001600160a01b0382166000908152601d602052604090205460ff16155b1561224e5760185460ff166121cc5760405162461bcd60e51b8152600401610c3990613aaa565b6007546001600160a01b0384811691161415612204576017548111156122045760405162461bcd60e51b8152600401610c3990613b9c565b6007546001600160a01b0383811691161461224e576016548161222684611455565b6122309190613da1565b111561224e5760405162461bcd60e51b8152600401610c3990613c6d565b600061225930611455565b600a549091508110801590819061227a5750600754600160a01b900460ff16155b801561229f57506001600160a01b0385166000908152601e602052604090205460ff16155b80156122c457506122ae611600565b6001600160a01b0316856001600160a01b031614155b80156122e957506122d3611600565b6001600160a01b0316846001600160a01b031614155b15612348576007805460ff60a01b1916600160a01b1790556015541561231457612314601554612b58565b6013541561232757612327601354612901565b6014541561233a5761233a601454612994565b6007805460ff60a01b191690555b6007546001600160a01b0386166000908152601d602052604090205460ff600160a01b90920482161591168061239657506001600160a01b0385166000908152601d602052604090205460ff165b1561239f575060005b80156125ab576001600160a01b0386166000908152601e6020526040812054819081908190819060ff161561248d576123ee60646123e8600d548c611f6490919063ffffffff16565b90611fa9565b935083601360008282546124029190613da1565b9091555050600b5461241c906064906123e8908c90611f64565b925082601460008282546124309190613da1565b9091555050600f5461244a906064906123e8908c90611f64565b9150816015600082825461245e9190613da1565b9091555050601154612478906064906123e8908c90611f64565b905061248a81611c9784818888611f2e565b94505b6001600160a01b038a166000908152601e602052604090205460ff1615612567576124c860646123e8600e548c611f6490919063ffffffff16565b935083601360008282546124dc9190613da1565b9091555050600c546124f6906064906123e8908c90611f64565b9250826014600082825461250a9190613da1565b9091555050601054612524906064906123e8908c90611f64565b915081601560008282546125389190613da1565b9091555050601254612552906064906123e8908c90611f64565b905061256481611c9784818888611f2e565b94505b6125718986612e5a565b9850801561259157601a54612591908c906001600160a01b031683612d45565b6125a58b306125a08885612e5a565b612d45565b50505050505b6125b6868686612d45565b6008546001600160a01b031663e30443bc876125d181611455565b6040518363ffffffff1660e01b81526004016125ee929190613660565b600060405180830381600087803b15801561260857600080fd5b505af1925050508015612619575060015b506008546001600160a01b031663e30443bc8661263581611455565b6040518363ffffffff1660e01b8152600401612652929190613660565b600060405180830381600087803b15801561266c57600080fd5b505af192505050801561267d575060015b50600754600160a01b900460ff1661276157601c546008546040516001624d3b8760e01b031981526001600160a01b039091169063ffb2c479906126c5908490600401613cdb565b606060405180830381600087803b1580156126df57600080fd5b505af192505050801561270f575060408051601f3d908101601f1916820190925261270c918101906135d3565b60015b6127185761275f565b60405132906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9890612753908790879087908b90613d78565b60405180910390a35050505b505b5050505b505050565b6000818484111561278e5760405162461bcd60e51b8152600401610c399190613773565b50600061279b8486613df8565b95945050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166000908152601e602052604090205460ff16151581151514156128355760405162461bcd60e51b8152600401610c3990613987565b6001600160a01b0382166000908152601e60205260409020805460ff191682158015919091179091556128c55760085460405163031e79db60e41b81526001600160a01b03909116906331e79db090612892908590600401613631565b600060405180830381600087803b1580156128ac57600080fd5b505af11580156128c0573d6000803e3d6000fd5b505050505b604051811515906001600160a01b038416907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab90600090a35050565b600061290e826002611fa9565b9050600061291c8383612e5a565b90504761292883612e9c565b60006129344783612e5a565b90506129408382613019565b8460135461294e9190613df8565b6013556040517f17bbfb9a6069321b6ded73bd96327c9e6b7212a5cd51ff219cd61370acafb5619061298590869084908790613d62565b60405180910390a15050505050565b61299d816130c3565b806014546129ab9190613df8565b6014556009546040516370a0823160e01b81526000916001600160a01b0316906370a08231906129df903090600401613631565b60206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f919061359a565b60095460085460405163a9059cbb60e01b81529293506000926001600160a01b039283169263a9059cbb92612a6b929116908690600401613660565b602060405180830381600087803b158015612a8557600080fd5b505af1158015612a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abd9190613566565b905080156127655760085460405163ba72a95560e01b81526001600160a01b039091169063ba72a95590612af5908590600401613cdb565b600060405180830381600087803b158015612b0f57600080fd5b505af1158015612b23573d6000803e3d6000fd5b505050507f80195cc573b02cc48460cbca6e6e4cc85ddb91959d946e1c3025ea3d87942dc38383604051611ab9929190613d54565b6009546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612b89903090600401613631565b60206040518083038186803b158015612ba157600080fd5b505afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd9919061359a565b9050612be4826130c3565b6009546040516370a0823160e01b8152600091612c719184916001600160a01b0316906370a0823190612c1b903090600401613631565b60206040518083038186803b158015612c3357600080fd5b505afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b919061359a565b90612e5a565b60095460185460405163a9059cbb60e01b81529293506001600160a01b039182169263a9059cbb92612cae92610100900416908590600401613660565b602060405180830381600087803b158015612cc857600080fd5b505af1158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d009190613566565b5082601554612d0f9190613df8565b601555505050565b60008183612d385760405162461bcd60e51b8152600401610c399190613773565b50600061279b8486613db9565b6001600160a01b038316612d6b5760405162461bcd60e51b8152600401610c3990613be4565b6001600160a01b038216612d915760405162461bcd60e51b8152600401610c3990613831565b612d9c838383612765565b612dd981604051806060016040528060268152602001613e9f602691396001600160a01b038616600090815260208190526040902054919061276a565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612e089082611f2e565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612096908590613cdb565b6000611f5d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061276a565b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612edf57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092018101919091526006546040805163ef8ef56f60e01b81529051919093169263ef8ef56f926004808301939192829003018186803b158015612f3357600080fd5b505afa158015612f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6b9190613375565b81600181518110612f8c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600654612fb29130911684611fef565b60065460405163791ac94760e01b81526001600160a01b039091169063791ac94790612feb908590600090869030904290600401613ce4565b600060405180830381600087803b15801561300557600080fd5b505af1158015612761573d6000803e3d6000fd5b6006546130319030906001600160a01b031684611fef565b60065460195460405163f305d71960e01b81526001600160a01b039283169263f305d71992859261307192309289926000928392169042906004016136d4565b6060604051808303818588803b15801561308a57600080fd5b505af115801561309e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ca091906135d3565b6040805160038082526080820190925260009160208201606080368337019050509050308160008151811061310857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092018101919091526006546040805163ef8ef56f60e01b81529051919093169263ef8ef56f926004808301939192829003018186803b15801561315c57600080fd5b505afa158015613170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131949190613375565b6009546001600160a01b03908116911614156132015760095481516001600160a01b0390911690829060019081106131dc57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050613308565b600660009054906101000a90046001600160a01b03166001600160a01b031663ef8ef56f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561324f57600080fd5b505afa158015613263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132879190613375565b816001815181106132a857634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526009548251911690829060029081106132e757634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250505b6006546133209030906001600160a01b031684611fef565b600654604051635c11d79560e01b81526001600160a01b0390911690635c11d79590612feb908590600090869030904290600401613ce4565b60006020828403121561336a578081fd5b8135611f5d81613e7b565b600060208284031215613386578081fd5b8151611f5d81613e7b565b600080604083850312156133a3578081fd5b82356133ae81613e7b565b915060208301356133be81613e7b565b809150509250929050565b6000806000606084860312156133dd578081fd5b83356133e881613e7b565b925060208401356133f881613e7b565b929592945050506040919091013590565b6000806040838503121561341b578182fd5b823561342681613e7b565b915060208301356133be81613e90565b600080600080600080600080610100898b031215613452578384fd5b885161345d81613e7b565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b600080604083850312156134b1578182fd5b82356134bc81613e7b565b946020939093013593505050565b6000806000604084860312156134de578283fd5b833567ffffffffffffffff808211156134f5578485fd5b818601915086601f830112613508578485fd5b813581811115613516578586fd5b8760208083028501011115613529578586fd5b6020928301955093505084013561353f81613e90565b809150509250925092565b60006020828403121561355b578081fd5b8135611f5d81613e90565b600060208284031215613577578081fd5b8151611f5d81613e90565b600060208284031215613593578081fd5b5035919050565b6000602082840312156135ab578081fd5b5051919050565b600080604083850312156135c4578182fd5b50508035926020909101359150565b6000806000606084860312156135e7578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215613615578182fd5b5050823594602084013594506040840135936060013592509050565b6001600160a01b0391909116815260200190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03989098168852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b6040808252810183905260008460608301825b8681101561375257823561373581613e7b565b6001600160a01b0316825260209283019290910190600101613722565b5080925050508215156020830152949350505050565b901515815260200190565b6000602080835283518082850152825b8181101561379f57858101830151858201604001528201613783565b818111156137b05783604083870101525b50601f01601f1916929092016040019392505050565b60208082526045908201527f5468652050616e63616b655377617020706169722063616e6e6f74206265207260408201527f656d6f7665642066726f6d206175746f6d617465644d61726b65744d616b6572606082015264506169727360d81b608082015260a00190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526019908201527f546f74616c2062757920666565206973206f7665722032352500000000000000604082015260600190565b60208082526034908201527f476173466f7250726f63657373696e67206d757374206265206265747765656e6040820152730203230302c30303020616e64203530302c3030360641b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526038908201527f4175746f6d61746564206d61726b6574206d616b65722070616972206973206160408201527f6c72656164792073657420746f20746861742076616c75650000000000000000606082015260800190565b6020808252602c908201527f43616e6e6f742075706461746520676173466f7250726f63657373696e67207460408201526b6f2073616d652076616c756560a01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526023908201527f54686520726f7574657220616c7265616479206861732074686174206164647260408201526265737360e81b606082015260800190565b6020808252600f908201526e151c985919481a5cc818db1bdcd959608a1b604082015260600190565b6020808252600d908201526c456e656d79206164647265737360981b604082015260600190565b602080825260129082015271746f6b656e2062616c616e6365207a65726f60701b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526028908201527f5472616e7366657220616d6f756e74206578636565647320746865206d6178426040820152673abca634b6b4ba1760c11b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601b908201527f4578636565647320746865206d617857616c6c65744c696d69742e0000000000604082015260600190565b60208082526019908201527f546f74616c2073656c20666565206973206f7665722032352500000000000000604082015260600190565b90815260200190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015613d335784516001600160a01b031683529383019391830191600101613d0e565b50506001600160a01b03969096166060850152505050608001529392505050565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60ff91909116815260200190565b60008219821115613db457613db4613e65565b500190565b600082613dd457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615613df357613df3613e65565b500290565b600082821015613e0a57613e0a613e65565b500390565b600281046001821680613e2357607f821691505b60208210811415613e4457634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613e5e57613e5e613e65565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114610f4a57600080fd5b8015158114610f4a57600080fdfe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212203767ec4d8822def3e0e256de6a5ccf0158fd99aa70017a26134b59ef9f0b5b6564736f6c6343000800003360806040523480156200001157600080fd5b506040516200248838038062002488833981016040819052620000349162000200565b6040518060400160405280600f81526020016e2234bb34b232b72faa3930b1b5b2b960891b8152506040518060400160405280601081526020016f2234bb34b232b7322faa3930b1b5b2b960811b8152508382828160039080519060200190620000a09291906200015a565b508051620000b69060049060208401906200015a565b505050620000d3620000cd6200010460201b60201c565b62000108565b600680546001600160a01b0319166001600160a01b0392909216919091179055505060c86012556013555062000277565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b82805462000168906200023a565b90600052602060002090601f0160209004810192826200018c5760008555620001d7565b82601f10620001a757805160ff1916838001178555620001d7565b82800160010185558215620001d7579182015b82811115620001d7578251825591602001919060010190620001ba565b50620001e5929150620001e9565b5090565b5b80821115620001e55760008155600101620001ea565b6000806040838503121562000213578182fd5b82516001600160a01b03811681146200022a578283fd5b6020939093015192949293505050565b6002810460018216806200024f57607f821691505b602082108114156200027157634e487b7160e01b600052602260045260246000fd5b50919050565b61220180620002876000396000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c806385a6b3ae11610151578063ba72a955116100c3578063e30443bc11610087578063e30443bc14610509578063e7841ec01461051c578063e98030c714610524578063f2fde38b14610537578063fbcbc0f11461054a578063ffb2c4791461055d57610274565b8063ba72a955146104b5578063bc4c4b37146104c8578063be10b614146104db578063c705c569146104e3578063dd62ed3e146104f657610274565b8063a3395cb411610115578063a3395cb414610456578063a457c2d714610469578063a8b9d2401461047c578063a9059cbb1461048f578063aafd847a146104a2578063b1181e55146102cc57610274565b806385a6b3ae146104235780638da5cb5b1461042b57806391b89fba1461043357806395d89b411461044657806399248ea71461044e57610274565b8063313ce567116101ea578063556cafb0116101ae578063556cafb0146103d25780635ebf4db9146103e55780636a474002146103f85780636f2789ec1461040057806370a0823114610408578063715018a61461041b57610274565b8063313ce5671461035d57806331e79db01461037257806339509351146103855780634e7b827f146103985780635183d6fd146103ab57610274565b80631105e7401161023c5780631105e7401461030157806318160ddd14610314578063226cfa3d1461031c57806323b872dd1461032f57806327ce0147146103425780633009a6091461035557610274565b806306fdde03146102795780630716c61114610297578063095ea7b3146102ac57806309bbedde146102cc57806310a8c46b146102e1575b600080fd5b61028161057f565b60405161028e9190611bd2565b60405180910390f35b6102aa6102a5366004611a30565b610611565b005b6102bf6102ba366004611a84565b610771565b60405161028e9190611bbe565b6102d461078f565b60405161028e9190611bc9565b6102f46102ef366004611b38565b610795565b60405161028e9190611b50565b6102aa61030f366004611a84565b6107d8565b6102d461089a565b6102d461032a366004611a30565b6108a0565b6102bf61033d366004611adc565b6108b2565b6102d4610350366004611a30565b610939565b6102d4610992565b610365610998565b60405161028e9190611fd1565b6102aa610380366004611a30565b61099d565b6102bf610393366004611a84565b610a79565b6102bf6103a6366004611a30565b610ac7565b6103be6103b9366004611b38565b610adc565b60405161028e989796959493929190611b7d565b6102d46103e0366004611a30565b610b48565b6102aa6103f3366004611b38565b610b63565b6102aa610ba7565b6102d4610bc1565b6102d4610416366004611a30565b610bc7565b6102aa610be2565b6102d4610c2b565b6102f4610c31565b6102d4610441366004611a30565b610c40565b610281610c4b565b6102f4610c5a565b6102d4610464366004611a30565b610c69565b6102bf610477366004611a84565b610cae565b6102d461048a366004611a30565b610d16565b6102bf61049d366004611a84565b610d42565b6102d46104b0366004611a30565b610d56565b6102aa6104c3366004611b38565b610d71565b6102bf6104d6366004611a4c565b610e46565b6102d4610f06565b6102bf6104f1366004611a30565b610f0c565b6102d4610504366004611aaf565b610f2a565b6102aa610517366004611a84565b610f55565b6102d4611000565b6102aa610532366004611b38565b611006565b6102aa610545366004611a30565b6110cb565b6103be610558366004611a30565b611139565b61057061056b366004611b38565b611220565b60405161028e93929190611fbb565b60606003805461058e906120cd565b80601f01602080910402602001604051908101604052809291908181526020018280546105ba906120cd565b80156106075780601f106105dc57610100808354040283529160200191610607565b820191906000526020600020905b8154815290600101906020018083116105ea57829003601f168201915b5050505050905090565b6001600160a01b0381166000908152600e602052604090205460ff166106365761076e565b6001600160a01b0381166000908152600e60209081526040808320805460ff19169055600c8252808320839055600d909152812054600b5490919061067d906001906120b6565b90506000600b60000182815481106106a557634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b03908116808452600d90925260408084208790559087168352822091909155600b805491925082918590811061070057634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600b80548061074857634e487b7160e01b600052603160045260246000fd5b600082815260209020810160001990810180546001600160a01b03191690550190555050505b50565b600061078561077e611349565b848461134d565b5060015b92915050565b600b5490565b6000600b60000182815481106107bb57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031690505b919050565b6001600160a01b0382166000908152600e602052604090205460ff1615610819576001600160a01b0382166000908152600c60205260409020819055610896565b6001600160a01b0382166000818152600e60209081526040808320805460ff19166001908117909155600c8352818420869055600b8054600d909452918420839055820181559091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b03191690911790555b5050565b60025490565b60116020526000908152604090205481565b60006108bf848484611401565b61092f846108cb611349565b61092a8560405180606001604052806028815260200161217f602891396001600160a01b038a16600090815260016020526040812090610909611349565b6001600160a01b031681526020810191909152604001600020549190611419565b61134d565b5060019392505050565b6001600160a01b038116600090815260086020526040812054600160801b90610988906109839061097d61097861096f88610bc7565b60075490611453565b61149f565b906114af565b6114ed565b6107899190612038565b600f5481565b601290565b6109a5611349565b6001600160a01b03166109b6610c31565b6001600160a01b0316146109e55760405162461bcd60e51b81526004016109dc90611e54565b60405180910390fd5b6001600160a01b03811660009081526010602052604090205460ff1615610a0b57600080fd5b6001600160a01b0381166000908152601060205260408120805460ff19166001179055610a39908290611500565b610a4281610611565b6040516001600160a01b038216907fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b2590600090a250565b6000610785610a86611349565b8461092a8560016000610a97611349565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611559565b60106020526000908152604090205460ff1681565b600080600080600080600080610af061078f565b8910610b15575060009650600019955085945086935083925082915081905080610b3d565b6000610b208a610795565b9050610b2b81611139565b98509850985098509850985098509850505b919395975091939597565b6001600160a01b03166000908152600c602052604090205490565b610b6b611349565b6001600160a01b0316610b7c610c31565b6001600160a01b031614610ba25760405162461bcd60e51b81526004016109dc90611e54565b601355565b60405162461bcd60e51b81526004016109dc90611d90565b565b60125481565b6001600160a01b031660009081526020819052604090205490565b610bea611349565b6001600160a01b0316610bfb610c31565b6001600160a01b031614610c215760405162461bcd60e51b81526004016109dc90611e54565b610bbf6000611588565b600a5481565b6005546001600160a01b031690565b600061078982610d16565b60606004805461058e906120cd565b6006546001600160a01b031681565b6001600160a01b0381166000908152600e602052604081205460ff16610c9257506000196107d3565b506001600160a01b03166000908152600d602052604090205490565b6000610785610cbb611349565b8461092a856040518060600160405280602581526020016121a76025913960016000610ce5611349565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611419565b6001600160a01b03811660009081526009602052604081205461078990610d3c84610939565b906115da565b6000610785610d4f611349565b8484611401565b6001600160a01b031660009081526009602052604090205490565b610d79611349565b6001600160a01b0316610d8a610c31565b6001600160a01b031614610db05760405162461bcd60e51b81526004016109dc90611e54565b6000610dba61089a565b11610dc457600080fd5b801561076e57610df6610dd561089a565b610de383600160801b611453565b610ded9190612038565b60075490611559565b60075560405133907fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d7845411651190610e2b908490611bc9565b60405180910390a2600a54610e409082611559565b600a5550565b6000610e50611349565b6001600160a01b0316610e61610c31565b6001600160a01b031614610e875760405162461bcd60e51b81526004016109dc90611e54565b6000610e928461161c565b90508015610efc576001600160a01b038416600081815260116020526040908190204290555184151591907fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf09290610eea908590611bc9565b60405180910390a36001915050610789565b5060009392505050565b60135481565b6001600160a01b031660009081526010602052604090205460ff1690565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610f5d611349565b6001600160a01b0316610f6e610c31565b6001600160a01b031614610f945760405162461bcd60e51b81526004016109dc90611e54565b6001600160a01b03821660009081526010602052604090205460ff1615610fba57610896565b6013548110610fdc57610fcd8282611500565b610fd782826107d8565b610ff0565b610fe7826000611500565b610ff082610611565b610ffb826001610e46565b505050565b600f5490565b61100e611349565b6001600160a01b031661101f610c31565b6001600160a01b0316146110455760405162461bcd60e51b81526004016109dc90611e54565b610e10811015801561105a5750620151808111155b6110765760405162461bcd60e51b81526004016109dc90611c25565b6012548114156110985760405162461bcd60e51b81526004016109dc90611f54565b60125460405182907f474ea64804364a1e29a4487ddb63c3342a2dd826ccd8acf48825e680a0e6f20f90600090a3601255565b6110d3611349565b6001600160a01b03166110e4610c31565b6001600160a01b03161461110a5760405162461bcd60e51b81526004016109dc90611e54565b6001600160a01b0381166111305760405162461bcd60e51b81526004016109dc90611c9a565b61076e81611588565b80600080808080808061114b88610c69565b96506000199550600087126111ad57600f5487111561117957600f5461117290889061178e565b95506111ad565b600f54600b546000911061118e57600061119d565b600f54600b5461119d916115da565b90506111a988826114af565b9650505b6111b688610d16565b94506111c188610939565b6001600160a01b0389166000908152601160205260409020549094509250826111eb5760006111f9565b6012546111f9908490611559565b9150428211611209576000611213565b61121382426115da565b9050919395975091939597565b600b546000908190819080611240575050600f5460009250829150611342565b600f546000805a90506000805b898410801561125b57508582105b15611331578461126a81612108565b600b549096508610905061127d57600094505b6000600b60000186815481106112a357634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b031680835260119091526040909120549091506112d4906117cb565b156112f7576112e4816001610e46565b156112f757816112f381612108565b9250505b8261130181612108565b93505060005a9050808511156113285761132561131e86836115da565b8790611559565b95505b935061124d9050565b600f85905590975095509193505050505b9193909250565b3390565b6001600160a01b0383166113735760405162461bcd60e51b81526004016109dc90611f10565b6001600160a01b0382166113995760405162461bcd60e51b81526004016109dc90611ce0565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906113f4908590611bc9565b60405180910390a3505050565b60405162461bcd60e51b81526004016109dc90611e89565b6000818484111561143d5760405162461bcd60e51b81526004016109dc9190611bd2565b50600061144a84866120b6565b95945050505050565b60008261146257506000610789565b600061146e8385612058565b90508261147b8583612038565b146114985760405162461bcd60e51b81526004016109dc90611e13565b9392505050565b6000818181121561078957600080fd5b6000806114bc8385611fdf565b9050600083121580156114cf5750838112155b806114e457506000831280156114e457508381125b61149857600080fd5b6000808212156114fc57600080fd5b5090565b600061150b83610bc7565b90508082111561153357600061152183836115da565b905061152d84826117f2565b50610ffb565b80821015610ffb57600061154782846115da565b90506115538482611856565b50505050565b6000806115668385612020565b9050838110156114985760405162461bcd60e51b81526004016109dc90611d22565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061149883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611419565b60008061162883610d16565b90508015611785576001600160a01b0383166000908152600960205260409020546116539082611559565b6001600160a01b038416600081815260096020526040908190209290925590517fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d906116a0908490611bc9565b60405180910390a260065460405163a9059cbb60e01b81526000916001600160a01b03169063a9059cbb906116db9087908690600401611b64565b602060405180830381600087803b1580156116f557600080fd5b505af1158015611709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172d9190611b1c565b90508061177d576001600160a01b03841660009081526009602052604090205461175790836115da565b6001600160a01b03851660009081526009602052604081209190915592506107d3915050565b5090506107d3565b50600092915050565b60008061179b8385612077565b9050600083121580156117ae5750838113155b806114e457506000831280156114e4575083811361149857600080fd5b6000428211156117dd575060006107d3565b6012546117ea42846115da565b101592915050565b6117fc828261189a565b6118366118176109788360075461145390919063ffffffff16565b6001600160a01b0384166000908152600860205260409020549061178e565b6001600160a01b0390921660009081526008602052604090209190915550565b611860828261195a565b61183661187b6109788360075461145390919063ffffffff16565b6001600160a01b038416600090815260086020526040902054906114af565b6001600160a01b0382166118c05760405162461bcd60e51b81526004016109dc90611d59565b6118cc60008383610ffb565b6002546118d99082611559565b6002556001600160a01b0382166000908152602081905260409020546118ff9082611559565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061194e908590611bc9565b60405180910390a35050565b6001600160a01b0382166119805760405162461bcd60e51b81526004016109dc90611ecf565b61198c82600083610ffb565b6119c98160405180606001604052806022815260200161215d602291396001600160a01b0385166000908152602081905260409020549190611419565b6001600160a01b0383166000908152602081905260409020556002546119ef90826115da565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061194e908590611bc9565b600060208284031215611a41578081fd5b813561149881612139565b60008060408385031215611a5e578081fd5b8235611a6981612139565b91506020830135611a798161214e565b809150509250929050565b60008060408385031215611a96578182fd5b8235611aa181612139565b946020939093013593505050565b60008060408385031215611ac1578182fd5b8235611acc81612139565b91506020830135611a7981612139565b600080600060608486031215611af0578081fd5b8335611afb81612139565b92506020840135611b0b81612139565b929592945050506040919091013590565b600060208284031215611b2d578081fd5b81516114988161214e565b600060208284031215611b49578081fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03989098168852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b901515815260200190565b90815260200190565b6000602080835283518082850152825b81811015611bfe57858101830151858201604001528201611be2565b81811115611c0f5783604083870101525b50601f01601f1916929092016040019392505050565b6020808252604f908201527f5544414f546f6b656e5f4469766964656e645f547261636b65723a20636c616960408201527f6d57616974206d757374206265207570646174656420746f206265747765656e60608201526e203120616e6420323420686f75727360881b608082015260a00190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f45524332303a206361737420746f20746865207a65726f206164647265737300604082015260600190565b6020808252605b908201527f4469766964656e645f547261636b65723a20776974686472617744697669646560408201527f6e642064697361626c65642e20557365207468652027636c61696d272066756e60608201527f6374696f6e206f6e20746865206d61696e20636f6e74726163742e0000000000608082015260a00190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526026908201527f4469766964656e645f547261636b65723a204e6f207472616e736665727320616040820152651b1b1bddd95960d21b606082015260800190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526041908201527f5544414f546f6b656e5f4469766964656e645f547261636b65723a2043616e6e60408201527f6f742075706461746520636c61696d5761697420746f2073616d652076616c756060820152606560f81b608082015260a00190565b9283526020830191909152604082015260600190565b60ff91909116815260200190565b600080821280156001600160ff1b038490038513161561200157612001612123565b600160ff1b839003841281161561201a5761201a612123565b50500190565b6000821982111561203357612033612123565b500190565b60008261205357634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561207257612072612123565b500290565b60008083128015600160ff1b85018412161561209557612095612123565b6001600160ff1b03840183138116156120b0576120b0612123565b50500390565b6000828210156120c8576120c8612123565b500390565b6002810460018216806120e157607f821691505b6020821081141561210257634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561211c5761211c612123565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461076e57600080fd5b801515811461076e57600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122012971cc4a0f46c787f2ef0f6e9106be70fe256574e23851c89b3e778da30d21564736f6c63430008000033

Deployed ByteCode

0x6080604052600436106103e85760003560e01c8063871c128d11610208578063c492f04611610118578063e98030c7116100ab578063f480fec21161007a578063f480fec214610abf578063f637434214610adf578063f664da5514610af4578063f7c618c114610b14578063f832679514610b29576103ef565b8063e98030c714610a4a578063f11a24d314610a6a578063f27fd25414610a7f578063f2fde38b14610a9f576103ef565b8063dd62ed3e116100e7578063dd62ed3e146109e0578063e2f4560514610a00578063e4bf1bed14610a15578063e7841ec014610a35576103ef565b8063c492f04614610976578063c705c56914610996578063cfe0e619146109b6578063d2a8b440146109cb576103ef565b8063a26579ad1161019b578063aa797dbc1161016a578063aa797dbc146108c2578063ad56c13c146108e2578063afa4f3b214610916578063b62496f514610936578063c024666814610956576103ef565b8063a26579ad1461084d578063a457c2d714610862578063a8b9d24014610882578063a9059cbb146108a2576103ef565b806395d89b41116101d757806395d89b41146107e35780639a7a23d6146107f85780639c1b8af5146108185780639d913ef51461082d576103ef565b8063871c128d146107845780638da5cb5b146107a45780638de743b3146107b957806392136913146107ce576103ef565b806349bd5a5e1161030357806366a88d961161029657806370a082311161026557806370a0823114610705578063715018a6146107255780637bce5a041461073a57806385141a771461074f5780638692361114610764576103ef565b806366a88d961461069b5780636843cd84146106b05780636aa5b37f146106d0578063700bb191146106e5576103ef565b806360901444116102d2578063609014441461063157806361a60d571461064657806364b0f6531461066657806365b8dbc01461067b576103ef565b806349bd5a5e146105c75780634e71d92d146105dc5780634fbee193146105f15780635d098b3814610611576103ef565b806324942a041161037b57806331e79db01161034a57806331e79db01461055d5780633926876d1461057d57806339509351146105925780634144d9e4146105b2576103ef565b806324942a04146104fc5780632c1f52161461051157806330bb4cff14610526578063313ce5671461053b576103ef565b80630dcb2e89116103b75780630dcb2e89146104835780631694505e146104a557806318160ddd146104c757806323b872dd146104dc576103ef565b806302df64d6146103f457806306fdde031461041f57806308b2a12c14610441578063095ea7b314610456576103ef565b366103ef57005b600080fd5b34801561040057600080fd5b50610409610b3e565b6040516104169190613cdb565b60405180910390f35b34801561042b57600080fd5b50610434610b44565b6040516104169190613773565b34801561044d57600080fd5b50610409610bd6565b34801561046257600080fd5b5061047661047136600461349f565b610bdc565b6040516104169190613768565b34801561048f57600080fd5b506104a361049e366004613582565b610bfa565b005b3480156104b157600080fd5b506104ba610ca7565b6040516104169190613631565b3480156104d357600080fd5b50610409610cb6565b3480156104e857600080fd5b506104766104f73660046133c9565b610cbc565b34801561050857600080fd5b50610409610d43565b34801561051d57600080fd5b506104ba610d49565b34801561053257600080fd5b50610409610d58565b34801561054757600080fd5b50610550610dda565b6040516104169190613d93565b34801561056957600080fd5b506104a3610578366004613359565b610ddf565b34801561058957600080fd5b50610409610e4e565b34801561059e57600080fd5b506104766105ad36600461349f565b610e54565b3480156105be57600080fd5b506104ba610ea2565b3480156105d357600080fd5b506104ba610eb6565b3480156105e857600080fd5b506104a3610ec5565b3480156105fd57600080fd5b5061047661060c366004613359565b610f4d565b34801561061d57600080fd5b506104a361062c366004613359565b610f6b565b34801561063d57600080fd5b50610476610fd2565b34801561065257600080fd5b506104a3610661366004613359565b610fdb565b34801561067257600080fd5b5061040961103c565b34801561068757600080fd5b506104a3610696366004613359565b611081565b3480156106a757600080fd5b506104096112e7565b3480156106bc57600080fd5b506104096106cb366004613359565b6112ed565b3480156106dc57600080fd5b5061040961136e565b3480156106f157600080fd5b506104a3610700366004613582565b611374565b34801561071157600080fd5b50610409610720366004613359565b611455565b34801561073157600080fd5b506104a3611470565b34801561074657600080fd5b506104096114bb565b34801561075b57600080fd5b506104ba6114c1565b34801561077057600080fd5b506104a361077f366004613409565b6114d0565b34801561079057600080fd5b506104a361079f366004613582565b61153a565b3480156107b057600080fd5b506104ba611600565b3480156107c557600080fd5b5061040961160f565b3480156107da57600080fd5b50610409611615565b3480156107ef57600080fd5b5061043461161b565b34801561080457600080fd5b506104a3610813366004613409565b61162a565b34801561082457600080fd5b506104096116a5565b34801561083957600080fd5b506104a36108483660046135b2565b6116ab565b34801561085957600080fd5b506104096116f5565b34801561086e57600080fd5b5061047661087d36600461349f565b61173a565b34801561088e57600080fd5b5061040961089d366004613359565b6117a2565b3480156108ae57600080fd5b506104766108bd36600461349f565b6117d3565b3480156108ce57600080fd5b506104766108dd366004613359565b6117e7565b3480156108ee57600080fd5b506109026108fd366004613359565b6117fc565b604051610416989796959493929190613693565b34801561092257600080fd5b506104a3610931366004613582565b6118a9565b34801561094257600080fd5b50610476610951366004613359565b6118ed565b34801561096257600080fd5b506104a3610971366004613409565b611902565b34801561098257600080fd5b506104a36109913660046134ca565b6119c7565b3480156109a257600080fd5b506104766109b1366004613359565b611ac6565b3480156109c257600080fd5b50610409611b47565b3480156109d757600080fd5b506104a3611b4d565b3480156109ec57600080fd5b506104096109fb366004613391565b611c15565b348015610a0c57600080fd5b50610409611c40565b348015610a2157600080fd5b506104a3610a30366004613600565b611c46565b348015610a4157600080fd5b50610409611cd2565b348015610a5657600080fd5b506104a3610a65366004613582565b611d17565b348015610a7657600080fd5b50610409611d86565b348015610a8b57600080fd5b50610902610a9a366004613582565b611d8c565b348015610aab57600080fd5b506104a3610aba366004613359565b611dcd565b348015610acb57600080fd5b506104a3610ada366004613600565b611e3b565b348015610aeb57600080fd5b50610409611ec1565b348015610b0057600080fd5b506104a3610b0f36600461354a565b611ec7565b348015610b2057600080fd5b506104ba611f19565b348015610b3557600080fd5b50610409611f28565b600b5481565b606060038054610b5390613e0f565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7f90613e0f565b8015610bcc5780601f10610ba157610100808354040283529160200191610bcc565b820191906000526020600020905b815481529060010190602001808311610baf57829003601f168201915b5050505050905090565b600c5481565b6000610bf0610be9611feb565b8484611fef565b5060015b92915050565b610c02611feb565b6001600160a01b0316610c13611600565b6001600160a01b031614610c425760405162461bcd60e51b8152600401610c3990613b67565b60405180910390fd5b600854604051635ebf4db960e01b81526001600160a01b0390911690635ebf4db990610c72908490600401613cdb565b600060405180830381600087803b158015610c8c57600080fd5b505af1158015610ca0573d6000803e3d6000fd5b5050505050565b6006546001600160a01b031681565b60025490565b6000610cc98484846120a3565b610d3984610cd5611feb565b610d3485604051806060016040528060288152602001613ec5602891396001600160a01b038a16600090815260016020526040812090610d13611feb565b6001600160a01b03168152602081019190915260400160002054919061276a565b611fef565b5060019392505050565b60125481565b6008546001600160a01b031681565b600854604080516342d359d760e11b815290516000926001600160a01b0316916385a6b3ae916004808301926020929190829003018186803b158015610d9d57600080fd5b505afa158015610db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd5919061359a565b905090565b601290565b610de7611feb565b6001600160a01b0316610df8611600565b6001600160a01b031614610e1e5760405162461bcd60e51b8152600401610c3990613b67565b60085460405163031e79db60e41b81526001600160a01b03909116906331e79db090610c72908490600401613631565b60145481565b6000610bf0610e61611feb565b84610d348560016000610e72611feb565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490611f2e565b60185461010090046001600160a01b031681565b6007546001600160a01b031681565b60085460405163bc4c4b3760e01b81526001600160a01b039091169063bc4c4b3790610ef8903390600090600401613645565b602060405180830381600087803b158015610f1257600080fd5b505af1158015610f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4a9190613566565b50565b6001600160a01b03166000908152601d602052604090205460ff1690565b610f73611feb565b6001600160a01b0316610f84611600565b6001600160a01b031614610faa5760405162461bcd60e51b8152600401610c3990613b67565b601880546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60185460ff1681565b610fe3611feb565b6001600160a01b0316610ff4611600565b6001600160a01b03161461101a5760405162461bcd60e51b8152600401610c3990613b67565b601a80546001600160a01b0319166001600160a01b0392909216919091179055565b600854604080516304ddf6ef60e11b815290516000926001600160a01b0316916309bbedde916004808301926020929190829003018186803b158015610d9d57600080fd5b611089611feb565b6001600160a01b031661109a611600565b6001600160a01b0316146110c05760405162461bcd60e51b8152600401610c3990613b67565b6006546001600160a01b03828116911614156110ee5760405162461bcd60e51b8152600401610c3990613a67565b6006546040516001600160a01b03918216918316907f8fc842bbd331dfa973645f4ed48b11683d501ebf1352708d77a5da2ab49a576e90600090a3600680546001600160a01b0319166001600160a01b0383811691909117918290556040805163c45a015560e01b815290516000939092169163c45a015591600480820192602092909190829003018186803b15801561118757600080fd5b505afa15801561119b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111bf9190613375565b6001600160a01b031663c9c6539630600660009054906101000a90046001600160a01b03166001600160a01b031663ef8ef56f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561121c57600080fd5b505afa158015611230573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112549190613375565b6040518363ffffffff1660e01b8152600401611271929190613679565b602060405180830381600087803b15801561128b57600080fd5b505af115801561129f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c39190613375565b600780546001600160a01b0319166001600160a01b03929092169190911790555050565b60165481565b6008546040516370a0823160e01b81526000916001600160a01b0316906370a082319061131e908590600401613631565b60206040518083038186803b15801561133657600080fd5b505afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf4919061359a565b60175481565b6008546040516001624d3b8760e01b03198152600091829182916001600160a01b03169063ffb2c479906113ac908790600401613cdb565b606060405180830381600087803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe91906135d3565b925092509250326001600160a01b0316600015157fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a98858585896040516114479493929190613d78565b60405180910390a350505050565b6001600160a01b031660009081526020819052604090205490565b611478611feb565b6001600160a01b0316611489611600565b6001600160a01b0316146114af5760405162461bcd60e51b8152600401610c3990613b67565b6114b960006127a4565b565b600f5481565b601a546001600160a01b031681565b6114d8611feb565b6001600160a01b03166114e9611600565b6001600160a01b03161461150f5760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b03919091166000908152601b60205260409020805460ff1916911515919091179055565b611542611feb565b6001600160a01b0316611553611600565b6001600160a01b0316146115795760405162461bcd60e51b8152600401610c3990613b67565b62030d40811015801561158f57506207a1208111155b6115ab5760405162461bcd60e51b8152600401610c39906138ab565b601c548114156115cd5760405162461bcd60e51b8152600401610c39906139e4565b601c5460405182907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3601c55565b6005546001600160a01b031690565b60115481565b60105481565b606060048054610b5390613e0f565b611632611feb565b6001600160a01b0316611643611600565b6001600160a01b0316146116695760405162461bcd60e51b8152600401610c3990613b67565b6007546001600160a01b03838116911614156116975760405162461bcd60e51b8152600401610c39906137c6565b6116a182826127f6565b5050565b601c5481565b6116b3611feb565b6001600160a01b03166116c4611600565b6001600160a01b0316146116ea5760405162461bcd60e51b8152600401610c3990613b67565b601791909155601655565b60085460408051631bc9e27b60e21b815290516000926001600160a01b031691636f2789ec916004808301926020929190829003018186803b158015610d9d57600080fd5b6000610bf0611747611feb565b84610d3485604051806060016040528060258152602001613eed6025913960016000611771611feb565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919061276a565b6008546040516302a2e74960e61b81526000916001600160a01b03169063a8b9d2409061131e908590600401613631565b6000610bf06117e0611feb565b84846120a3565b601b6020526000908152604090205460ff1681565b60085460405163fbcbc0f160e01b815260009182918291829182918291829182916001600160a01b039091169063fbcbc0f19061183d908c90600401613631565b6101006040518083038186803b15801561185657600080fd5b505afa15801561186a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188e9190613436565b97509750975097509750975097509750919395975091939597565b6118b1611feb565b6001600160a01b03166118c2611600565b6001600160a01b0316146118e85760405162461bcd60e51b8152600401610c3990613b67565b600a55565b601e6020526000908152604090205460ff1681565b61190a611feb565b6001600160a01b031661191b611600565b6001600160a01b0316146119415760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b0382166000908152601d602052604090205460ff161515811515146116a1576001600160a01b0382166000818152601d602052604090819020805460ff1916841515179055517f9d8f7706ea1113d1a167b526eca956215946dd36cc7df39eb16180222d8b5df7906119bb908490613768565b60405180910390a25050565b6119cf611feb565b6001600160a01b03166119e0611600565b6001600160a01b031614611a065760405162461bcd60e51b8152600401610c3990613b67565b60005b82811015611a855781601d6000868685818110611a3657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611a4b9190613359565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580611a7d81613e4a565b915050611a09565b507f7fdaf542373fa84f4ee8d662c642f44e4c2276a217d7d29e548b6eb29a233b35838383604051611ab99392919061370f565b60405180910390a1505050565b60085460405163c705c56960e01b81526000916001600160a01b03169063c705c56990611af7908590600401613631565b60206040518083038186803b158015611b0f57600080fd5b505afa158015611b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613566565b60155481565b611b55611feb565b6001600160a01b0316611b66611600565b6001600160a01b031614611b8c5760405162461bcd60e51b8152600401610c3990613b67565b6000611b9730611455565b905060008111611bb95760405162461bcd60e51b8152600401610c3990613afa565b6007805460ff60a01b1916600160a01b17905560135415611bdf57611bdf601354612901565b60145415611bf257611bf2601454612994565b60155415611c0557611c05601554612b58565b506007805460ff60a01b19169055565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600a5481565b611c4e611feb565b6001600160a01b0316611c5f611600565b6001600160a01b031614611c855760405162461bcd60e51b8152600401610c3990613b67565b6019611c9d82611c978581888a611f2e565b90611f2e565b1115611cbb5760405162461bcd60e51b8152600401610c3990613874565b600b92909255600d92909255600f91909155601155565b6008546040805163039e107b60e61b815290516000926001600160a01b03169163e7841ec0916004808301926020929190829003018186803b158015610d9d57600080fd5b611d1f611feb565b6001600160a01b0316611d30611600565b6001600160a01b031614611d565760405162461bcd60e51b8152600401610c3990613b67565b60085460405163e98030c760e01b81526001600160a01b039091169063e98030c790610c72908490600401613cdb565b600d5481565b600854604051635183d6fd60e01b815260009182918291829182918291829182916001600160a01b0390911690635183d6fd9061183d908c90600401613cdb565b611dd5611feb565b6001600160a01b0316611de6611600565b6001600160a01b031614611e0c5760405162461bcd60e51b8152600401610c3990613b67565b6001600160a01b038116611e325760405162461bcd60e51b8152600401610c39906138ff565b610f4a816127a4565b611e43611feb565b6001600160a01b0316611e54611600565b6001600160a01b031614611e7a5760405162461bcd60e51b8152600401610c3990613b67565b6019611e8c82611c978581888a611f2e565b1115611eaa5760405162461bcd60e51b8152600401610c3990613ca4565b600c92909255600e92909255601091909155601255565b600e5481565b611ecf611feb565b6001600160a01b0316611ee0611600565b6001600160a01b031614611f065760405162461bcd60e51b8152600401610c3990613b67565b6018805460ff1916911515919091179055565b6009546001600160a01b031681565b60135481565b600080611f3b8385613da1565b905083811015611f5d5760405162461bcd60e51b8152600401610c3990613a30565b9392505050565b600082611f7357506000610bf4565b6000611f7f8385613dd9565b905082611f8c8583613db9565b14611f5d5760405162461bcd60e51b8152600401610c3990613b26565b6000611f5d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612d17565b3390565b6001600160a01b0383166120155760405162461bcd60e51b8152600401610c3990613c29565b6001600160a01b03821661203b5760405162461bcd60e51b8152600401610c3990613945565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612096908590613cdb565b60405180910390a3505050565b6001600160a01b0383166120c95760405162461bcd60e51b8152600401610c3990613be4565b6001600160a01b0382166120ef5760405162461bcd60e51b8152600401610c3990613831565b6001600160a01b0383166000908152601b602052604090205460ff1615801561213157506001600160a01b0382166000908152601b602052604090205460ff16155b61214d5760405162461bcd60e51b8152600401610c3990613ad3565b806121635761215e83836000612d45565b612765565b6001600160a01b0383166000908152601d602052604090205460ff161580156121a557506001600160a01b0382166000908152601d602052604090205460ff16155b1561224e5760185460ff166121cc5760405162461bcd60e51b8152600401610c3990613aaa565b6007546001600160a01b0384811691161415612204576017548111156122045760405162461bcd60e51b8152600401610c3990613b9c565b6007546001600160a01b0383811691161461224e576016548161222684611455565b6122309190613da1565b111561224e5760405162461bcd60e51b8152600401610c3990613c6d565b600061225930611455565b600a549091508110801590819061227a5750600754600160a01b900460ff16155b801561229f57506001600160a01b0385166000908152601e602052604090205460ff16155b80156122c457506122ae611600565b6001600160a01b0316856001600160a01b031614155b80156122e957506122d3611600565b6001600160a01b0316846001600160a01b031614155b15612348576007805460ff60a01b1916600160a01b1790556015541561231457612314601554612b58565b6013541561232757612327601354612901565b6014541561233a5761233a601454612994565b6007805460ff60a01b191690555b6007546001600160a01b0386166000908152601d602052604090205460ff600160a01b90920482161591168061239657506001600160a01b0385166000908152601d602052604090205460ff165b1561239f575060005b80156125ab576001600160a01b0386166000908152601e6020526040812054819081908190819060ff161561248d576123ee60646123e8600d548c611f6490919063ffffffff16565b90611fa9565b935083601360008282546124029190613da1565b9091555050600b5461241c906064906123e8908c90611f64565b925082601460008282546124309190613da1565b9091555050600f5461244a906064906123e8908c90611f64565b9150816015600082825461245e9190613da1565b9091555050601154612478906064906123e8908c90611f64565b905061248a81611c9784818888611f2e565b94505b6001600160a01b038a166000908152601e602052604090205460ff1615612567576124c860646123e8600e548c611f6490919063ffffffff16565b935083601360008282546124dc9190613da1565b9091555050600c546124f6906064906123e8908c90611f64565b9250826014600082825461250a9190613da1565b9091555050601054612524906064906123e8908c90611f64565b915081601560008282546125389190613da1565b9091555050601254612552906064906123e8908c90611f64565b905061256481611c9784818888611f2e565b94505b6125718986612e5a565b9850801561259157601a54612591908c906001600160a01b031683612d45565b6125a58b306125a08885612e5a565b612d45565b50505050505b6125b6868686612d45565b6008546001600160a01b031663e30443bc876125d181611455565b6040518363ffffffff1660e01b81526004016125ee929190613660565b600060405180830381600087803b15801561260857600080fd5b505af1925050508015612619575060015b506008546001600160a01b031663e30443bc8661263581611455565b6040518363ffffffff1660e01b8152600401612652929190613660565b600060405180830381600087803b15801561266c57600080fd5b505af192505050801561267d575060015b50600754600160a01b900460ff1661276157601c546008546040516001624d3b8760e01b031981526001600160a01b039091169063ffb2c479906126c5908490600401613cdb565b606060405180830381600087803b1580156126df57600080fd5b505af192505050801561270f575060408051601f3d908101601f1916820190925261270c918101906135d3565b60015b6127185761275f565b60405132906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a9890612753908790879087908b90613d78565b60405180910390a35050505b505b5050505b505050565b6000818484111561278e5760405162461bcd60e51b8152600401610c399190613773565b50600061279b8486613df8565b95945050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166000908152601e602052604090205460ff16151581151514156128355760405162461bcd60e51b8152600401610c3990613987565b6001600160a01b0382166000908152601e60205260409020805460ff191682158015919091179091556128c55760085460405163031e79db60e41b81526001600160a01b03909116906331e79db090612892908590600401613631565b600060405180830381600087803b1580156128ac57600080fd5b505af11580156128c0573d6000803e3d6000fd5b505050505b604051811515906001600160a01b038416907fffa9187bf1f18bf477bd0ea1bcbb64e93b6a98132473929edfce215cd9b16fab90600090a35050565b600061290e826002611fa9565b9050600061291c8383612e5a565b90504761292883612e9c565b60006129344783612e5a565b90506129408382613019565b8460135461294e9190613df8565b6013556040517f17bbfb9a6069321b6ded73bd96327c9e6b7212a5cd51ff219cd61370acafb5619061298590869084908790613d62565b60405180910390a15050505050565b61299d816130c3565b806014546129ab9190613df8565b6014556009546040516370a0823160e01b81526000916001600160a01b0316906370a08231906129df903090600401613631565b60206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f919061359a565b60095460085460405163a9059cbb60e01b81529293506000926001600160a01b039283169263a9059cbb92612a6b929116908690600401613660565b602060405180830381600087803b158015612a8557600080fd5b505af1158015612a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abd9190613566565b905080156127655760085460405163ba72a95560e01b81526001600160a01b039091169063ba72a95590612af5908590600401613cdb565b600060405180830381600087803b158015612b0f57600080fd5b505af1158015612b23573d6000803e3d6000fd5b505050507f80195cc573b02cc48460cbca6e6e4cc85ddb91959d946e1c3025ea3d87942dc38383604051611ab9929190613d54565b6009546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612b89903090600401613631565b60206040518083038186803b158015612ba157600080fd5b505afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd9919061359a565b9050612be4826130c3565b6009546040516370a0823160e01b8152600091612c719184916001600160a01b0316906370a0823190612c1b903090600401613631565b60206040518083038186803b158015612c3357600080fd5b505afa158015612c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6b919061359a565b90612e5a565b60095460185460405163a9059cbb60e01b81529293506001600160a01b039182169263a9059cbb92612cae92610100900416908590600401613660565b602060405180830381600087803b158015612cc857600080fd5b505af1158015612cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d009190613566565b5082601554612d0f9190613df8565b601555505050565b60008183612d385760405162461bcd60e51b8152600401610c399190613773565b50600061279b8486613db9565b6001600160a01b038316612d6b5760405162461bcd60e51b8152600401610c3990613be4565b6001600160a01b038216612d915760405162461bcd60e51b8152600401610c3990613831565b612d9c838383612765565b612dd981604051806060016040528060268152602001613e9f602691396001600160a01b038616600090815260208190526040902054919061276a565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612e089082611f2e565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612096908590613cdb565b6000611f5d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061276a565b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612edf57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092018101919091526006546040805163ef8ef56f60e01b81529051919093169263ef8ef56f926004808301939192829003018186803b158015612f3357600080fd5b505afa158015612f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6b9190613375565b81600181518110612f8c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600654612fb29130911684611fef565b60065460405163791ac94760e01b81526001600160a01b039091169063791ac94790612feb908590600090869030904290600401613ce4565b600060405180830381600087803b15801561300557600080fd5b505af1158015612761573d6000803e3d6000fd5b6006546130319030906001600160a01b031684611fef565b60065460195460405163f305d71960e01b81526001600160a01b039283169263f305d71992859261307192309289926000928392169042906004016136d4565b6060604051808303818588803b15801561308a57600080fd5b505af115801561309e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ca091906135d3565b6040805160038082526080820190925260009160208201606080368337019050509050308160008151811061310857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092018101919091526006546040805163ef8ef56f60e01b81529051919093169263ef8ef56f926004808301939192829003018186803b15801561315c57600080fd5b505afa158015613170573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131949190613375565b6009546001600160a01b03908116911614156132015760095481516001600160a01b0390911690829060019081106131dc57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050613308565b600660009054906101000a90046001600160a01b03166001600160a01b031663ef8ef56f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561324f57600080fd5b505afa158015613263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132879190613375565b816001815181106132a857634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526009548251911690829060029081106132e757634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250505b6006546133209030906001600160a01b031684611fef565b600654604051635c11d79560e01b81526001600160a01b0390911690635c11d79590612feb908590600090869030904290600401613ce4565b60006020828403121561336a578081fd5b8135611f5d81613e7b565b600060208284031215613386578081fd5b8151611f5d81613e7b565b600080604083850312156133a3578081fd5b82356133ae81613e7b565b915060208301356133be81613e7b565b809150509250929050565b6000806000606084860312156133dd578081fd5b83356133e881613e7b565b925060208401356133f881613e7b565b929592945050506040919091013590565b6000806040838503121561341b578182fd5b823561342681613e7b565b915060208301356133be81613e90565b600080600080600080600080610100898b031215613452578384fd5b885161345d81613e7b565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b600080604083850312156134b1578182fd5b82356134bc81613e7b565b946020939093013593505050565b6000806000604084860312156134de578283fd5b833567ffffffffffffffff808211156134f5578485fd5b818601915086601f830112613508578485fd5b813581811115613516578586fd5b8760208083028501011115613529578586fd5b6020928301955093505084013561353f81613e90565b809150509250925092565b60006020828403121561355b578081fd5b8135611f5d81613e90565b600060208284031215613577578081fd5b8151611f5d81613e90565b600060208284031215613593578081fd5b5035919050565b6000602082840312156135ab578081fd5b5051919050565b600080604083850312156135c4578182fd5b50508035926020909101359150565b6000806000606084860312156135e7578081fd5b8351925060208401519150604084015190509250925092565b60008060008060808587031215613615578182fd5b5050823594602084013594506040840135936060013592509050565b6001600160a01b0391909116815260200190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03989098168852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b6040808252810183905260008460608301825b8681101561375257823561373581613e7b565b6001600160a01b0316825260209283019290910190600101613722565b5080925050508215156020830152949350505050565b901515815260200190565b6000602080835283518082850152825b8181101561379f57858101830151858201604001528201613783565b818111156137b05783604083870101525b50601f01601f1916929092016040019392505050565b60208082526045908201527f5468652050616e63616b655377617020706169722063616e6e6f74206265207260408201527f656d6f7665642066726f6d206175746f6d617465644d61726b65744d616b6572606082015264506169727360d81b608082015260a00190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526019908201527f546f74616c2062757920666565206973206f7665722032352500000000000000604082015260600190565b60208082526034908201527f476173466f7250726f63657373696e67206d757374206265206265747765656e6040820152730203230302c30303020616e64203530302c3030360641b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526038908201527f4175746f6d61746564206d61726b6574206d616b65722070616972206973206160408201527f6c72656164792073657420746f20746861742076616c75650000000000000000606082015260800190565b6020808252602c908201527f43616e6e6f742075706461746520676173466f7250726f63657373696e67207460408201526b6f2073616d652076616c756560a01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526023908201527f54686520726f7574657220616c7265616479206861732074686174206164647260408201526265737360e81b606082015260800190565b6020808252600f908201526e151c985919481a5cc818db1bdcd959608a1b604082015260600190565b6020808252600d908201526c456e656d79206164647265737360981b604082015260600190565b602080825260129082015271746f6b656e2062616c616e6365207a65726f60701b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526028908201527f5472616e7366657220616d6f756e74206578636565647320746865206d6178426040820152673abca634b6b4ba1760c11b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601b908201527f4578636565647320746865206d617857616c6c65744c696d69742e0000000000604082015260600190565b60208082526019908201527f546f74616c2073656c20666565206973206f7665722032352500000000000000604082015260600190565b90815260200190565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015613d335784516001600160a01b031683529383019391830191600101613d0e565b50506001600160a01b03969096166060850152505050608001529392505050565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60ff91909116815260200190565b60008219821115613db457613db4613e65565b500190565b600082613dd457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615613df357613df3613e65565b500290565b600082821015613e0a57613e0a613e65565b500390565b600281046001821680613e2357607f821691505b60208210811415613e4457634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613e5e57613e5e613e65565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114610f4a57600080fd5b8015158114610f4a57600080fdfe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212203767ec4d8822def3e0e256de6a5ccf0158fd99aa70017a26134b59ef9f0b5b6564736f6c63430008000033