ETH Price: $2,596.51 (-2.56%)

Token

Solar AI (SOLAR)
 

Overview

Max Total Supply

100,000,000 SOLAR

Holders

92

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
161,113.48004584273307674 SOLAR

Value
$0.00
0x63ad67fd8453a9a938cb89565e3263aaa9385099
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
ChainFactory_ERC20

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion, MIT license
File 1 of 14 : ChainFactory_ERC20.sol
/*

  Solar AI

  Solar AI is an Ethereum blockchain-based project that utilizes solar energy to mine cryptocurrency and shares the profit as revenue with its holders
  
  Web: https://solarai.biz
  X: https://x.com/solaraieth
  Telegram: https://t.me/Solar_AI

*/

// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";
import "./CF_ERC20.sol";
import "./CF_Recoverable.sol";
import "./CF_Burnable.sol";
import "./CF_Whitelist.sol";
import "./CF_Cooldown.sol";
import "./CF_MaxTx.sol";
import "./CF_MaxBalance.sol";
import "./CF_Taxable.sol";
import "./CF_DEXRouterV2.sol";

contract ChainFactory_ERC20 is CF_Common, CF_Ownable, CF_ERC20, CF_Recoverable, CF_Burnable, CF_Whitelist, CF_Cooldown, CF_MaxTx, CF_MaxBalance, CF_Taxable, CF_DEXRouterV2 {
  constructor() {
    _name = unicode"Solar AI";
    _symbol = unicode"SOLAR";
    _decimals = 18;
    _totalSupply = 100000000000000000000000000; // 100,000,000 SOLAR
    _transferOwnership(0xA26BD8BCB6904533B9eff88E5c5563C60dA614eD);
    _transferInitialSupply(0xA26BD8BCB6904533B9eff88E5c5563C60dA614eD, 100000); // 100%
    _setDEXRouterV2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    _setEarlyPenaltyTime(180); // 3min
    _setTaxToken(address(this));
    _autoSwapEnabled = true;
    _setAutoSwapPercent(50, 250); // 0.05% -> 0.25% of total supply
    _setAutoAddLiquidityPercent(100, 100000); // 0.1% -> 100% of total supply
    _setTaxBeneficiary(0, 0x8881d9869aC7C7840971cAac043D7f4D144Abd10, [ uint24(0), uint24(0), uint24(0) ], [ uint24(0), uint24(2000), uint24(2000) ]); // ChainFactory Anti-Sniper revenue (10%)
    _setTaxBeneficiary(1, 0xA26BD8BCB6904533B9eff88E5c5563C60dA614eD, [ uint24(0), uint24(5000), uint24(5000) ], [ uint24(0), uint24(20000), uint24(20000) ]);
    _initialWhitelist([ 0xA26BD8BCB6904533B9eff88E5c5563C60dA614eD, 0x1fE6a48678d757df6bC7497520D4E432cFf5F966, 0x74001DcFf64643B76cE4919af4DcD83da6Fe1E02 ]);
    _setCooldown(5, 3600, 3600); // 5 tx in 1h will result in a 1h freeze
    _setMaxTxPercent(1000); // 1% of total supply
    _setMaxBalancePercent(2000); // 2% of total supply
    _domainSeparator = keccak256(abi.encode(keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(_name)), keccak256(bytes("1")), block.chainid, address(this)));

    _initialized = true;
  }

  function _transfer(address from, address to, uint256 amount) internal virtual override {
    if (to == address(0xdEaD)) {
      _burn(from, amount);

      return;
    }

    if (!_distributing && !_swapping && (from != _dex.pair && from != _dex.router)) {
      _autoSwap(false);
      _autoTaxDistribute();
    }

    if (amount > 0 && !_whitelisted[from] && !_whitelisted[to] && from != address(this) && to != address(this) && to != _dex.router) {
      require((from != _dex.pair && to != _dex.pair) || ((from == _dex.pair || to == _dex.pair) && _tradingEnabled > 0), "Trading disabled");

      unchecked {
        if (_cooldownPeriod > 0 && from != _dex.pair) {
          require(remainingCooldownTime(from) == 0, "Cooldown");

          if (_holder[from].start + _cooldownTriggerTime < _timestamp()) {
            _holder[from].count = 1;
            _holder[from].start = _timestamp();
          } else {
            if (++_holder[from].count >= _cooldownTriggerCount) { _cooldown(from); }
          }
        }

        require(amount <= _maxTxAmount, "Exceeds maxTx");
        require(to == address(this) || (to == _dex.pair || to == _dex.router) || _balance[to] + amount <= _maxBalanceAmount, "Exceeds maxBalance");

        if (!_suspendTaxes && !_distributing && !_swapping) {
          uint256 appliedTax;
          uint8 taxType;

          if (from == _dex.pair || to == _dex.pair) { taxType = from == _dex.pair ? 1 : 2; }

          address _account = taxType == 1 ? to : from;

          if (_tradingEnabled + _earlyPenaltyTime >= _timestamp() && !_holder[_account].penalty) { _holder[_account].penalty = true; }

          for (uint8 i; i < 6; i++) {
            uint256 percent = uint256(taxType > 0 ? (taxType == 1 ? (_holder[_account].penalty ? _taxBeneficiary[i].penalty[1] : _taxBeneficiary[i].percent[1]) : (_holder[_account].penalty ? _taxBeneficiary[i].penalty[2] : _taxBeneficiary[i].percent[2])) : (_holder[_account].penalty ? _taxBeneficiary[i].penalty[0] : _taxBeneficiary[i].percent[0]));

            if (percent == 0) { continue; }

            uint256 taxAmount = _percentage(amount, percent);

            super._transfer(from, address(this), taxAmount);

            if (_taxBeneficiary[i].account == _dex.pair) {
              _amountForLiquidity += taxAmount;
            } else if (_taxBeneficiary[i].account == address(0xdEaD)) {
              _burn(address(this), taxAmount);
            } else {
              _taxBeneficiary[i].unclaimed += taxAmount;
              _amountForTaxDistribution += taxAmount;
              _totalTaxUnclaimed += taxAmount;
            }

            appliedTax += taxAmount;
          }

          if (appliedTax > 0) {
            _totalTaxCollected += appliedTax;

            amount -= appliedTax;
          }
        }
      }
    }

    super._transfer(from, to, amount);
  }

  function _burn(address account, uint256 amount) internal virtual override {
    super._burn(account, amount);

    _setMaxTxPercent(_maxTxPercent);
    _setMaxBalancePercent(_maxBalancePercent);
    _setAutoSwapPercent(_minAutoSwapPercent, _maxAutoSwapPercent);
    _setAutoAddLiquidityPercent(_minAutoAddLiquidityPercent, _maxAutoAddLiquidityPercent);
  }

  function _transferInitialSupply(address account, uint24 percent) private {
    require(!_initialized);

    uint256 amount = _percentage(_totalSupply, uint256(percent));

    _balance[account] = amount;

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

  /// @notice Returns a list specifying the renounce status of each feature
  function renounced() external view returns (bool Whitelist, bool Cooldown, bool MaxTx, bool MaxBalance, bool DEXRouterV2, bool Taxable) {
    return (_renounced.Whitelist, _renounced.Cooldown, _renounced.MaxTx, _renounced.MaxBalance, _renounced.DEXRouterV2, _renounced.Taxable);
  }

  /// @notice Returns basic information about this Smart-Contract
  function info() external view returns (string memory name, string memory symbol, uint8 decimals, address owner, uint256 totalSupply, string memory version) {
    return (_name, _symbol, _decimals, _owner, _totalSupply, _version);
  }

  receive() external payable { }
  fallback() external payable { }
}

File 2 of 14 : IDEXV2.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

interface IDEXRouterV2 {
  function factory() external pure returns (address);
  function WETH() external pure returns (address);
  function addLiquidityETH(address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
  function swapExactTokensForETHSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external;
  function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external;
}

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

File 3 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

interface IERC20 {
  function balanceOf(address account) external view returns (uint256);
  function transfer(address to, uint256 amount) external returns (bool);
  function approve(address spender, uint256 amount) external returns (bool);
}

File 4 of 14 : CF_ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";

abstract contract CF_ERC20 is CF_Common {
  string internal _name;
  string internal _symbol;
  bytes32 internal _domainSeparator;
  bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
  mapping(address => uint256) private _nonces;

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

  function name() external view returns (string memory) {
    return _name;
  }

  function symbol() external view returns (string memory) {
    return _symbol;
  }

  function decimals() external view returns (uint8) {
    return _decimals;
  }

  function totalSupply() external view returns (uint256) {
    return _totalSupply;
  }

  function balanceOf(address account) external view returns (uint256) {
    return _balance[account];
  }

  function allowance(address owner, address spender) public view returns (uint256) {
    return _allowance[owner][spender];
  }

  function approve(address spender, uint256 amount) external returns (bool) {
    _approve(msg.sender, spender, amount);

    return true;
  }

  function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external {
    require(deadline >= block.timestamp, "Expired signature");

    unchecked {
      bytes32 digest = keccak256(abi.encodePacked(hex"1901", _domainSeparator, keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _nonces[owner]++, deadline))));
      address recoveredAddress = ecrecover(digest, v, r, s);

      require(recoveredAddress != address(0) && recoveredAddress == owner, "Invalid signature");
    }

    _approve(owner, spender, value);
  }

  function nonces(address owner) external view returns (uint256) {
    return _nonces[owner];
  }

  function DOMAIN_SEPARATOR() external view returns (bytes32) {
    return _domainSeparator;
  }

  function transfer(address to, uint256 amount) external returns (bool) {
    _transfer(msg.sender, to, amount);

    return true;
  }

  function transferFrom(address from, address to, uint256 amount) external returns (bool) {
    _spendAllowance(from, msg.sender, amount);
    _transfer(from, to, amount);

    return true;
  }

  function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {
    unchecked {
      _approve(msg.sender, spender, allowance(msg.sender, spender) + addedValue);
    }

    return true;
  }

  function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {
    uint256 currentAllowance = allowance(msg.sender, spender);

    require(currentAllowance >= subtractedValue, "Negative allowance");

    unchecked {
      _approve(msg.sender, spender, currentAllowance - subtractedValue);
    }

    return true;
  }

  function _approve(address owner, address spender, uint256 amount) internal {
    _allowance[owner][spender] = amount;

    emit Approval(owner, spender, amount);
  }

  function _spendAllowance(address owner, address spender, uint256 amount) internal {
    uint256 currentAllowance = allowance(owner, spender);

    require(currentAllowance >= amount, "Insufficient allowance");

    unchecked {
      _approve(owner, spender, currentAllowance - amount);
    }
  }

  function _transfer(address from, address to, uint256 amount) internal virtual {
    require(from != address(0) && to != address(0), "Transfer from/to zero address");
    require(_balance[from] >= amount, "Exceeds balance");

    if (amount > 0) {
      unchecked {
        _balance[from] -= amount;
        _balance[to] += amount;
      }
    }

    emit Transfer(from, to, amount);
  }
}

File 5 of 14 : CF_MaxTx.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";

abstract contract CF_MaxTx is CF_Common, CF_Ownable {
  event SetMaxTxPercent(uint24 percent);
  event RenouncedMaxTx();

  /// @notice Permanently renounce and prevent the owner from being able to update the max. transferable amount
  /// @dev Existing settings will continue to be effective
  function renounceMaxTx() external onlyOwner {
    _renounced.MaxTx = true;

    emit RenouncedMaxTx();
  }

  /// @notice Percentage of the max. transferable amount, depending on total supply
  function getMaxTxPercent() external view returns (uint24) {
    return _maxTxPercent;
  }

  /// @notice Set the max. percentage of a transferable amount, depending on total supply
  /// @param percent Desired percentage, multiplied by denominator (min. 0.1% of total supply)
  function setMaxTxPercent(uint24 percent) external onlyOwner {
    require(!_renounced.MaxTx);

    _setMaxTxPercent(percent);

    emit SetMaxTxPercent(percent);
  }

  function _setMaxTxPercent(uint24 percent) internal {
    unchecked {
      require(percent >= 100 && percent <= 100 * _denominator);
    }

    _maxTxPercent = percent;
    _maxTxAmount = _percentage(_totalSupply, uint256(percent));

    if (!_initialized) { emit SetMaxTxPercent(percent); }
  }
}

File 6 of 14 : CF_Common.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./IDEXV2.sol";
import "./IERC20.sol";

abstract contract CF_Common {
  string internal constant _version = "1.0.3";

  mapping(address => uint256) internal _balance;
  mapping(address => mapping(address => uint256)) internal _allowance;
  mapping(address => bool) internal _whitelisted;
  mapping(address => holderAccount) internal _holder;
  mapping(uint8 => taxBeneficiary) internal _taxBeneficiary;
  mapping(address => uint256) internal _tokensForTaxDistribution;

  address[] internal _holders;

  bool internal _autoSwapEnabled;
  bool internal _swapping;
  bool internal _suspendTaxes;
  bool internal _distributing;
  bool internal immutable _initialized;

  uint8 internal immutable _decimals;
  uint8 internal _cooldownTriggerCount;
  uint24 internal constant _denominator = 1000;
  uint24 internal _maxTxPercent;
  uint24 internal _maxBalancePercent;
  uint24 internal _totalTxTax;
  uint24 internal _totalBuyTax;
  uint24 internal _totalSellTax;
  uint24 internal _totalPenaltyTxTax;
  uint24 internal _totalPenaltyBuyTax;
  uint24 internal _totalPenaltySellTax;
  uint24 internal _minAutoSwapPercent;
  uint24 internal _maxAutoSwapPercent;
  uint24 internal _minAutoAddLiquidityPercent;
  uint24 internal _maxAutoAddLiquidityPercent;
  uint32 internal _lastTaxDistribution;
  uint32 internal _tradingEnabled;
  uint32 internal _lastSwap;
  uint32 internal _earlyPenaltyTime;
  uint32 internal _cooldownTriggerTime;
  uint32 internal _cooldownPeriod;
  uint256 internal _totalSupply;
  uint256 internal _totalBurned;
  uint256 internal _maxTxAmount;
  uint256 internal _maxBalanceAmount;
  uint256 internal _minAutoSwapAmount;
  uint256 internal _maxAutoSwapAmount;
  uint256 internal _minAutoAddLiquidityAmount;
  uint256 internal _maxAutoAddLiquidityAmount;
  uint256 internal _amountForLiquidity;
  uint256 internal _ethForLiquidity;
  uint256 internal _totalTaxCollected;
  uint256 internal _totalTaxUnclaimed;
  uint256 internal _amountForTaxDistribution;
  uint256 internal _amountSwappedForTaxDistribution;
  uint256 internal _ethForTaxDistribution;

  struct Renounced {
    bool Whitelist;
    bool Cooldown;
    bool MaxTx;
    bool MaxBalance;
    bool Taxable;
    bool DEXRouterV2;
  }

  struct holderAccount {
    bool exists;
    bool penalty;
    uint32 count;
    uint32 start;
    uint32 cooldown;
  }

  struct taxBeneficiary {
    bool exists;
    address account;
    uint24[3] percent; // 0: tx, 1: buy, 2: sell
    uint24[3] penalty;
    uint256 unclaimed;
  }

  struct DEXRouterV2 {
    address router;
    address pair;
    address token0;
    address WETH;
    address receiver;
  }

  Renounced internal _renounced;
  IERC20 internal _taxToken;
  DEXRouterV2 internal _dex;

  function _percentage(uint256 amount, uint256 bps) internal pure returns (uint256) {
    unchecked {
      return (amount * bps) / (100 * uint256(_denominator));
    }
  }

  function _timestamp() internal view returns (uint32) {
    unchecked {
      return uint32(block.timestamp % 2**32);
    }
  }

  function denominator() external pure returns (uint24) {
    return _denominator;
  }

  function version() external pure returns (string memory) {
    return _version;
  }
}

File 7 of 14 : CF_Ownable.sol
// SPDX-License-Identifier: MIT

import "./CF_Common.sol";

pragma solidity 0.8.25;

abstract contract CF_Ownable is CF_Common {
  address internal _owner;

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

  modifier onlyOwner() {
    require(_owner == msg.sender, "Unauthorized");

    _;
  }

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

  function renounceOwnership() external onlyOwner {
    _renounced.Whitelist = true;
    _renounced.Cooldown = true;
    _renounced.MaxTx = true;
    _renounced.MaxBalance = true;
    _renounced.Taxable = true;
    _renounced.DEXRouterV2 = true;

    _transferOwnership(address(0));
  }

  function transferOwnership(address newOwner) external onlyOwner {
    require(newOwner != address(0));

    _transferOwnership(newOwner);
  }

  function _transferOwnership(address newOwner) internal {
    address oldOwner = _owner;
    _owner = newOwner;

    emit OwnershipTransferred(oldOwner, newOwner);
  }
}

File 8 of 14 : CF_Taxable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";
import "./CF_ERC20.sol";

abstract contract CF_Taxable is CF_Common, CF_Ownable, CF_ERC20 {
  event SetTaxBeneficiary(uint8 slot, address account, uint24[3] percent, uint24[3] penalty);
  event SetEarlyPenaltyTime(uint32 time);
  event TaxDistributed(uint256 amount);
  event RenouncedTaxable();

  struct taxBeneficiaryView {
    address account;
    uint24[3] percent;
    uint24[3] penalty;
    uint256 unclaimed;
  }

  modifier lockDistributing {
    _distributing = true;
    _;
    _distributing = false;
  }

  /// @notice Permanently renounce and prevent the owner from being able to update the tax features
  /// @dev Existing settings will continue to be effective
  function renounceTaxable() external onlyOwner {
    _renounced.Taxable = true;

    emit RenouncedTaxable();
  }

  /// @notice Total amount of taxes collected so far
  function totalTaxCollected() external view returns (uint256) {
    return _totalTaxCollected;
  }
  /// @notice Tax applied per transfer
  /// @dev Taking in consideration your wallet address
  function txTax() external view returns (uint24) {
    return txTax(msg.sender);
  }

  /// @notice Tax applied per transfer
  /// @param from Sender address
  function txTax(address from) public view returns (uint24) {
    unchecked {
      return from == address(this) || _whitelisted[from] || from == _dex.pair ? 0 : (_holder[from].penalty || _tradingEnabled + _earlyPenaltyTime >= _timestamp() ? _totalPenaltyTxTax : _totalTxTax);
    }
  }

  /// @notice Tax applied for buying
  /// @dev Taking in consideration your wallet address
  function buyTax() external view returns (uint24) {
    return buyTax(msg.sender);
  }

  /// @notice Tax applied for buying
  /// @param from Buyer's address
  function buyTax(address from) public view returns (uint24) {
    if (_suspendTaxes) { return 0; }

    unchecked {
      return from == address(this) || _whitelisted[from] || from == _dex.pair ? 0 : (_holder[from].penalty || _tradingEnabled + _earlyPenaltyTime >= _timestamp() ? _totalPenaltyBuyTax : _totalBuyTax);
    }
  }
  /// @notice Tax applied for selling
  /// @dev Taking in consideration your wallet address
  function sellTax() external view returns (uint24) {
    return sellTax(msg.sender);
  }

  /// @notice Tax applied for selling
  /// @param to Seller's address
  function sellTax(address to) public view returns (uint24) {
    if (_suspendTaxes) { return 0; }

    unchecked {
      return to == address(this) || _whitelisted[to] || to == _dex.pair || to == _dex.router ? 0 : (_holder[to].penalty || _tradingEnabled + _earlyPenaltyTime >= _timestamp() ? _totalPenaltySellTax : _totalSellTax);
    }
  }

  /// @notice List of all tax beneficiaries and their assigned percentage, according to type of transfer
  /// @custom:return `list[].account` Beneficiary address
  /// @custom:return `list[].percent[3]` Index 0 is for tx tax, 1 is for buy tax, 2 is for sell tax, multiplied by denominator
  /// @custom:return `list[].penalty[3]` Index 0 is for tx penalty, 1 is for buy penalty, 2 is for sell penalty, multiplied by denominator
  function listTaxBeneficiaries() external view returns (taxBeneficiaryView[] memory list) {
    list = new taxBeneficiaryView[](6);

    unchecked {
      for (uint8 i; i < 6; i++) { list[i] = taxBeneficiaryView(_taxBeneficiary[i].account, _taxBeneficiary[i].percent, _taxBeneficiary[i].penalty, _taxBeneficiary[i].unclaimed); }
    }
  }

  /// @notice Sets a tax beneficiary
  /// @dev Maximum of 5 wallets can be assigned
  /// @dev Slot 0 is reserved for ChainFactory revenue
  /// @param slot Slot number (1 to 5)
  /// @param account Beneficiary address
  /// @param percent[3] Index 0 is for tx tax, 1 is for buy tax, 2 is for sell tax, multiplied by denominator
  /// @param penalty[3] Index 0 is for tx penalty, 1 is for buy penalty, 2 is for sell penalty, multiplied by denominator
  function setTaxBeneficiary(uint8 slot, address account, uint24[3] memory percent, uint24[3] memory penalty) external onlyOwner {
    require(!_renounced.Taxable);
    require(slot >= 1 && slot <= 5, "Reserved");

    _setTaxBeneficiary(slot, account, percent, penalty);
  }

  function _setTaxBeneficiary(uint8 slot, address account, uint24[3] memory percent, uint24[3] memory penalty) internal {
    require(slot <= 5);
    require(account != address(this) && account != address(0));

    taxBeneficiary storage taxBeneficiarySlot = _taxBeneficiary[slot];

    if (slot > 0 && account == address(0xdEaD) && taxBeneficiarySlot.unclaimed > 0) { revert("Unclaimed taxes"); }

    unchecked {
      _totalTxTax += percent[0] - taxBeneficiarySlot.percent[0];
      _totalBuyTax += percent[1] - taxBeneficiarySlot.percent[1];
      _totalSellTax += percent[2] - taxBeneficiarySlot.percent[2];
      _totalPenaltyTxTax += penalty[0] - taxBeneficiarySlot.penalty[0];
      _totalPenaltyBuyTax += penalty[1] - taxBeneficiarySlot.penalty[1];
      _totalPenaltySellTax += penalty[2] - taxBeneficiarySlot.penalty[2];

      require(_totalTxTax <= 25 * _denominator && ((_totalBuyTax <= 25 * _denominator && _totalSellTax <= 25 * _denominator) && (_totalBuyTax + _totalSellTax <= 25 * _denominator)), "High Tax");
      require(_totalPenaltyTxTax <= 90 * _denominator && _totalPenaltyBuyTax <= 90 * _denominator && _totalPenaltySellTax <= 90 * _denominator, "Invalid Penalty");

      taxBeneficiarySlot.account = account;
      taxBeneficiarySlot.percent = percent;

      if (_initialized && slot > 0) { _setTaxBeneficiary(0, _taxBeneficiary[0].account, [ uint24(0), uint24(0), uint24(0) ], [ _taxBeneficiary[0].penalty[0] + uint24((penalty[0] * 10 / 100) - (taxBeneficiarySlot.penalty[0] * 10 / 100)), _taxBeneficiary[0].penalty[1] + uint24((penalty[1] * 10 / 100) - (taxBeneficiarySlot.penalty[1] * 10 / 100)), _taxBeneficiary[0].penalty[2] + uint24((penalty[2] * 10 / 100) - (taxBeneficiarySlot.penalty[2] * 10 / 100)) ]); }

      taxBeneficiarySlot.penalty = penalty;
    }

    if (!taxBeneficiarySlot.exists) { taxBeneficiarySlot.exists = true; }

    emit SetTaxBeneficiary(slot, account, percent, penalty);
  }

  /// @notice Triggers the tax distribution
  /// @dev Will only be executed if there is no ongoing swap or tax distribution
  function autoTaxDistribute() external {
    require(msg.sender == _owner || _whitelisted[msg.sender], "Unauthorized");
    require(!_swapping && !_distributing);

    _autoTaxDistribute();
  }

  function _autoTaxDistribute() internal lockDistributing {
    if (_totalTaxUnclaimed == 0) { return; }

    unchecked {
      uint256 distributedTaxes;

      for (uint8 i; i < 6; i++) {
        taxBeneficiary storage taxBeneficiarySlot = _taxBeneficiary[i];
        address account = taxBeneficiarySlot.account;

        if (taxBeneficiarySlot.unclaimed == 0 || account == address(0xdEaD) || account == _dex.pair) { continue; }

        uint256 unclaimed = _percentage(address(_taxToken) == address(this) ? _amountForTaxDistribution : _amountSwappedForTaxDistribution, (100 * uint256(_denominator) * taxBeneficiarySlot.unclaimed) / _totalTaxUnclaimed);
        uint256 _distributedTaxes = _distribute(account, unclaimed);

        if (_distributedTaxes > 0) {
          taxBeneficiarySlot.unclaimed -= _distributedTaxes;
          distributedTaxes += _distributedTaxes;
        }
      }

      _lastTaxDistribution = _timestamp();

      if (distributedTaxes > 0) {
        _totalTaxUnclaimed -= distributedTaxes;

        emit TaxDistributed(distributedTaxes);
      }
    }
  }

  function _distribute(address account, uint256 unclaimed) private returns (uint256) {
    if (unclaimed == 0) { return 0; }

    unchecked {
      if (address(_taxToken) == address(this)) {
        if (_balance[account] + unclaimed > _maxBalanceAmount && !_whitelisted[account]) {
          unclaimed = _maxBalanceAmount > _balance[account] ? _maxBalanceAmount - _balance[account] : 0;

          if (unclaimed == 0) { return 0; }
        }

        super._transfer(address(this), account, unclaimed);

        _amountForTaxDistribution -= unclaimed;
      } else {
        uint256 percent = (100 * uint256(_denominator) * unclaimed) / _amountSwappedForTaxDistribution;
        uint256 amount;

        if (address(_taxToken) == _dex.WETH) {
          amount = _percentage(_ethForTaxDistribution, percent);

          (bool success, ) = payable(account).call{ value: amount, gas: 30000 }("");

          if (!success) { return 0; }

          _ethForTaxDistribution -= amount;
        } else {
          amount = _percentage(_tokensForTaxDistribution[address(_taxToken)], percent);

          try _taxToken.transfer(account, amount) { _tokensForTaxDistribution[address(_taxToken)] -= amount; } catch { return 0; }
        }

        _amountSwappedForTaxDistribution -= unclaimed;
      }
    }

    return unclaimed;
  }

  /// @notice Suspend or reinstate tax collection
  /// @dev Also applies to early penalties
  /// @param status True to suspend, False to reinstate existent taxes
  function suspendTaxes(bool status) external onlyOwner {
    require(!_renounced.Taxable);

    _suspendTaxes = status;
  }

  /// @notice Checks if tax collection is currently suspended
  function taxesSuspended() external view returns (bool) {
    return _suspendTaxes;
  }

  /// @notice Removes the penalty status of a wallet
  /// @param account Address to depenalize
  function removePenalty(address account) external onlyOwner {
    require(!_renounced.Taxable);

    _holder[account].penalty = false;
  }

  /// @notice Check if a wallet is penalized due to an early transaction
  /// @param account Address to check
  function isPenalized(address account) external view returns (bool) {
    return _holder[account].penalty;
  }

  /// @notice Returns the period of time during which early buyers will be penalized from the time trading was enabled
  function getEarlyPenaltyTime() external view returns (uint32) {
    return _earlyPenaltyTime;
  }

  /// @notice Defines the period of time during which early buyers will be penalized from the time trading was enabled
  /// @dev Must be less or equal to 1 hour
  /// @param time Time, in seconds
  function setEarlyPenaltyTime(uint32 time) external onlyOwner {
    require(!_renounced.Taxable);
    require(time <= 600);

    _setEarlyPenaltyTime(time);
  }

  function _setEarlyPenaltyTime(uint32 time) internal {
    _earlyPenaltyTime = time;

    emit SetEarlyPenaltyTime(time);
  }
}

File 9 of 14 : CF_Burnable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_ERC20.sol";

abstract contract CF_Burnable is CF_Common, CF_ERC20 {
  /// @notice Total amount of tokens burned so far
  function totalBurned() external view returns (uint256) {
    return _totalBurned;
  }

  function burn(uint256 amount) external {
    _burn(msg.sender, amount);
  }

  function burnFrom(address account, uint256 amount) external {
    _spendAllowance(account, msg.sender, amount);
    _burn(account, amount);
  }

  function _burn(address account, uint256 amount) internal virtual {
    require(_balance[account] >= amount, "Exceeds balance");

    unchecked {
      _balance[account] -= amount;
      _totalSupply -= amount;
      _totalBurned += amount;
    }

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

File 10 of 14 : CF_Cooldown.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";

abstract contract CF_Cooldown is CF_Common, CF_Ownable {
  event SetCooldown(uint8 count, uint32 time, uint32 period);
  event RenouncedCooldown();

  /// @notice Permanently renounce and prevent the owner from being able to update cooldown features
  /// @dev Existing settings will continue to be effective
  function renounceCooldown() external onlyOwner {
    _renounced.Cooldown = true;

    emit RenouncedCooldown();
  }

  /// @notice Returns current cooldown settings
  /// @return count Number of transfers
  /// @return time Seconds during which the number of transfers will be taken into account
  /// @return period Seconds during which the wallet will be in cooldown (0 means disabled)
  function getCooldownSettings() external view returns (uint8 count, uint32 time, uint32 period) {
    return (_cooldownTriggerCount, _cooldownTriggerTime, _cooldownPeriod);
  }

  /// @notice Set cooldown settings
  /// @param count Number of transfers
  /// @param time Seconds during which the number of transfers will be taken into account
  /// @param period Seconds during which the wallet will be in cooldown (less or equal to 1 week, 0 to disable)
  function setCooldown(uint8 count, uint32 time, uint32 period) external onlyOwner {
    require(!_renounced.Cooldown);

    _setCooldown(count, time, period);
  }

  function _setCooldown(uint8 count, uint32 time, uint32 period) internal {
    require(count > 1 && time > 5 && period <= 1 weeks);

    _cooldownTriggerCount = count;
    _cooldownTriggerTime = time;
    _cooldownPeriod = period;

    emit SetCooldown(count, time, period);
  }

  function _cooldown(address account) internal {
    unchecked {
      _holder[account].cooldown = _timestamp() + _cooldownPeriod;
    }
  }

  /// @notice Removes the cooldown status of a wallet
  /// @param account Address to unfreeze
  function removeCooldown(address account) external onlyOwner {
    require(!_renounced.Cooldown);

    _holder[account].count = 0;
    _holder[account].start = 0;
    _holder[account].cooldown = 0;
  }

  /// @notice Check if a wallet is currently in cooldown
  /// @param account Address to check
  /// @return Remaining seconds in cooldown
  function remainingCooldownTime(address account) public view returns (uint32) {
    if (_cooldownPeriod == 0 || _holder[account].cooldown < _timestamp()) { return 0; }

    unchecked {
      return _holder[account].cooldown - _timestamp();
    }
  }
}

File 11 of 14 : CF_Whitelist.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";

abstract contract CF_Whitelist is CF_Common, CF_Ownable {
  event Whitelisted(address indexed account, bool status);
  event RenouncedWhitelist();

  /// @notice Permanently renounce and prevent the owner from being able to update the whitelist
  /// @dev Existing entries will continue to be effective
  function renounceWhitelist() external onlyOwner {
    _renounced.Whitelist = true;

    emit RenouncedWhitelist();
  }

  /// @notice Check if an address is whitelisted
  /// @param account Address to check
  function isWhitelisted(address account) external view returns (bool) {
    return _whitelisted[account];
  }

  /// @notice Add or remove an address from the whitelist
  /// @param status True for adding, False for removing
  function whitelist(address account, bool status) public onlyOwner {
    _whitelist(account, status);
  }

  function _whitelist(address account, bool status) internal {
    require(!_renounced.Whitelist);
    require(account != address(0) && account != address(0xdEaD));
    require(account != _dex.router && account != _dex.pair, "DEX router and pair are privileged");


    _whitelisted[account] = status;

    emit Whitelisted(account, status);
  }

  /// @notice Add or remove multiple addresses from the whitelist
  /// @param status True for adding, False for removing
  function whitelist(address[] calldata accounts, bool status) external onlyOwner {
    unchecked {
      uint256 cnt = accounts.length;

      for (uint256 i; i < cnt; i++) { _whitelist(accounts[i], status); }
    }
  }

  function _initialWhitelist(address[3] memory accounts) internal {
    require(!_initialized);

    unchecked {
      for (uint256 i; i < 3; i++) { _whitelist(accounts[i], true); }
    }
  }
}

File 12 of 14 : CF_MaxBalance.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";

abstract contract CF_MaxBalance is CF_Common, CF_Ownable {
  event SetMaxBalancePercent(uint24 percent);
  event RenouncedMaxBalance();

  /// @notice Permanently renounce and prevent the owner from being able to update the max. balance
  /// @dev Existing settings will continue to be effective
  function renounceMaxBalance() external onlyOwner {
    _renounced.MaxBalance = true;

    emit RenouncedMaxBalance();
  }

  /// @notice Percentage of the max. balance per wallet, depending on total supply
  function getMaxBalancePercent() external view returns (uint24) {
    return _maxBalancePercent;
  }

  /// @notice Set the max. percentage of a wallet balance, depending on total supply
  /// @param percent Desired percentage, multiplied by denominator (min. 0.1% of total supply)
  function setMaxBalancePercent(uint24 percent) external onlyOwner {
    require(!_renounced.MaxBalance);

    _setMaxBalancePercent(percent);

    emit SetMaxBalancePercent(percent);
  }

  function _setMaxBalancePercent(uint24 percent) internal {
    unchecked {
      require(percent >= 100 && percent <= 100 * _denominator);
    }

    _maxBalancePercent = percent;
    _maxBalanceAmount = _percentage(_totalSupply, uint256(percent));

    if (!_initialized) { emit SetMaxBalancePercent(percent); }
  }
}

File 13 of 14 : CF_DEXRouterV2.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";
import "./CF_ERC20.sol";

abstract contract CF_DEXRouterV2 is CF_Common, CF_Ownable, CF_ERC20 {
  event AddedLiquidity(uint256 tokenAmount, uint256 ethAmount, uint256 liquidity);
  event SwappedTokensForTokens(address token, uint256 token0Amount, uint256 token1Amount);
  event SwappedTokensForNative(uint256 tokenAmount, uint256 ethAmount);
  event SetDEXRouterV2(address indexed router, address indexed pair);
  event TradingEnabled();
  event RenouncedDEXRouterV2();

  modifier lockSwapping {
    _swapping = true;
    _;
    _swapping = false;
  }

  /// @notice Permanently renounce and prevent the owner from being able to update the DEX features
  /// @dev Existing settings will continue to be effective
  function renounceDEXRouterV2() external onlyOwner {
    _renounced.DEXRouterV2 = true;

    emit RenouncedDEXRouterV2();
  }

  function _setDEXRouterV2(address router, address token0) internal {
    IDEXRouterV2 _router = IDEXRouterV2(router);
    IDEXFactoryV2 factory = IDEXFactoryV2(_router.factory());
    address pair = factory.createPair(address(this), token0);

    _dex = DEXRouterV2(router, pair, token0, _router.WETH(), address(0));

    emit SetDEXRouterV2(router, _dex.pair);
  }

  /// @notice Returns the DEX router currently in use
  function getDEXRouterV2() external view returns (address) {
    return _dex.router;
  }

  /// @notice Returns the trading pair
  function getDEXPairV2() external view returns (address) {
    return _dex.pair;
  }

  /// @notice Checks whether the token can be traded through the assigned DEX
  function isTradingEnabled() external view returns (bool) {
    return _tradingEnabled > 0;
  }

  /// @notice Returns address of the LP tokens receiver
  /// @dev Used for automated liquidity injection through taxes
  function getDEXLPTokenReceiver() external view returns (address) {
    return _dex.receiver;
  }

  /// @notice Set the address of the LP tokens receiver
  /// @dev Used for automated liquidity injection through taxes
  function setDEXLPTokenReceiver(address receiver) external onlyOwner {
    _setDEXLPTokenReceiver(receiver);
  }

  function _setDEXLPTokenReceiver(address receiver) internal {
    _dex.receiver = receiver;
  }

  /// @notice Checks the status of the auto-swapping feature
  function isAutoSwapEnabled() external view returns (bool) {
    return _autoSwapEnabled;
  }

  /// @notice Returns the percentage range of the total supply over which the auto-swap will operate when accumulating taxes in the contract balance
  function getAutoSwapPercent() external view returns (uint24 min, uint24 max) {
    return (_minAutoSwapPercent, _maxAutoSwapPercent);
  }

  /// @notice Sets the percentage range of the total supply over which the auto-swap will operate when accumulating taxes in the contract balance
  /// @param min Desired min. percentage to trigger the auto-swap, multiplied by denominator (0.001% to 1% of total supply)
  /// @param max Desired max. percentage to limit the auto-swap, multiplied by denominator (0.001% to 1% of total supply)
  function setAutoSwapPercent(uint24 min, uint24 max) external onlyOwner {
    require(!_renounced.DEXRouterV2);
    require(min >= 1 && min <= 1000, "0.001% to 1%");
    require(max >= min && max <= 1000, "0.001% to 1%");

    _setAutoSwapPercent(min, max);
  }

  function _setAutoSwapPercent(uint24 min, uint24 max) internal {
    _minAutoSwapPercent = min;
    _maxAutoSwapPercent = max;
    _minAutoSwapAmount = _percentage(_totalSupply, uint256(min));
    _maxAutoSwapAmount = _percentage(_totalSupply, uint256(max));
  }

  /// @notice Enables or disables the auto-swap function
  /// @param status True to enable, False to disable
  function enableAutoSwap(bool status) external onlyOwner {
    require(!_renounced.DEXRouterV2);
    require(!status || _dex.router != address(0), "No DEX");

    _autoSwapEnabled = status;
  }

  /// @notice Swaps the assigned amount to inject liquidity and prepare collected taxes for its distribution
  /// @dev Will only be executed if there is no ongoing swap or tax distribution and the min. threshold has been reached
  function autoSwap() external {
    require(_autoSwapEnabled && !_swapping && !_distributing);

    _autoSwap(false);
  }

  /// @notice Swaps the assigned amount to inject liquidity and prepare collected taxes for its distribution
  /// @dev Will only be executed if there is no ongoing swap or tax distribution and the min. threshold has been reached unless forced
  /// @param force Ignore the min. and max. threshold amount
  function autoSwap(bool force) external {
    require(msg.sender == _owner || _whitelisted[msg.sender], "Unauthorized");
    require((force || _autoSwapEnabled) && !_swapping && !_distributing);

    _autoSwap(force);
  }

  function _autoSwap(bool force) internal lockSwapping {
    if (!force && !_autoSwapEnabled) { return; }

    unchecked {
      uint256 amountForLiquidityToSwap = _amountForLiquidity > 0 ? _amountForLiquidity / 2 : 0;
      uint256 amountForTaxDistributionToSwap = (address(_taxToken) == _dex.WETH ? _amountForTaxDistribution : 0);
      uint256 amountToSwap = amountForTaxDistributionToSwap + amountForLiquidityToSwap;

      if (!force && amountToSwap > _maxAutoSwapAmount) {
        amountForLiquidityToSwap = amountForLiquidityToSwap > 0 ? _percentage(_maxAutoSwapAmount, (100 * uint256(_denominator) * amountForLiquidityToSwap) / amountToSwap) : 0;
        amountForTaxDistributionToSwap = amountForTaxDistributionToSwap > 0 ? _percentage(_maxAutoSwapAmount, (100 * uint256(_denominator) * amountForTaxDistributionToSwap) / amountToSwap) : 0;
        amountToSwap = amountForTaxDistributionToSwap + amountForLiquidityToSwap;
      }

      if ((force || amountToSwap >= _minAutoSwapAmount) && _balance[address(this)] >= amountToSwap + amountForLiquidityToSwap) {
        uint256 ethBalance = address(this).balance;
        address[] memory pathToSwapExactTokensForNative = new address[](2);
        pathToSwapExactTokensForNative[0] = address(this);
        pathToSwapExactTokensForNative[1] = _dex.WETH;

        _approve(address(this), _dex.router, amountToSwap);

        try IDEXRouterV2(_dex.router).swapExactTokensForETHSupportingFeeOnTransferTokens(amountToSwap, 0, pathToSwapExactTokensForNative, address(this), block.timestamp) {
          if (_amountForLiquidity > 0) { _amountForLiquidity -= amountForLiquidityToSwap; }

          uint256 ethAmount = address(this).balance - ethBalance;

          emit SwappedTokensForNative(amountToSwap, ethAmount);

          if (ethAmount > 0) {
            _ethForLiquidity += _percentage(ethAmount, (100 * uint256(_denominator) * amountForLiquidityToSwap) / amountToSwap);

            if (address(_taxToken) == _dex.WETH) {
              _ethForTaxDistribution += _percentage(ethAmount, (100 * uint256(_denominator) * amountForTaxDistributionToSwap) / amountToSwap);
              _amountSwappedForTaxDistribution += amountForTaxDistributionToSwap;
              _amountForTaxDistribution -= amountForTaxDistributionToSwap;
            }
          }
        } catch {
          _approve(address(this), _dex.router, 0);
        }
      }

      if (address(_taxToken) != address(this) && address(_taxToken) != _dex.WETH) {
        amountForTaxDistributionToSwap = _amountForTaxDistribution;

        if (!force && amountForTaxDistributionToSwap > _maxAutoSwapAmount) { amountForTaxDistributionToSwap = _maxAutoSwapAmount; }

        if ((force || amountForTaxDistributionToSwap >= _minAutoSwapAmount) && _balance[address(this)] >= amountForTaxDistributionToSwap) {
          uint256 tokenAmount = _swapTokensForTokens(_taxToken, amountForTaxDistributionToSwap);

          if (tokenAmount > 0) {
            _tokensForTaxDistribution[address(_taxToken)] += tokenAmount;
            _amountSwappedForTaxDistribution += amountForTaxDistributionToSwap;
            _amountForTaxDistribution -= amountForTaxDistributionToSwap;
          }
        }
      }
    }

    _addLiquidity(force);
    _lastSwap = _timestamp();
  }

  function _swapTokensForTokens(IERC20 token, uint256 amount) private returns (uint256 tokenAmount) {
    uint256 tokenBalance = token.balanceOf(address(this));
    address[] memory pathToSwapExactTokensForTokens = new address[](3);
    pathToSwapExactTokensForTokens[0] = address(this);
    pathToSwapExactTokensForTokens[1] = _dex.WETH;
    pathToSwapExactTokensForTokens[2] = address(token);

    _approve(address(this), _dex.router, amount);

    try IDEXRouterV2(_dex.router).swapExactTokensForTokensSupportingFeeOnTransferTokens(amount, 0, pathToSwapExactTokensForTokens, address(this), block.timestamp) {
      tokenAmount = token.balanceOf(address(this)) - tokenBalance;

      emit SwappedTokensForTokens(address(token), amount, tokenAmount);
    } catch {
      _approve(address(this), _dex.router, 0);
    }
  }

  function _addLiquidity(bool force) private {
    if (!force && (_amountForLiquidity < _minAutoAddLiquidityAmount || _ethForLiquidity == 0)) { return; }

    unchecked {
      uint256 amountForLiquidityToAdd = !force && _amountForLiquidity > _maxAutoAddLiquidityAmount ? _maxAutoAddLiquidityAmount : _amountForLiquidity;
      uint256 ethForLiquidityToAdd = !force && _amountForLiquidity > _maxAutoAddLiquidityAmount ? _percentage(_ethForLiquidity, 100 * uint256(_denominator) * (_maxAutoAddLiquidityAmount / _amountForLiquidity)) : _ethForLiquidity;

      _approve(address(this), _dex.router, amountForLiquidityToAdd);

      try IDEXRouterV2(_dex.router).addLiquidityETH{ value: ethForLiquidityToAdd }(address(this), amountForLiquidityToAdd, 0, 0, _dex.receiver, block.timestamp) returns (uint256 tokenAmount, uint256 ethAmount, uint256 liquidity) {
        emit AddedLiquidity(tokenAmount, ethAmount, liquidity);

        _amountForLiquidity -= amountForLiquidityToAdd;
        _ethForLiquidity -= ethForLiquidityToAdd;
      } catch {
        _approve(address(this), _dex.router, 0);
      }
    }
  }

  /// @notice Returns the percentage range of the total supply over which the auto add liquidity will operate when accumulating taxes in the contract balance
  /// @dev Applies only if a Tax Beneficiary is the liquidity pool
  function getAutoAddLiquidityPercent() external view returns (uint24 min, uint24 max) {
    return (_minAutoAddLiquidityPercent, _maxAutoAddLiquidityPercent);
  }

  /// @notice Sets the percentage range of the total supply over which the auto add liquidity will operate when accumulating taxes in the contract balance
  /// @param min Desired min. percentage to trigger the auto add liquidity, multiplied by denominator (0.01% to 100% of total supply)
  /// @param max Desired max. percentage to limit the auto add liquidity, multiplied by denominator (0.01% to 100% of total supply)
  function setAutoAddLiquidityPercent(uint24 min, uint24 max) external onlyOwner {
    require(!_renounced.DEXRouterV2);
    require(min >= 10 && min <= 100 * _denominator, "0.01% to 100%");
    require(max >= min && max <= 100 * _denominator, "0.01% to 100%");

    _setAutoAddLiquidityPercent(min, max);
  }

  function _setAutoAddLiquidityPercent(uint24 min, uint24 max) internal {
    _minAutoAddLiquidityPercent = min;
    _maxAutoAddLiquidityPercent = max;
    _minAutoAddLiquidityAmount = _percentage(_totalSupply, uint256(min));
    _maxAutoAddLiquidityAmount = _percentage(_totalSupply, uint256(max));
  }

  /// @notice Returns the token for tax distribution
  function getTaxToken() external view returns (address) {
    return address(_taxToken);
  }

  function _setTaxToken(address token) internal {
    require((!_initialized && token == address(0)) || token == address(this) || token == _dex.WETH || IDEXFactoryV2(IDEXRouterV2(_dex.router).factory()).getPair(_dex.WETH, token) != address(0), "No Pair");

    _taxToken = IERC20(token == address(0) ? address(this) : token);
  }

  /// @notice Enables the trading capability via the DEX set up
  /// @dev Once enabled, it cannot be reverted
  function enableTrading() external onlyOwner {
    require(!_renounced.DEXRouterV2);
    require(_tradingEnabled == 0, "Already enabled");

    _tradingEnabled = _timestamp();

    emit TradingEnabled();
  }
}

File 14 of 14 : CF_Recoverable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.25;

import "./CF_Common.sol";
import "./CF_Ownable.sol";

abstract contract CF_Recoverable is CF_Common, CF_Ownable {
  /// @notice Recovers a misplaced amount of an ERC-20 token sitting in the contract balance
  /// @dev Beware of scam tokens!
  /// @dev Note that if the token of this contract is specified, amounts allocated for tax distribution and liquidity are reserved
  /// @param token Address of the ERC-20 token
  /// @param to Recipient
  /// @param amount Amount to be transferred
  function recoverERC20(address token, address to, uint256 amount) external onlyOwner {
    unchecked {
      uint256 balance = IERC20(token).balanceOf(address(this));
      uint256 allocated = token == address(this) ? _amountForTaxDistribution + _amountForLiquidity : (address(_taxToken) == token ? _tokensForTaxDistribution[address(_taxToken)] : 0);

      require(balance - (allocated >= balance ? balance : allocated) >= amount, "Exceeds balance");
    }

    IERC20(token).transfer(to, amount);
  }

  /// @notice Recovers a misplaced amount of native tokens sitting in the contract balance
  /// @dev Note that if the reflection token is the wrapped native, amounts allocated for tax distribution and/or liquidity are reserved
  /// @param to Recipient
  /// @param amount Amount of native tokens to be transferred
  function recoverNative(address payable to, uint256 amount) external onlyOwner {
    unchecked {
      uint256 balance = address(this).balance;
      uint256 allocated = address(_taxToken) == _dex.WETH ? _ethForTaxDistribution : 0;

      require(balance - (allocated >= balance ? balance : allocated) >= amount, "Exceeds balance");
    }

    (bool success, ) = to.call{ value: amount }("");

    require(success);
  }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidity","type":"uint256"}],"name":"AddedLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedCooldown","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedDEXRouterV2","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedMaxBalance","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedMaxTx","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedTaxable","type":"event"},{"anonymous":false,"inputs":[],"name":"RenouncedWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"count","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"time","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"period","type":"uint32"}],"name":"SetCooldown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"address","name":"pair","type":"address"}],"name":"SetDEXRouterV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"time","type":"uint32"}],"name":"SetEarlyPenaltyTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"percent","type":"uint24"}],"name":"SetMaxBalancePercent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"percent","type":"uint24"}],"name":"SetMaxTxPercent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"slot","type":"uint8"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint24[3]","name":"percent","type":"uint24[3]"},{"indexed":false,"internalType":"uint24[3]","name":"penalty","type":"uint24[3]"}],"name":"SetTaxBeneficiary","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"SwappedTokensForNative","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"token0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amount","type":"uint256"}],"name":"SwappedTokensForTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TaxDistributed","type":"event"},{"anonymous":false,"inputs":[],"name":"TradingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"Whitelisted","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"force","type":"bool"}],"name":"autoSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoTaxDistribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"buyTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"enableAutoSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAutoAddLiquidityPercent","outputs":[{"internalType":"uint24","name":"min","type":"uint24"},{"internalType":"uint24","name":"max","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutoSwapPercent","outputs":[{"internalType":"uint24","name":"min","type":"uint24"},{"internalType":"uint24","name":"max","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCooldownSettings","outputs":[{"internalType":"uint8","name":"count","type":"uint8"},{"internalType":"uint32","name":"time","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDEXLPTokenReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDEXPairV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDEXRouterV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEarlyPenaltyTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxBalancePercent","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxTxPercent","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"info","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"string","name":"version","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAutoSwapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPenalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listTaxBeneficiaries","outputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint24[3]","name":"percent","type":"uint24[3]"},{"internalType":"uint24[3]","name":"penalty","type":"uint24[3]"},{"internalType":"uint256","name":"unclaimed","type":"uint256"}],"internalType":"struct CF_Taxable.taxBeneficiaryView[]","name":"list","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"remainingCooldownTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removePenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceDEXRouterV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceMaxBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceMaxTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceTaxable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounced","outputs":[{"internalType":"bool","name":"Whitelist","type":"bool"},{"internalType":"bool","name":"Cooldown","type":"bool"},{"internalType":"bool","name":"MaxTx","type":"bool"},{"internalType":"bool","name":"MaxBalance","type":"bool"},{"internalType":"bool","name":"DEXRouterV2","type":"bool"},{"internalType":"bool","name":"Taxable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"sellTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"min","type":"uint24"},{"internalType":"uint24","name":"max","type":"uint24"}],"name":"setAutoAddLiquidityPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"min","type":"uint24"},{"internalType":"uint24","name":"max","type":"uint24"}],"name":"setAutoSwapPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"count","type":"uint8"},{"internalType":"uint32","name":"time","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"}],"name":"setCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setDEXLPTokenReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"time","type":"uint32"}],"name":"setEarlyPenaltyTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"percent","type":"uint24"}],"name":"setMaxBalancePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"percent","type":"uint24"}],"name":"setMaxTxPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"slot","type":"uint8"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint24[3]","name":"percent","type":"uint24[3]"},{"internalType":"uint24[3]","name":"penalty","type":"uint24[3]"}],"name":"setTaxBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"suspendTaxes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxesSuspended","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTaxCollected","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"txTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"txTax","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c060405234801561000f575f80fd5b50604080518082019091526008815267536f6c617220414960c01b602082015260219061003c90826112ad565b5060408051808201909152600581526429a7a620a960d91b602082015260229061006690826112ad565b50601260a0526a52b7d2dcc80cd2e4000000600a5561009873a26bd8bcb6904533b9eff88e5c5563c60da614ed61033b565b6100b973a26bd8bcb6904533b9eff88e5c5563c60da614ed620186a061038c565b6100eb737a250d5630b4cf539739df2c5dacb4c659f2488d73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2610406565b6100f560b461062c565b6100fe30610687565b6007805460ff19166001179055610117603260fa61082f565b6008805468ffffffffffff0000001916680186a0000064000000179055600a54620186a0606482028190046010559081020460115560408051606080820183525f8083526020808401829052838501829052845192830185528183526107d0908301819052938201939093526101a39291738881d9869ac7c7840971caac043d7f4d144abd1091610890565b60408051606080820183525f80835261138860208085018290528486019190915284519283018552908252614e20908201819052928101929092526102009160019173a26bd8bcb6904533b9eff88e5c5563c60da614ed91610890565b6040805160608101825273a26bd8bcb6904533b9eff88e5c5563c60da614ed8152731fe6a48678d757df6bc7497520d4e432cff5f96660208201527374001dcff64643b76ce4919af4dcd83da6fe1e029181019190915261026090610e02565b61026e6005610e1080610e46565b6102796103e8610f18565b6102846107d0610fae565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60216040516102b4919061136c565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f198184030181529190528051602090910120602355600160805261149d565b602080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60805115610398575f80fd5b5f6103b0600a548362ffffff1661104460201b60201c565b6001600160a01b0384165f8181526020818152604080832085905551848152939450919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b5f8290505f816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610447573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061046b91906113de565b6040516364e329cb60e11b81523060048201526001600160a01b0385811660248301529192505f9183169063c9c65396906044016020604051808303815f875af11580156104bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104df91906113de565b90506040518060a00160405280866001600160a01b03168152602001826001600160a01b03168152602001856001600160a01b03168152602001846001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015610555573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061057991906113de565b6001600160a01b0390811682525f60209283018190528351601b80549184166001600160a01b031992831617905592840151601c805491841691851682179055604080860151601d80549186169187169190911790556060860151601e8054918616918716919091179055608090950151601f8054918516919095161790935592519192908816917f068ccb581b10310dd98c3f0999214bce7660c126ffa63a399df0287144582d579190a35050505050565b6008805463ffffffff60a81b1916600160a81b63ffffffff8416908102919091179091556040519081527f703cced883e2faf6a2d5c676ef2f9dd7cfafa0acecee468ece9314ecf462ba91906020015b60405180910390a150565b60805115801561069e57506001600160a01b038116155b806106b157506001600160a01b03811630145b806106c95750601e546001600160a01b038281169116145b806107ba5750601b546040805163c45a015560e01b815290515f926001600160a01b03169163c45a01559160048083019260209291908290030181865afa158015610716573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073a91906113de565b601e5460405163e6a4390560e01b81526001600160a01b039182166004820152848216602482015291169063e6a43905906044016020604051808303815f875af115801561078a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ae91906113de565b6001600160a01b031614155b6107f55760405162461bcd60e51b81526020600482015260076024820152662737902830b4b960c91b60448201526064015b60405180910390fd5b6001600160a01b0381161561080a578061080c565b305b601a80546001600160a01b0319166001600160a01b039290921691909117905550565b600780546001600160e81b0316600160e81b62ffffff858116918202929092179092556008805462ffffff1916918416919091179055600a5461087691620186a091020490565b600e55600a54620186a062ffffff929092160204600f5550565b60058460ff1611156108a0575f80fd5b6001600160a01b03831630148015906108c157506001600160a01b03831615155b6108c9575f80fd5b60ff84165f81815260046020526040902090158015906108f357506001600160a01b03841661dead145b801561090257505f8160030154115b156109415760405162461bcd60e51b815260206004820152600f60248201526e556e636c61696d656420746178657360881b60448201526064016107ec565b60018101805484516007805462ffffff60581b19811662ffffff9485169093036b0100000000000000000000008083048616919091018516810293841780845586546020808c015162ffffff60701b1990971665ffffffffffff60581b19909516949094176301000000918290048816909603600160701b9283900488160187169091029490941780845595546040808b015162ffffff60881b1989166601000000000000938490048916909103600160881b808b048a169190910189160290811780875560028b0180548d5162ffffff60a01b1990941665ffffffffffff60881b19909c169b909b179a8a16909203600160a01b918290048a1601891602989098178086558854948b015162ffffff60b81b198216979095048816909403600160b81b8086048916919091018816029586178086559754908a0151600160d01b988990048816929091048716900301851690950262ffffff60d01b1990931665ffffffffffff60b81b199091161791909117908190556161a89290041611801590610b2957506007546161a8600160701b90910462ffffff1611801590610afa57506007546161a8600160881b90910462ffffff1611155b8015610b2957506007546161a8600160701b820462ffffff908116600160881b90930481169290920190911611155b610b605760405162461bcd60e51b8152602060048201526008602482015267090d2ced040a8c2f60c31b60448201526064016107ec565b60075462015f90600160a01b90910462ffffff1611801590610b94575060075462015f90600160b81b90910462ffffff1611155b8015610bb2575060075462015f90600160d01b90910462ffffff1611155b610bf05760405162461bcd60e51b815260206004820152600f60248201526e496e76616c69642050656e616c747960881b60448201526064016107ec565b8054610100600160a81b0319166101006001600160a01b03861602178155610c1d60018201846003611169565b506080518015610c2f57505f8560ff16115b15610d99575f808052600460209081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec54604080516060808201835285825293810185905280820185905281519384019091526002850154610d9994936101009093046001600160a01b031692908190606490600a62ffffff9182160216046064895f6020020151600a0262ffffff1681610ccd57610ccd61141f565b5f808052600460208181525f805160206164a78339815191525462ffffff8082169690950496909603949094018316865260028c01548d850151928052908452630100000094859004831660649582048416600a9081028516879004938102851687900493909303018316938601939093526040808d01519501946601000000000000909304821681028216849004939202165f805260046020525f805160206164a78339815191525462ffffff66010000000000009091048116929091049290920301169052610890565b610da860028201836003611169565b50805460ff16610dbe57805460ff191660011781555b7f30034b3ad500b0a06492ddcfbb1eedee788dff84a77d76d5c3658ab517cec51a85858585604051610df39493929190611460565b60405180910390a15050505050565b60805115610e0e575f80fd5b5f5b6003811015610e4257610e3a828260038110610e2e57610e2e61140b565b6020020151600161104e565b600101610e10565b5050565b60018360ff16118015610e5f575060058263ffffffff16115b8015610e74575062093a808163ffffffff1611155b610e7c575f80fd5b6007805460ff60201b191664010000000060ff8616908102919091179091556008805463ffffffff60c81b1916600160c81b63ffffffff868116918202929092179092556009805463ffffffff19169185169182179055604080519384526020840192909252908201527f24b1343f86058af6b8e48d5f9ca6b4e206b72690500086e848cc587b2f4097149060600160405180910390a1505050565b60648162ffffff1610158015610f365750620186a062ffffff821611155b610f3e575f80fd5b6007805462ffffff60281b19166501000000000062ffffff841690810291909117909155600a54620186a0910204600c55608051610fab5760405162ffffff821681527ff01936354f43c5b49521c6c3fdc9740709976ee07acac3ebf79fbd6282cda1959060200161067c565b50565b60648162ffffff1610158015610fcc5750620186a062ffffff821611155b610fd4575f80fd5b6007805462ffffff60401b19166801000000000000000062ffffff841690810291909117909155600a54620186a0910204600d55608051610fab5760405162ffffff821681527fd03edfeea801807308f0e9302e347c8a12ad32508cae5bce26e9e2a3654158c99060200161067c565b620186a091020490565b60195460ff161561105d575f80fd5b6001600160a01b0382161580159061108057506001600160a01b03821661dead14155b611088575f80fd5b601b546001600160a01b038381169116148015906110b45750601c546001600160a01b03838116911614155b61110b5760405162461bcd60e51b815260206004820152602260248201527f44455820726f7574657220616e642070616972206172652070726976696c6567604482015261195960f21b60648201526084016107ec565b6001600160a01b0382165f81815260026020908152604091829020805460ff191685151590811790915591519182527fa54714518c5d275fdcd3d2a461e4858e4e8cb04fb93cd0bca9d6d34115f26440910160405180910390a25050565b6001830191839082156111f1579160200282015f5b838211156111c057835183826101000a81548162ffffff021916908362ffffff160217905550926020019260030160208160020104928301926001030261117e565b80156111ef5782816101000a81549062ffffff02191690556003016020816002010492830192600103026111c0565b505b506111fd929150611201565b5090565b5b808211156111fd575f8155600101611202565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061123d57607f821691505b60208210810361125b57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156112a857805f5260205f20601f840160051c810160208510156112865750805b601f840160051c820191505b818110156112a5575f8155600101611292565b50505b505050565b81516001600160401b038111156112c6576112c6611215565b6112da816112d48454611229565b84611261565b602080601f83116001811461130d575f84156112f65750858301515b5f19600386901b1c1916600185901b178555611364565b5f85815260208120601f198616915b8281101561133b5788860151825594840194600190910190840161131c565b508582101561135857878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f80835461137981611229565b6001828116801561139157600181146113a6576113d2565b60ff19841687528215158302870194506113d2565b875f526020805f205f5b858110156113c95781548a8201529084019082016113b0565b50505082870194505b50929695505050505050565b5f602082840312156113ee575f80fd5b81516001600160a01b0381168114611404575f80fd5b9392505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b805f5b600381101561145a57815162ffffff16845260209384019390910190600101611436565b50505050565b60ff851681526001600160a01b038416602082015261010081016114876040830185611433565b61149460a0830184611433565b95945050505050565b60805160a051614fd46114d35f395f81816105d1015261123601525f8181612b32015281816136110152613e8e0152614fd45ff3fe608060405260043610610404575f3560e01c806379cc679011610210578063c292158311610121578063da88d01a116100af578063f2fde38b11610076578063f2fde38b14610d01578063f3dc4f4814610d20578063f59c370814610d5c578063f7c3b38f14610d7b578063f7de0e5714610d9b57005b8063da88d01a14610c71578063dd62ed3e14610c90578063e92871f614610caf578063edd286cf14610cc3578063f2cda82e14610ce257005b8063d232c220116100f3578063d232c22014610b98578063d505accf14610c0b578063d6a018eb14610c2a578063d8454a8214610c49578063d89135cd14610c5d57005b8063c292158314610b3f578063c77e006d14610b5c578063c78fe0d414610b70578063cc1776d314610b8457005b806396ce07951161019e578063a4d8971a11610170578063a4d8971a14610aa4578063a5596b4f14610ac3578063a6cbe5c114610ae2578063a9059cbb14610b01578063be5e49b214610b2057005b806396ce079514610a3357806397a26b9e14610a475780639c5ef8d714610a71578063a457c2d714610a8557005b80638bf1acff116101e25780638bf1acff146109b05780638d8350ca146109c45780638da5cb5b146109e357806395101f9014610a0057806395d89b4114610a1f57005b806379cc6790146109355780637ecebe00146109545780638324c3b9146109885780638a8c523c1461099c57005b80633af32abf116103155780635b90fe66116102a357806370a082311161026a57806370a08231146108a5578063715018a6146108d957806375de1496146108ed578063770048511461090d57806379b3d4111461092157005b80635b90fe66146107f55780635bbb7a51146108275780635f641758146108465780636d5c1490146108655780636f05be971461088457005b806344b691ff116102e757806344b691ff1461074d5780634b7d9db41461076c5780634f7041a51461078357806354fd4d50146107ab5780635a0d4f88146107d857005b80633af32abf146106a75780633b7854de146106de5780633ed8a1691461070f57806342966c681461072e57005b80632623e9751161039257806332acf3de1161036457806332acf3de146105fb5780633644e5151461063a578063370158ea1461064e57806339137f8b14610674578063395093511461068857005b80632623e975146105385780632984207a146105575780632d6916be14610576578063313ce567146105be57005b8063095ea7b3116103d6578063095ea7b31461049e5780631171bda9146104bd57806318160ddd146104dc578063186488a8146104fa57806323b872dd1461051957005b806301b38af51461040d578063064a59d01461042c57806306fdde031461046057806307e9652c1461048157005b3661040b57005b005b348015610418575f80fd5b5061040b61042736600461488e565b610db8565b348015610437575f80fd5b50600854600160681b900463ffffffff1615155b60405190151581526020015b60405180910390f35b34801561046b575f80fd5b50610474610e35565b604051610457919061493b565b34801561048c575f80fd5b5060075462010000900460ff1661044b565b3480156104a9575f80fd5b5061044b6104b8366004614968565b610ec5565b3480156104c8575f80fd5b5061040b6104d7366004614992565b610edb565b3480156104e7575f80fd5b50600a545b604051908152602001610457565b348015610505575f80fd5b5061040b610514366004614a75565b61106d565b348015610524575f80fd5b5061044b610533366004614992565b611108565b348015610543575f80fd5b5061040b610552366004614acb565b611129565b348015610562575f80fd5b5061040b610571366004614af9565b6111c8565b348015610581575f80fd5b5060075460085460095460408051600160201b90940460ff168452600160c81b90920463ffffffff90811660208501521690820152606001610457565b3480156105c9575f80fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610457565b348015610606575f80fd5b5060075460085462ffffff600160e81b909204821691165b6040805162ffffff938416815292909116602083015201610457565b348015610645575f80fd5b506023546104ec565b348015610659575f80fd5b50610662611228565b60405161045796959493929190614b12565b34801561067f575f80fd5b5061040b6113b3565b348015610693575f80fd5b5061044b6106a2366004614968565b611414565b3480156106b2575f80fd5b5061044b6106c1366004614b76565b6001600160a01b03165f9081526002602052604090205460ff1690565b3480156106e9575f80fd5b50601f546001600160a01b03165b6040516001600160a01b039091168152602001610457565b34801561071a575f80fd5b5061040b610729366004614b91565b61142b565b348015610739575f80fd5b5061040b610748366004614baa565b6114b0565b348015610758575f80fd5b5061040b610767366004614bc1565b6114ba565b348015610777575f80fd5b5060075460ff1661044b565b34801561078e575f80fd5b506107976115bc565b60405162ffffff9091168152602001610457565b3480156107b6575f80fd5b50604080518082019091526005815264312e302e3360d81b6020820152610474565b3480156107e3575f80fd5b50601a546001600160a01b03166106f7565b348015610800575f80fd5b50600854600160a81b900463ffffffff165b60405163ffffffff9091168152602001610457565b348015610832575f80fd5b5061040b610841366004614b76565b6115cb565b348015610851575f80fd5b50610797610860366004614b76565b611636565b348015610870575f80fd5b5061040b61087f366004614bf2565b611731565b34801561088f575f80fd5b5061089861177f565b6040516104579190614c59565b3480156108b0575f80fd5b506104ec6108bf366004614b76565b6001600160a01b03165f9081526020819052604090205490565b3480156108e4575f80fd5b5061040b611910565b3480156108f8575f80fd5b50600754600160401b900462ffffff16610797565b348015610918575f80fd5b5061040b61195c565b34801561092c575f80fd5b5061040b61199d565b348015610940575f80fd5b5061040b61094f366004614968565b611a00565b34801561095f575f80fd5b506104ec61096e366004614b76565b6001600160a01b03165f9081526024602052604090205490565b348015610993575f80fd5b5061040b611a15565b3480156109a7575f80fd5b5061040b611a7d565b3480156109bb575f80fd5b50610797611b54565b3480156109cf575f80fd5b506107976109de366004614b76565b611b5a565b3480156109ee575f80fd5b506020546001600160a01b03166106f7565b348015610a0b575f80fd5b50610797610a1a366004614b76565b611c1d565b348015610a2a575f80fd5b50610474611cf9565b348015610a3e575f80fd5b506103e8610797565b348015610a52575f80fd5b5060085462ffffff63010000008204811691600160301b90041661061e565b348015610a7c575f80fd5b5061040b611d08565b348015610a90575f80fd5b5061044b610a9f366004614968565b611d7d565b348015610aaf575f80fd5b5061040b610abe366004614acb565b611ddd565b348015610ace575f80fd5b5061040b610add366004614acb565b611e69565b348015610aed575f80fd5b50610812610afc366004614b76565b611ec5565b348015610b0c575f80fd5b5061044b610b1b366004614968565b611f3b565b348015610b2b575f80fd5b5061040b610b3a366004614b76565b611f47565b348015610b4a575f80fd5b50601c546001600160a01b03166106f7565b348015610b67575f80fd5b5061040b611fa8565b348015610b7b575f80fd5b5061040b61200f565b348015610b8f575f80fd5b50610797612078565b348015610ba3575f80fd5b506019546040805160ff808416151582526101008404811615156020830152620100008404811615159282019290925263010000008304821615156060820152600160281b8304821615156080820152600160201b90920416151560a082015260c001610457565b348015610c16575f80fd5b5061040b610c25366004614cd8565b612082565b348015610c35575f80fd5b5061040b610c44366004614bc1565b61226a565b348015610c54575f80fd5b506014546104ec565b348015610c68575f80fd5b50600b546104ec565b348015610c7c575f80fd5b5061040b610c8b366004614b91565b612388565b348015610c9b575f80fd5b506104ec610caa366004614d41565b612405565b348015610cba575f80fd5b5061040b61242f565b348015610cce575f80fd5b5061040b610cdd366004614b76565b612494565b348015610ced575f80fd5b5061040b610cfc366004614968565b6124dc565b348015610d0c575f80fd5b5061040b610d1b366004614b76565b6125bc565b348015610d2b575f80fd5b5061044b610d3a366004614b76565b6001600160a01b03165f90815260036020526040902054610100900460ff1690565b348015610d67575f80fd5b5061040b610d76366004614d78565b612601565b348015610d86575f80fd5b50600754600160281b900462ffffff16610797565b348015610da6575f80fd5b50601b546001600160a01b03166106f7565b6020546001600160a01b03163314610deb5760405162461bcd60e51b8152600401610de290614da4565b60405180910390fd5b815f5b81811015610e2e57610e26858583818110610e0b57610e0b614dca565b9050602002016020810190610e209190614b76565b84612631565b600101610dee565b5050505050565b606060218054610e4490614dde565b80601f0160208091040260200160405190810160405280929190818152602001828054610e7090614dde565b8015610ebb5780601f10610e9257610100808354040283529160200191610ebb565b820191905f5260205f20905b815481529060010190602001808311610e9e57829003601f168201915b5050505050905090565b5f610ed133848461274c565b5060015b92915050565b6020546001600160a01b03163314610f055760405162461bcd60e51b8152600401610de290614da4565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015610f49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6d9190614e10565b90505f6001600160a01b0385163014610fba57601a546001600160a01b03868116911614610f9b575f610fc2565b601a546001600160a01b03165f90815260056020526040902054610fc2565b601254601654015b90508282821015610fd35781610fd5565b825b83031015610ff55760405162461bcd60e51b8152600401610de290614e27565b505060405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af1158015611043573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110679190614e50565b50505050565b6020546001600160a01b031633146110975760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff16156110ad575f80fd5b60018460ff16101580156110c5575060058460ff1611155b6110fc5760405162461bcd60e51b815260206004820152600860248201526714995cd95c9d995960c21b6044820152606401610de2565b611067848484846127ad565b5f611114843384612d52565b61111f848484612db5565b5060019392505050565b6020546001600160a01b031633146111535760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff1615611169575f80fd5b8015806111805750601b546001600160a01b031615155b6111b55760405162461bcd60e51b815260206004820152600660248201526509cde40888ab60d31b6044820152606401610de2565b6007805460ff1916911515919091179055565b6020546001600160a01b031633146111f25760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611208575f80fd5b6102588163ffffffff16111561121c575f80fd5b61122581613561565b50565b6060805f805f6060602160227f000000000000000000000000000000000000000000000000000000000000000060205f9054906101000a90046001600160a01b0316600a5460405180604001604052806005815260200164312e302e3360d81b81525085805461129790614dde565b80601f01602080910402602001604051908101604052809291908181526020018280546112c390614dde565b801561130e5780601f106112e55761010080835404028352916020019161130e565b820191905f5260205f20905b8154815290600101906020018083116112f157829003601f168201915b5050505050955084805461132190614dde565b80601f016020809104026020016040519081016040528092919081815260200182805461134d90614dde565b80156113985780601f1061136f57610100808354040283529160200191611398565b820191905f5260205f20905b81548152906001019060200180831161137b57829003601f168201915b50505050509450955095509550955095509550909192939495565b6020546001600160a01b031633146113dd5760405162461bcd60e51b8152600401610de290614da4565b6019805460ff191660011790556040517f951371dba26ef6174e32c5005af266bb9a0405124df206f136f85716d9c96093905f90a1565b5f610ed13384846114253388612405565b0161274c565b6020546001600160a01b031633146114555760405162461bcd60e51b8152600401610de290614da4565b6019546301000000900460ff161561146b575f80fd5b611474816135b5565b60405162ffffff821681527fd03edfeea801807308f0e9302e347c8a12ad32508cae5bce26e9e2a3654158c9906020015b60405180910390a150565b6112253382613669565b6020546001600160a01b031633146114e45760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff16156114fa575f80fd5b60018262ffffff161015801561151757506103e88262ffffff1611155b6115525760405162461bcd60e51b815260206004820152600c60248201526b302e3030312520746f20312560a01b6044820152606401610de2565b8162ffffff168162ffffff161015801561157357506103e88162ffffff1611155b6115ae5760405162461bcd60e51b815260206004820152600c60248201526b302e3030312520746f20312560a01b6044820152606401610de2565b6115b882826136e4565b5050565b5f6115c633611c1d565b905090565b6020546001600160a01b031633146115f55760405162461bcd60e51b8152600401610de290614da4565b601954610100900460ff1615611609575f80fd5b6001600160a01b03165f90815260036020526040902080546dffffffffffffffffffffffff000019169055565b6007545f9062010000900460ff161561165057505f919050565b6001600160a01b03821630148061167e57506001600160a01b0382165f9081526002602052604090205460ff165b806116965750601c546001600160a01b038381169116145b806116ae5750601b546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff16806116fe575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b61171657600754600160881b900462ffffff16610ed5565b600754600160d01b900462ffffff16610ed5565b5f92915050565b6020546001600160a01b0316331461175b5760405162461bcd60e51b8152600401610de290614da4565b601954610100900460ff161561176f575f80fd5b61177a838383613745565b505050565b60408051600680825260e08201909252606091816020015b61179f614780565b8152602001906001900390816117975790505090505f5b60068160ff16101561190c576040805160808101825260ff83165f81815260046020818152858320805461010090046001600160a01b03168652938352908152845160608101958690529394908501939260010191600391908390855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411611813579050505050918352505060ff83165f9081526004602090815260409182902082516060810190935292019160020160038282826020028201915f905b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116118875750505092845250505060ff83165f81815260046020908152604090912060030154920191909152835184919081106118f9576118f9614dca565b60209081029190910101526001016117b6565b5090565b6020546001600160a01b0316331461193a5760405162461bcd60e51b8152600401610de290614da4565b6019805465ffffffffffff19166501010101010117905561195a5f613817565b565b60075460ff1680156119765750600754610100900460ff16155b801561198c57506007546301000000900460ff16155b611994575f80fd5b61195a5f613868565b6020546001600160a01b031633146119c75760405162461bcd60e51b8152600401610de290614da4565b6019805461ff0019166101001790556040517ffd61f9d9e981b264f65f693615b347d7c5addcab978b82e81ae866b25155e426905f90a1565b611a0b823383612d52565b6115b88282613669565b6020546001600160a01b03163314611a3f5760405162461bcd60e51b8152600401610de290614da4565b6019805464ff000000001916600160201b1790556040517fb18b29d65a3b95dc80df0b9528f12b8592bd02395ca19228958e8b7cdf3ddd2b905f90a1565b6020546001600160a01b03163314611aa75760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff1615611abd575f80fd5b600854600160681b900463ffffffff1615611b0c5760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e48195b98589b1959608a1b6044820152606401610de2565b6008805463ffffffff60681b1916600160681b63ffffffff4216021790556040517f799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7905f90a1565b5f6115c6335b5f6001600160a01b038216301480611b8957506001600160a01b0382165f9081526002602052604090205460ff165b80611ba15750601c546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff1680611bf1575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b611c0957600754600160581b900462ffffff16610ed5565b600754600160a01b900462ffffff16610ed5565b6007545f9062010000900460ff1615611c3757505f919050565b6001600160a01b038216301480611c6557506001600160a01b0382165f9081526002602052604090205460ff165b80611c7d5750601c546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff1680611ccd575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b611ce557600754600160701b900462ffffff16610ed5565b600754600160b81b900462ffffff16610ed5565b606060228054610e4490614dde565b6020546001600160a01b0316331480611d2f5750335f9081526002602052604090205460ff165b611d4b5760405162461bcd60e51b8152600401610de290614da4565b600754610100900460ff16158015611d6d57506007546301000000900460ff16155b611d75575f80fd5b61195a613c62565b5f80611d893385612405565b905082811015611dd05760405162461bcd60e51b81526020600482015260126024820152714e6567617469766520616c6c6f77616e636560701b6044820152606401610de2565b61111f338585840361274c565b6020546001600160a01b0316331480611e045750335f9081526002602052604090205460ff165b611e205760405162461bcd60e51b8152600401610de290614da4565b8080611e2e575060075460ff165b8015611e425750600754610100900460ff16155b8015611e5857506007546301000000900460ff16155b611e60575f80fd5b61122581613868565b6020546001600160a01b03163314611e935760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611ea9575f80fd5b60078054911515620100000262ff000019909216919091179055565b6009545f9063ffffffff161580611f0257506001600160a01b0382165f9081526003602052604090205463ffffffff428116600160501b90920416105b15611f0e57505f919050565b506001600160a01b03165f9081526003602052604090205463ffffffff428116600160501b909204160390565b5f610ed1338484612db5565b6020546001600160a01b03163314611f715760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611f87575f80fd5b6001600160a01b03165f908152600360205260409020805461ff0019169055565b6020546001600160a01b03163314611fd25760405162461bcd60e51b8152600401610de290614da4565b6019805463ff000000191663010000001790556040517f6754c879eecdc6d0fbd95c51f8e377373a9f6be654462f792774fe3740e317ee905f90a1565b6020546001600160a01b031633146120395760405162461bcd60e51b8152600401610de290614da4565b6019805465ff00000000001916600160281b1790556040517ff7f7205ed48f7a35df9b5857667bdee0189d5d7cd80588f217a82641c3b4d08c905f90a1565b5f6115c633611636565b428410156120c65760405162461bcd60e51b815260206004820152601160248201527045787069726564207369676e617475726560781b6044820152606401610de2565b6023546001600160a01b038881165f8181526024602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e08501825280519083012061190160f01b6101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e280820193601f1981019281900390910190855afa1580156121de573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116158015906122145750886001600160a01b0316816001600160a01b0316145b6122545760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610de2565b505061226187878761274c565b50505050505050565b6020546001600160a01b031633146122945760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff16156122aa575f80fd5b600a8262ffffff16101580156122d657506122c86103e86064614e7f565b62ffffff168262ffffff1611155b6123125760405162461bcd60e51b815260206004820152600d60248201526c302e30312520746f203130302560981b6044820152606401610de2565b8162ffffff168162ffffff161015801561234257506123346103e86064614e7f565b62ffffff168162ffffff1611155b61237e5760405162461bcd60e51b815260206004820152600d60248201526c302e30312520746f203130302560981b6044820152606401610de2565b6115b88282613ddd565b6020546001600160a01b031633146123b25760405162461bcd60e51b8152600401610de290614da4565b60195462010000900460ff16156123c7575f80fd5b6123d081613e35565b60405162ffffff821681527ff01936354f43c5b49521c6c3fdc9740709976ee07acac3ebf79fbd6282cda195906020016114a5565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6020546001600160a01b031633146124595760405162461bcd60e51b8152600401610de290614da4565b6019805462ff00001916620100001790556040517fcc2f10fb1214ece03bcb178c4d75943daee74aff93182bfb58ba9b8ef5d8c5aa905f90a1565b6020546001600160a01b031633146124be5760405162461bcd60e51b8152600401610de290614da4565b601f80546001600160a01b0319166001600160a01b03831617905550565b6020546001600160a01b031633146125065760405162461bcd60e51b8152600401610de290614da4565b601e54601a5447915f916001600160a01b03908116911614612528575f61252c565b6018545b9050828282101561253d578161253f565b825b8303101561255f5760405162461bcd60e51b8152600401610de290614e27565b50505f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146125aa576040519150601f19603f3d011682016040523d82523d5f602084013e6125af565b606091505b505090508061177a575f80fd5b6020546001600160a01b031633146125e65760405162461bcd60e51b8152600401610de290614da4565b6001600160a01b0381166125f8575f80fd5b61122581613817565b6020546001600160a01b0316331461262b5760405162461bcd60e51b8152600401610de290614da4565b6115b882825b60195460ff1615612640575f80fd5b6001600160a01b0382161580159061266357506001600160a01b03821661dead14155b61266b575f80fd5b601b546001600160a01b038381169116148015906126975750601c546001600160a01b03838116911614155b6126ee5760405162461bcd60e51b815260206004820152602260248201527f44455820726f7574657220616e642070616972206172652070726976696c6567604482015261195960f21b6064820152608401610de2565b6001600160a01b0382165f81815260026020908152604091829020805460ff191685151590811790915591519182527fa54714518c5d275fdcd3d2a461e4858e4e8cb04fb93cd0bca9d6d34115f26440910160405180910390a25050565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60058460ff1611156127bd575f80fd5b6001600160a01b03831630148015906127de57506001600160a01b03831615155b6127e6575f80fd5b60ff84165f818152600460205260409020901580159061281057506001600160a01b03841661dead145b801561281f57505f8160030154115b1561285e5760405162461bcd60e51b815260206004820152600f60248201526e556e636c61696d656420746178657360881b6044820152606401610de2565b60018101805484516007805462ffffff60581b19811662ffffff948516909303600160581b8083048616919091018516810293841780845586546020808c015162ffffff60701b1990971665ffffffffffff60581b19909516949094176301000000918290048816909603600160701b9283900488160187169091029490941780845595546040808b015162ffffff60881b198916600160301b938490048916909103600160881b808b048a169190910189160290811780875560028b0180548d5162ffffff60a01b1990941665ffffffffffff60881b19909c169b909b179a8a16909203600160a01b918290048a1601891602989098178086558854948b015162ffffff60b81b198216979095048816909403600160b81b8086048916919091018816029586178086559754908a0151600160d01b988990048816929091048716900301851690950262ffffff60d01b1990931665ffffffffffff60b81b199091161791909117908190556161a89290041611801590612a3b57506007546161a8600160701b90910462ffffff1611801590612a0c57506007546161a8600160881b90910462ffffff1611155b8015612a3b57506007546161a8600160701b820462ffffff908116600160881b90930481169290920190911611155b612a725760405162461bcd60e51b8152602060048201526008602482015267090d2ced040a8c2f60c31b6044820152606401610de2565b60075462015f90600160a01b90910462ffffff1611801590612aa6575060075462015f90600160b81b90910462ffffff1611155b8015612ac4575060075462015f90600160d01b90910462ffffff1611155b612b025760405162461bcd60e51b815260206004820152600f60248201526e496e76616c69642050656e616c747960881b6044820152606401610de2565b8054610100600160a81b0319166101006001600160a01b03861602178155612b2f600182018460036147bb565b507f00000000000000000000000000000000000000000000000000000000000000008015612b5f57505f8560ff16115b15612ce9575f808052600460209081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec54604080516060808201835285825293810185905280820185905281519384019091526002850154612ce994936101009093046001600160a01b031692908190606490600a62ffffff9182160216046064895f6020020151600a0262ffffff1681612bfd57612bfd614e9e565b5f808052600460208181527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ee5462ffffff8082169690950496909603949094018316865260028c01548d850151928052908452630100000094859004831660649582048416600a9081028516879004938102851687900493909303018316938601939093526040808d0151950194600160301b909304821681028216849004939202165f805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ee5462ffffff600160301b90910481169290910492909203011690526127ad565b612cf8600282018360036147bb565b50805460ff16612d0e57805460ff191660011781555b7f30034b3ad500b0a06492ddcfbb1eedee788dff84a77d76d5c3658ab517cec51a85858585604051612d439493929190614eb2565b60405180910390a15050505050565b5f612d5d8484612405565b905081811015612da85760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610de2565b611067848484840361274c565b61deac196001600160a01b03831601612dd25761177a8382613669565b6007546301000000900460ff16158015612df45750600754610100900460ff16155b8015612e275750601c546001600160a01b03848116911614801590612e275750601b546001600160a01b03848116911614155b15612e3d57612e355f613868565b612e3d613c62565b5f81118015612e6457506001600160a01b0383165f9081526002602052604090205460ff16155b8015612e8857506001600160a01b0382165f9081526002602052604090205460ff16155b8015612e9d57506001600160a01b0383163014155b8015612eb257506001600160a01b0382163014155b8015612ecc5750601b546001600160a01b03838116911614155b1561355657601c546001600160a01b03848116911614801590612efd5750601c546001600160a01b03838116911614155b80612f465750601c546001600160a01b0384811691161480612f2c5750601c546001600160a01b038381169116145b8015612f465750600854600160681b900463ffffffff1615155b612f855760405162461bcd60e51b815260206004820152601060248201526f151c98591a5b99c8191a5cd8589b195960821b6044820152606401610de2565b60095463ffffffff1615801590612faa5750601c546001600160a01b03848116911614155b1561311057612fb883611ec5565b63ffffffff1615612ff65760405162461bcd60e51b815260206004820152600860248201526721b7b7b63237bbb760c11b6044820152606401610de2565b4263ffffffff166008546001600160a01b0385165f9081526003602052604090205463ffffffff928316600160c81b9092048316600160301b90910483160190911610156130b6576001600160a01b0383165f908152600360205260409020805465ffffffff000019166201000017905561307463ffffffff421690565b6001600160a01b0384165f908152600360205260409020805463ffffffff92909216600160301b0269ffffffff00000000000019909216919091179055613110565b6007546001600160a01b0384165f908152600360205260409020805465ffffffff0000198116620100009182900463ffffffff9081166001011691820217909155600160201b90910460ff16116131105761311083613ee6565b600c548111156131525760405162461bcd60e51b815260206004820152600d60248201526c08af0c6cacac8e640dac2f0a8f609b1b6044820152606401610de2565b6001600160a01b03821630148061318d5750601c546001600160a01b038381169116148061318d5750601b546001600160a01b038381169116145b806131b35750600d546001600160a01b0383165f90815260208190526040902054820111155b6131f45760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617842616c616e636560701b6044820152606401610de2565b60075462010000900460ff1615801561321757506007546301000000900460ff16155b801561322b5750600754610100900460ff16155b1561355657601c545f9081906001600160a01b038681169116148061325d5750601c546001600160a01b038581169116145b1561328457601c546001600160a01b0386811691161461327e576002613281565b60015b90505b5f8160ff166001146132965785613298565b845b60085490915063ffffffff428116600160a81b83048216600160681b90930482169290920116108015906132e957506001600160a01b0381165f90815260036020526040902054610100900460ff16155b15613313576001600160a01b0381165f908152600360205260409020805461ff0019166101001790555b5f5b60068160ff16101561353d575f808460ff16116133a0576001600160a01b0383165f90815260036020526040902054610100900460ff166133865760ff82165f908152600460205260408120600101905b600a91828204019190066003029054906101000a900462ffffff16613468565b60ff82165f90815260046020526040812060020190613366565b8360ff16600114613406576001600160a01b0383165f90815260036020526040902054610100900460ff166133ea5760ff82165f9081526004602052604090206001016002613366565b60ff82165f908152600460205260409020600290810190613366565b6001600160a01b0383165f90815260036020526040902054610100900460ff166134465760ff82165f908152600460205260409020600190810190613366565b60ff82165f908152600460205260409020600201546301000000900462ffffff165b62ffffff169050805f0361347c5750613535565b620186a08682020461348f893083613f3c565b601c5460ff84165f908152600460205260409020546001600160a01b03918216610100909104909116036134ca57601280548201905561352e565b60ff83165f9081526004602052604090205461deac196101009091046001600160a01b031601613503576134fe3082613669565b61352e565b60ff83165f908152600460205260409020600301805482019055601680548201905560158054820190555b9490940193505b600101613315565b50821561355257601480548401905592829003925b5050505b61177a838383613f3c565b6008805463ffffffff60a81b1916600160a81b63ffffffff8416908102919091179091556040519081527f703cced883e2faf6a2d5c676ef2f9dd7cfafa0acecee468ece9314ecf462ba91906020016114a5565b60648162ffffff16101580156135d35750620186a062ffffff821611155b6135db575f80fd5b600780546affffff00000000000000001916600160401b62ffffff841690810291909117909155600a54620186a0910204600d557f00000000000000000000000000000000000000000000000000000000000000006112255760405162ffffff821681527fd03edfeea801807308f0e9302e347c8a12ad32508cae5bce26e9e2a3654158c9906020016114a5565b6136738282614057565b60075461368b90600160281b900462ffffff16613e35565b6007546136a390600160401b900462ffffff166135b5565b6007546008546136c29162ffffff600160e81b909104811691166136e4565b6008546115b89062ffffff63010000008204811691600160301b900416613ddd565b600780546001600160e81b0316600160e81b62ffffff858116918202929092179092556008805462ffffff1916918416919091179055600a5461372b91620186a091020490565b600e55600a54620186a062ffffff929092160204600f5550565b60018360ff1611801561375e575060058263ffffffff16115b8015613773575062093a808163ffffffff1611155b61377b575f80fd5b6007805464ff000000001916600160201b60ff8616908102919091179091556008805463ffffffff60c81b1916600160c81b63ffffffff868116918202929092179092556009805463ffffffff19169185169182179055604080519384526020840192909252908201527f24b1343f86058af6b8e48d5f9ca6b4e206b72690500086e848cc587b2f4097149060600160405180910390a1505050565b602080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6007805461ff00191661010017905580158015613888575060075460ff16155b613c54575f806012541161389c575f6138b0565b6002601254816138ae576138ae614e9e565b045b601e54601a549192505f916001600160a01b039081169116146138d3575f6138d7565b6016545b9050818101831580156138eb5750600f5481115b15613954575f83116138fd575f613923565b600f546139239082620186a086028161391857613918614e9e565b04620186a091020490565b92505f8211613932575f61394d565b600f5461394d9082620186a085028161391857613918614e9e565b9150508181015b83806139625750600e548110155b801561397e5750305f9081526020819052604090205481840111155b15613b595760408051600280825260608201835247925f92919060208301908036833701905050905030815f815181106139ba576139ba614dca565b6001600160a01b039283166020918202929092010152601e548251911690829060019081106139eb576139eb614dca565b6001600160a01b039283166020918202929092010152601b54613a11913091168561274c565b601b5460405163791ac94760e01b81526001600160a01b039091169063791ac94790613a499086905f90869030904290600401614eef565b5f604051808303815f87803b158015613a60575f80fd5b505af1925050508015613a71575060015b613a9257601b54613a8d9030906001600160a01b03165f61274c565b613b56565b60125415613aa4576012805486900390555b604080518481524784900360208201819052917f9029ea20319a59447bd88162928acbbbe0955dead46655370929b794e46e8d96910160405180910390a18015613b5457613b008185620186a089028161391857613918614e9e565b601380549091019055601e54601a546001600160a01b03918216911603613b5457613b398185620186a088028161391857613918614e9e565b60188054909101905560178054860190556016805486900390555b505b50505b601a546001600160a01b03163014801590613b855750601e54601a546001600160a01b03908116911614155b15613c2957601654915083158015613b9e5750600f5482115b15613ba957600f5491505b8380613bb75750600e548210155b8015613bd15750305f908152602081905260409020548211155b15613c2957601a545f90613bee906001600160a01b0316846140f8565b90508015613c2757601a546001600160a01b03165f90815260056020526040902080548201905560178054840190556016805484900390555b505b505050613c358161436f565b6008805463ffffffff60881b19164263ffffffff16600160881b021790555b506007805461ff0019169055565b6007805463ff0000001916630100000017905560155415613dce575f805b60068160ff161015613d5e5760ff81165f908152600460205260409020805460038201546101009091046001600160a01b0316901580613cca57506001600160a01b03811661dead145b80613ce25750601c546001600160a01b038281169116145b15613cee575050613d56565b601a545f90613d2c906001600160a01b03163014613d0e57601754613d12565b6016545b6015546003860154620186a0028161391857613918614e9e565b90505f613d39838361451b565b90508015613d51576003840180548290039055948501945b505050505b600101613c80565b50600880546cffffffff0000000000000000001916690100000000000000000063ffffffff4216021790558015613dcc576015805482900390556040518181527fbb245b3c380b63918dc25ab2cc2e4b6939c4d58ffd95ea052b685a031e1ad2979060200160405180910390a15b505b6007805463ff00000019169055565b6008805468ffffffffffff0000001916630100000062ffffff94851690810268ffffff000000000000191691909117600160301b93909416928302939093179055600a54620186a09281028390046010550204601155565b60648162ffffff1610158015613e535750620186a062ffffff821611155b613e5b575f80fd5b6007805467ffffff00000000001916600160281b62ffffff841690810291909117909155600a54620186a0910204600c557f00000000000000000000000000000000000000000000000000000000000000006112255760405162ffffff821681527ff01936354f43c5b49521c6c3fdc9740709976ee07acac3ebf79fbd6282cda195906020016114a5565b60095463ffffffff16613efc63ffffffff421690565b6001600160a01b03929092165f908152600360205260409020805463ffffffff60501b1916600160501b9290930163ffffffff1691909102919091179055565b6001600160a01b03831615801590613f5c57506001600160a01b03821615155b613fa85760405162461bcd60e51b815260206004820152601d60248201527f5472616e736665722066726f6d2f746f207a65726f20616464726573730000006044820152606401610de2565b6001600160a01b0383165f90815260208190526040902054811115613fdf5760405162461bcd60e51b8152600401610de290614e27565b8015614012576001600160a01b038084165f90815260208190526040808220805485900390559184168152208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516127a091815260200190565b6001600160a01b0382165f9081526020819052604090205481111561408e5760405162461bcd60e51b8152600401610de290614e27565b6001600160a01b0382165f818152602081815260409182902080548590039055600a80548590039055600b805485019055905183815261dead92917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa15801561413e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141629190614e10565b604080516003808252608082019092529192505f91906020820160608036833701905050905030815f8151811061419b5761419b614dca565b6001600160a01b039283166020918202929092010152601e548251911690829060019081106141cc576141cc614dca565b60200260200101906001600160a01b031690816001600160a01b031681525050848160028151811061420057614200614dca565b6001600160a01b039283166020918202929092010152601b54614226913091168661274c565b601b54604051635c11d79560e01b81526001600160a01b0390911690635c11d7959061425e9087905f90869030904290600401614eef565b5f604051808303815f87803b158015614275575f80fd5b505af1925050508015614286575060015b6142a757601b546142a29030906001600160a01b03165f61274c565b614367565b6040516370a0823160e01b815230600482015282906001600160a01b038716906370a0823190602401602060405180830381865afa1580156142eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061430f9190614e10565b6143199190614f60565b604080516001600160a01b0388168152602081018790529081018290529093507fa82a03c1e8613c6192a82386fbb3690070528b0dd8bcae8a5c82d9ef937d7f769060600160405180910390a15b505092915050565b8015801561438a5750601054601254108061438a5750601354155b156143925750565b5f811580156143a45750601154601254115b6143b0576012546143b4565b6011545b90505f821580156143c85750601154601254115b6143d4576013546143fd565b6143fd601354601254601154816143ed576143ed614e9e565b04620186a002620186a091020490565b601b549091506144189030906001600160a01b03168461274c565b601b54601f5460405163f305d71960e01b8152306004820152602481018590525f6044820181905260648201526001600160a01b0391821660848201524260a482015291169063f305d71990839060c40160606040518083038185885af1935050505080156144a4575060408051601f3d908101601f191682019092526144a191810190614f73565b60015b6144c057601b5461177a9030906001600160a01b03165f61274c565b60408051848152602081018490529081018290527f947eb7d5785b0534dc368370fd3574434082455556a747116a88abea1ec6ceba9060600160405180910390a1505060128054849003905550601380548290039055505050565b5f815f0361452a57505f610ed5565b601a54306001600160a01b03909116036145f157600d546001600160a01b0384165f90815260208190526040902054830111801561458057506001600160a01b0383165f9081526002602052604090205460ff16155b156145d8576001600160a01b0383165f90815260208190526040902054600d54116145ab575f6145c8565b6001600160a01b0383165f90815260208190526040902054600d54035b9150815f036145d857505f610ed5565b6145e3308484613f3c565b60168054839003905561477a565b6017545f90620186a084028161460957614609614e9e565b601e54601a549290910492505f916001600160a01b039182169116036146ac57601854620186a09083020490505f856001600160a01b031682617530906040515f60405180830381858888f193505050503d805f8114614684576040519150601f19603f3d011682016040523d82523d5f602084013e614689565b606091505b505090508061469d575f9350505050610ed5565b5060188054829003905561476e565b601a546001600160a01b03165f90815260056020526040902054620186a090830204601a5460405163a9059cbb60e01b81526001600160a01b0388811660048301526024820184905292935091169063a9059cbb906044016020604051808303815f875af192505050801561473e575060408051601f3d908101601f1916820190925261473b91810190614e50565b60015b61474c575f92505050610ed5565b50601a546001600160a01b03165f908152600560205260409020805482900390555b50506017805483900390555b50919050565b60405180608001604052805f6001600160a01b031681526020016147a261484f565b81526020016147af61484f565b81526020015f81525090565b600183019183908215614843579160200282015f5b8382111561481257835183826101000a81548162ffffff021916908362ffffff16021790555092602001926003016020816002010492830192600103026147d0565b80156148415782816101000a81549062ffffff0219169055600301602081600201049283019260010302614812565b505b5061190c92915061486d565b60405180606001604052806003906020820280368337509192915050565b5b8082111561190c575f815560010161486e565b8015158114611225575f80fd5b5f805f604084860312156148a0575f80fd5b833567ffffffffffffffff808211156148b7575f80fd5b818601915086601f8301126148ca575f80fd5b8135818111156148d8575f80fd5b8760208260051b85010111156148ec575f80fd5b6020928301955093505084013561490281614881565b809150509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61494d602083018461490d565b9392505050565b6001600160a01b0381168114611225575f80fd5b5f8060408385031215614979575f80fd5b823561498481614954565b946020939093013593505050565b5f805f606084860312156149a4575f80fd5b83356149af81614954565b925060208401356149bf81614954565b929592945050506040919091013590565b803560ff811681146149e0575f80fd5b919050565b803562ffffff811681146149e0575f80fd5b5f82601f830112614a06575f80fd5b6040516060810181811067ffffffffffffffff82111715614a3557634e487b7160e01b5f52604160045260245ffd5b604052806060840185811115614a49575f80fd5b845b81811015614a6a57614a5c816149e5565b835260209283019201614a4b565b509195945050505050565b5f805f806101008587031215614a89575f80fd5b614a92856149d0565b93506020850135614aa281614954565b9250614ab186604087016149f7565b9150614ac08660a087016149f7565b905092959194509250565b5f60208284031215614adb575f80fd5b813561494d81614881565b803563ffffffff811681146149e0575f80fd5b5f60208284031215614b09575f80fd5b61494d82614ae6565b60c081525f614b2460c083018961490d565b8281036020840152614b36818961490d565b60ff881660408501526001600160a01b03871660608501526080840186905283810360a08501529050614b69818561490d565b9998505050505050505050565b5f60208284031215614b86575f80fd5b813561494d81614954565b5f60208284031215614ba1575f80fd5b61494d826149e5565b5f60208284031215614bba575f80fd5b5035919050565b5f8060408385031215614bd2575f80fd5b614bdb836149e5565b9150614be9602084016149e5565b90509250929050565b5f805f60608486031215614c04575f80fd5b614c0d846149d0565b9250614c1b60208501614ae6565b9150614c2960408501614ae6565b90509250925092565b805f5b600381101561106757815162ffffff16845260209384019390910190600101614c35565b602080825282518282018190525f919060409081850190868401855b82811015614ccb57815180516001600160a01b0316855286810151614c9c88870182614c32565b5085810151614cae6080870182614c32565b506060015160e08501526101009093019290850190600101614c75565b5091979650505050505050565b5f805f805f805f60e0888a031215614cee575f80fd5b8735614cf981614954565b96506020880135614d0981614954565b95506040880135945060608801359350614d25608089016149d0565b925060a0880135915060c0880135905092959891949750929550565b5f8060408385031215614d52575f80fd5b8235614d5d81614954565b91506020830135614d6d81614954565b809150509250929050565b5f8060408385031215614d89575f80fd5b8235614d9481614954565b91506020830135614d6d81614881565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680614df257607f821691505b60208210810361477a57634e487b7160e01b5f52602260045260245ffd5b5f60208284031215614e20575f80fd5b5051919050565b6020808252600f908201526e457863656564732062616c616e636560881b604082015260600190565b5f60208284031215614e60575f80fd5b815161494d81614881565b634e487b7160e01b5f52601160045260245ffd5b62ffffff81811683821602808216919082811461436757614367614e6b565b634e487b7160e01b5f52601260045260245ffd5b60ff851681526001600160a01b03841660208201526101008101614ed96040830185614c32565b614ee660a0830184614c32565b95945050505050565b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b81811015614f3f5784516001600160a01b031683529383019391830191600101614f1a565b50506001600160a01b03969096166060850152505050608001529392505050565b81810381811115610ed557610ed5614e6b565b5f805f60608486031215614f85575f80fd5b835192506020840151915060408401519050925092509256fea2646970667358221220fa50d9a2c712d18752455be43916af40de986f77031975d9a63eb2bcd0cf911b64736f6c6343000819003317ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ee

Deployed Bytecode

0x608060405260043610610404575f3560e01c806379cc679011610210578063c292158311610121578063da88d01a116100af578063f2fde38b11610076578063f2fde38b14610d01578063f3dc4f4814610d20578063f59c370814610d5c578063f7c3b38f14610d7b578063f7de0e5714610d9b57005b8063da88d01a14610c71578063dd62ed3e14610c90578063e92871f614610caf578063edd286cf14610cc3578063f2cda82e14610ce257005b8063d232c220116100f3578063d232c22014610b98578063d505accf14610c0b578063d6a018eb14610c2a578063d8454a8214610c49578063d89135cd14610c5d57005b8063c292158314610b3f578063c77e006d14610b5c578063c78fe0d414610b70578063cc1776d314610b8457005b806396ce07951161019e578063a4d8971a11610170578063a4d8971a14610aa4578063a5596b4f14610ac3578063a6cbe5c114610ae2578063a9059cbb14610b01578063be5e49b214610b2057005b806396ce079514610a3357806397a26b9e14610a475780639c5ef8d714610a71578063a457c2d714610a8557005b80638bf1acff116101e25780638bf1acff146109b05780638d8350ca146109c45780638da5cb5b146109e357806395101f9014610a0057806395d89b4114610a1f57005b806379cc6790146109355780637ecebe00146109545780638324c3b9146109885780638a8c523c1461099c57005b80633af32abf116103155780635b90fe66116102a357806370a082311161026a57806370a08231146108a5578063715018a6146108d957806375de1496146108ed578063770048511461090d57806379b3d4111461092157005b80635b90fe66146107f55780635bbb7a51146108275780635f641758146108465780636d5c1490146108655780636f05be971461088457005b806344b691ff116102e757806344b691ff1461074d5780634b7d9db41461076c5780634f7041a51461078357806354fd4d50146107ab5780635a0d4f88146107d857005b80633af32abf146106a75780633b7854de146106de5780633ed8a1691461070f57806342966c681461072e57005b80632623e9751161039257806332acf3de1161036457806332acf3de146105fb5780633644e5151461063a578063370158ea1461064e57806339137f8b14610674578063395093511461068857005b80632623e975146105385780632984207a146105575780632d6916be14610576578063313ce567146105be57005b8063095ea7b3116103d6578063095ea7b31461049e5780631171bda9146104bd57806318160ddd146104dc578063186488a8146104fa57806323b872dd1461051957005b806301b38af51461040d578063064a59d01461042c57806306fdde031461046057806307e9652c1461048157005b3661040b57005b005b348015610418575f80fd5b5061040b61042736600461488e565b610db8565b348015610437575f80fd5b50600854600160681b900463ffffffff1615155b60405190151581526020015b60405180910390f35b34801561046b575f80fd5b50610474610e35565b604051610457919061493b565b34801561048c575f80fd5b5060075462010000900460ff1661044b565b3480156104a9575f80fd5b5061044b6104b8366004614968565b610ec5565b3480156104c8575f80fd5b5061040b6104d7366004614992565b610edb565b3480156104e7575f80fd5b50600a545b604051908152602001610457565b348015610505575f80fd5b5061040b610514366004614a75565b61106d565b348015610524575f80fd5b5061044b610533366004614992565b611108565b348015610543575f80fd5b5061040b610552366004614acb565b611129565b348015610562575f80fd5b5061040b610571366004614af9565b6111c8565b348015610581575f80fd5b5060075460085460095460408051600160201b90940460ff168452600160c81b90920463ffffffff90811660208501521690820152606001610457565b3480156105c9575f80fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000012168152602001610457565b348015610606575f80fd5b5060075460085462ffffff600160e81b909204821691165b6040805162ffffff938416815292909116602083015201610457565b348015610645575f80fd5b506023546104ec565b348015610659575f80fd5b50610662611228565b60405161045796959493929190614b12565b34801561067f575f80fd5b5061040b6113b3565b348015610693575f80fd5b5061044b6106a2366004614968565b611414565b3480156106b2575f80fd5b5061044b6106c1366004614b76565b6001600160a01b03165f9081526002602052604090205460ff1690565b3480156106e9575f80fd5b50601f546001600160a01b03165b6040516001600160a01b039091168152602001610457565b34801561071a575f80fd5b5061040b610729366004614b91565b61142b565b348015610739575f80fd5b5061040b610748366004614baa565b6114b0565b348015610758575f80fd5b5061040b610767366004614bc1565b6114ba565b348015610777575f80fd5b5060075460ff1661044b565b34801561078e575f80fd5b506107976115bc565b60405162ffffff9091168152602001610457565b3480156107b6575f80fd5b50604080518082019091526005815264312e302e3360d81b6020820152610474565b3480156107e3575f80fd5b50601a546001600160a01b03166106f7565b348015610800575f80fd5b50600854600160a81b900463ffffffff165b60405163ffffffff9091168152602001610457565b348015610832575f80fd5b5061040b610841366004614b76565b6115cb565b348015610851575f80fd5b50610797610860366004614b76565b611636565b348015610870575f80fd5b5061040b61087f366004614bf2565b611731565b34801561088f575f80fd5b5061089861177f565b6040516104579190614c59565b3480156108b0575f80fd5b506104ec6108bf366004614b76565b6001600160a01b03165f9081526020819052604090205490565b3480156108e4575f80fd5b5061040b611910565b3480156108f8575f80fd5b50600754600160401b900462ffffff16610797565b348015610918575f80fd5b5061040b61195c565b34801561092c575f80fd5b5061040b61199d565b348015610940575f80fd5b5061040b61094f366004614968565b611a00565b34801561095f575f80fd5b506104ec61096e366004614b76565b6001600160a01b03165f9081526024602052604090205490565b348015610993575f80fd5b5061040b611a15565b3480156109a7575f80fd5b5061040b611a7d565b3480156109bb575f80fd5b50610797611b54565b3480156109cf575f80fd5b506107976109de366004614b76565b611b5a565b3480156109ee575f80fd5b506020546001600160a01b03166106f7565b348015610a0b575f80fd5b50610797610a1a366004614b76565b611c1d565b348015610a2a575f80fd5b50610474611cf9565b348015610a3e575f80fd5b506103e8610797565b348015610a52575f80fd5b5060085462ffffff63010000008204811691600160301b90041661061e565b348015610a7c575f80fd5b5061040b611d08565b348015610a90575f80fd5b5061044b610a9f366004614968565b611d7d565b348015610aaf575f80fd5b5061040b610abe366004614acb565b611ddd565b348015610ace575f80fd5b5061040b610add366004614acb565b611e69565b348015610aed575f80fd5b50610812610afc366004614b76565b611ec5565b348015610b0c575f80fd5b5061044b610b1b366004614968565b611f3b565b348015610b2b575f80fd5b5061040b610b3a366004614b76565b611f47565b348015610b4a575f80fd5b50601c546001600160a01b03166106f7565b348015610b67575f80fd5b5061040b611fa8565b348015610b7b575f80fd5b5061040b61200f565b348015610b8f575f80fd5b50610797612078565b348015610ba3575f80fd5b506019546040805160ff808416151582526101008404811615156020830152620100008404811615159282019290925263010000008304821615156060820152600160281b8304821615156080820152600160201b90920416151560a082015260c001610457565b348015610c16575f80fd5b5061040b610c25366004614cd8565b612082565b348015610c35575f80fd5b5061040b610c44366004614bc1565b61226a565b348015610c54575f80fd5b506014546104ec565b348015610c68575f80fd5b50600b546104ec565b348015610c7c575f80fd5b5061040b610c8b366004614b91565b612388565b348015610c9b575f80fd5b506104ec610caa366004614d41565b612405565b348015610cba575f80fd5b5061040b61242f565b348015610cce575f80fd5b5061040b610cdd366004614b76565b612494565b348015610ced575f80fd5b5061040b610cfc366004614968565b6124dc565b348015610d0c575f80fd5b5061040b610d1b366004614b76565b6125bc565b348015610d2b575f80fd5b5061044b610d3a366004614b76565b6001600160a01b03165f90815260036020526040902054610100900460ff1690565b348015610d67575f80fd5b5061040b610d76366004614d78565b612601565b348015610d86575f80fd5b50600754600160281b900462ffffff16610797565b348015610da6575f80fd5b50601b546001600160a01b03166106f7565b6020546001600160a01b03163314610deb5760405162461bcd60e51b8152600401610de290614da4565b60405180910390fd5b815f5b81811015610e2e57610e26858583818110610e0b57610e0b614dca565b9050602002016020810190610e209190614b76565b84612631565b600101610dee565b5050505050565b606060218054610e4490614dde565b80601f0160208091040260200160405190810160405280929190818152602001828054610e7090614dde565b8015610ebb5780601f10610e9257610100808354040283529160200191610ebb565b820191905f5260205f20905b815481529060010190602001808311610e9e57829003601f168201915b5050505050905090565b5f610ed133848461274c565b5060015b92915050565b6020546001600160a01b03163314610f055760405162461bcd60e51b8152600401610de290614da4565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015610f49573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6d9190614e10565b90505f6001600160a01b0385163014610fba57601a546001600160a01b03868116911614610f9b575f610fc2565b601a546001600160a01b03165f90815260056020526040902054610fc2565b601254601654015b90508282821015610fd35781610fd5565b825b83031015610ff55760405162461bcd60e51b8152600401610de290614e27565b505060405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af1158015611043573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110679190614e50565b50505050565b6020546001600160a01b031633146110975760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff16156110ad575f80fd5b60018460ff16101580156110c5575060058460ff1611155b6110fc5760405162461bcd60e51b815260206004820152600860248201526714995cd95c9d995960c21b6044820152606401610de2565b611067848484846127ad565b5f611114843384612d52565b61111f848484612db5565b5060019392505050565b6020546001600160a01b031633146111535760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff1615611169575f80fd5b8015806111805750601b546001600160a01b031615155b6111b55760405162461bcd60e51b815260206004820152600660248201526509cde40888ab60d31b6044820152606401610de2565b6007805460ff1916911515919091179055565b6020546001600160a01b031633146111f25760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611208575f80fd5b6102588163ffffffff16111561121c575f80fd5b61122581613561565b50565b6060805f805f6060602160227f000000000000000000000000000000000000000000000000000000000000001260205f9054906101000a90046001600160a01b0316600a5460405180604001604052806005815260200164312e302e3360d81b81525085805461129790614dde565b80601f01602080910402602001604051908101604052809291908181526020018280546112c390614dde565b801561130e5780601f106112e55761010080835404028352916020019161130e565b820191905f5260205f20905b8154815290600101906020018083116112f157829003601f168201915b5050505050955084805461132190614dde565b80601f016020809104026020016040519081016040528092919081815260200182805461134d90614dde565b80156113985780601f1061136f57610100808354040283529160200191611398565b820191905f5260205f20905b81548152906001019060200180831161137b57829003601f168201915b50505050509450955095509550955095509550909192939495565b6020546001600160a01b031633146113dd5760405162461bcd60e51b8152600401610de290614da4565b6019805460ff191660011790556040517f951371dba26ef6174e32c5005af266bb9a0405124df206f136f85716d9c96093905f90a1565b5f610ed13384846114253388612405565b0161274c565b6020546001600160a01b031633146114555760405162461bcd60e51b8152600401610de290614da4565b6019546301000000900460ff161561146b575f80fd5b611474816135b5565b60405162ffffff821681527fd03edfeea801807308f0e9302e347c8a12ad32508cae5bce26e9e2a3654158c9906020015b60405180910390a150565b6112253382613669565b6020546001600160a01b031633146114e45760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff16156114fa575f80fd5b60018262ffffff161015801561151757506103e88262ffffff1611155b6115525760405162461bcd60e51b815260206004820152600c60248201526b302e3030312520746f20312560a01b6044820152606401610de2565b8162ffffff168162ffffff161015801561157357506103e88162ffffff1611155b6115ae5760405162461bcd60e51b815260206004820152600c60248201526b302e3030312520746f20312560a01b6044820152606401610de2565b6115b882826136e4565b5050565b5f6115c633611c1d565b905090565b6020546001600160a01b031633146115f55760405162461bcd60e51b8152600401610de290614da4565b601954610100900460ff1615611609575f80fd5b6001600160a01b03165f90815260036020526040902080546dffffffffffffffffffffffff000019169055565b6007545f9062010000900460ff161561165057505f919050565b6001600160a01b03821630148061167e57506001600160a01b0382165f9081526002602052604090205460ff165b806116965750601c546001600160a01b038381169116145b806116ae5750601b546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff16806116fe575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b61171657600754600160881b900462ffffff16610ed5565b600754600160d01b900462ffffff16610ed5565b5f92915050565b6020546001600160a01b0316331461175b5760405162461bcd60e51b8152600401610de290614da4565b601954610100900460ff161561176f575f80fd5b61177a838383613745565b505050565b60408051600680825260e08201909252606091816020015b61179f614780565b8152602001906001900390816117975790505090505f5b60068160ff16101561190c576040805160808101825260ff83165f81815260046020818152858320805461010090046001600160a01b03168652938352908152845160608101958690529394908501939260010191600391908390855b82829054906101000a900462ffffff1662ffffff1681526020019060030190602082600201049283019260010382029150808411611813579050505050918352505060ff83165f9081526004602090815260409182902082516060810190935292019160020160038282826020028201915f905b82829054906101000a900462ffffff1662ffffff16815260200190600301906020826002010492830192600103820291508084116118875750505092845250505060ff83165f81815260046020908152604090912060030154920191909152835184919081106118f9576118f9614dca565b60209081029190910101526001016117b6565b5090565b6020546001600160a01b0316331461193a5760405162461bcd60e51b8152600401610de290614da4565b6019805465ffffffffffff19166501010101010117905561195a5f613817565b565b60075460ff1680156119765750600754610100900460ff16155b801561198c57506007546301000000900460ff16155b611994575f80fd5b61195a5f613868565b6020546001600160a01b031633146119c75760405162461bcd60e51b8152600401610de290614da4565b6019805461ff0019166101001790556040517ffd61f9d9e981b264f65f693615b347d7c5addcab978b82e81ae866b25155e426905f90a1565b611a0b823383612d52565b6115b88282613669565b6020546001600160a01b03163314611a3f5760405162461bcd60e51b8152600401610de290614da4565b6019805464ff000000001916600160201b1790556040517fb18b29d65a3b95dc80df0b9528f12b8592bd02395ca19228958e8b7cdf3ddd2b905f90a1565b6020546001600160a01b03163314611aa75760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff1615611abd575f80fd5b600854600160681b900463ffffffff1615611b0c5760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e48195b98589b1959608a1b6044820152606401610de2565b6008805463ffffffff60681b1916600160681b63ffffffff4216021790556040517f799663458a5ef2936f7fa0c99b3336c69c25890f82974f04e811e5bb359186c7905f90a1565b5f6115c6335b5f6001600160a01b038216301480611b8957506001600160a01b0382165f9081526002602052604090205460ff165b80611ba15750601c546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff1680611bf1575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b611c0957600754600160581b900462ffffff16610ed5565b600754600160a01b900462ffffff16610ed5565b6007545f9062010000900460ff1615611c3757505f919050565b6001600160a01b038216301480611c6557506001600160a01b0382165f9081526002602052604090205460ff165b80611c7d5750601c546001600160a01b038381169116145b61172a576001600160a01b0382165f90815260036020526040902054610100900460ff1680611ccd575060085463ffffffff428116600160a81b83048216600160681b9093048216929092011610155b611ce557600754600160701b900462ffffff16610ed5565b600754600160b81b900462ffffff16610ed5565b606060228054610e4490614dde565b6020546001600160a01b0316331480611d2f5750335f9081526002602052604090205460ff165b611d4b5760405162461bcd60e51b8152600401610de290614da4565b600754610100900460ff16158015611d6d57506007546301000000900460ff16155b611d75575f80fd5b61195a613c62565b5f80611d893385612405565b905082811015611dd05760405162461bcd60e51b81526020600482015260126024820152714e6567617469766520616c6c6f77616e636560701b6044820152606401610de2565b61111f338585840361274c565b6020546001600160a01b0316331480611e045750335f9081526002602052604090205460ff165b611e205760405162461bcd60e51b8152600401610de290614da4565b8080611e2e575060075460ff165b8015611e425750600754610100900460ff16155b8015611e5857506007546301000000900460ff16155b611e60575f80fd5b61122581613868565b6020546001600160a01b03163314611e935760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611ea9575f80fd5b60078054911515620100000262ff000019909216919091179055565b6009545f9063ffffffff161580611f0257506001600160a01b0382165f9081526003602052604090205463ffffffff428116600160501b90920416105b15611f0e57505f919050565b506001600160a01b03165f9081526003602052604090205463ffffffff428116600160501b909204160390565b5f610ed1338484612db5565b6020546001600160a01b03163314611f715760405162461bcd60e51b8152600401610de290614da4565b601954600160201b900460ff1615611f87575f80fd5b6001600160a01b03165f908152600360205260409020805461ff0019169055565b6020546001600160a01b03163314611fd25760405162461bcd60e51b8152600401610de290614da4565b6019805463ff000000191663010000001790556040517f6754c879eecdc6d0fbd95c51f8e377373a9f6be654462f792774fe3740e317ee905f90a1565b6020546001600160a01b031633146120395760405162461bcd60e51b8152600401610de290614da4565b6019805465ff00000000001916600160281b1790556040517ff7f7205ed48f7a35df9b5857667bdee0189d5d7cd80588f217a82641c3b4d08c905f90a1565b5f6115c633611636565b428410156120c65760405162461bcd60e51b815260206004820152601160248201527045787069726564207369676e617475726560781b6044820152606401610de2565b6023546001600160a01b038881165f8181526024602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e08501825280519083012061190160f01b6101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e280820193601f1981019281900390910190855afa1580156121de573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116158015906122145750886001600160a01b0316816001600160a01b0316145b6122545760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610de2565b505061226187878761274c565b50505050505050565b6020546001600160a01b031633146122945760405162461bcd60e51b8152600401610de290614da4565b601954600160281b900460ff16156122aa575f80fd5b600a8262ffffff16101580156122d657506122c86103e86064614e7f565b62ffffff168262ffffff1611155b6123125760405162461bcd60e51b815260206004820152600d60248201526c302e30312520746f203130302560981b6044820152606401610de2565b8162ffffff168162ffffff161015801561234257506123346103e86064614e7f565b62ffffff168162ffffff1611155b61237e5760405162461bcd60e51b815260206004820152600d60248201526c302e30312520746f203130302560981b6044820152606401610de2565b6115b88282613ddd565b6020546001600160a01b031633146123b25760405162461bcd60e51b8152600401610de290614da4565b60195462010000900460ff16156123c7575f80fd5b6123d081613e35565b60405162ffffff821681527ff01936354f43c5b49521c6c3fdc9740709976ee07acac3ebf79fbd6282cda195906020016114a5565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6020546001600160a01b031633146124595760405162461bcd60e51b8152600401610de290614da4565b6019805462ff00001916620100001790556040517fcc2f10fb1214ece03bcb178c4d75943daee74aff93182bfb58ba9b8ef5d8c5aa905f90a1565b6020546001600160a01b031633146124be5760405162461bcd60e51b8152600401610de290614da4565b601f80546001600160a01b0319166001600160a01b03831617905550565b6020546001600160a01b031633146125065760405162461bcd60e51b8152600401610de290614da4565b601e54601a5447915f916001600160a01b03908116911614612528575f61252c565b6018545b9050828282101561253d578161253f565b825b8303101561255f5760405162461bcd60e51b8152600401610de290614e27565b50505f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146125aa576040519150601f19603f3d011682016040523d82523d5f602084013e6125af565b606091505b505090508061177a575f80fd5b6020546001600160a01b031633146125e65760405162461bcd60e51b8152600401610de290614da4565b6001600160a01b0381166125f8575f80fd5b61122581613817565b6020546001600160a01b0316331461262b5760405162461bcd60e51b8152600401610de290614da4565b6115b882825b60195460ff1615612640575f80fd5b6001600160a01b0382161580159061266357506001600160a01b03821661dead14155b61266b575f80fd5b601b546001600160a01b038381169116148015906126975750601c546001600160a01b03838116911614155b6126ee5760405162461bcd60e51b815260206004820152602260248201527f44455820726f7574657220616e642070616972206172652070726976696c6567604482015261195960f21b6064820152608401610de2565b6001600160a01b0382165f81815260026020908152604091829020805460ff191685151590811790915591519182527fa54714518c5d275fdcd3d2a461e4858e4e8cb04fb93cd0bca9d6d34115f26440910160405180910390a25050565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60058460ff1611156127bd575f80fd5b6001600160a01b03831630148015906127de57506001600160a01b03831615155b6127e6575f80fd5b60ff84165f818152600460205260409020901580159061281057506001600160a01b03841661dead145b801561281f57505f8160030154115b1561285e5760405162461bcd60e51b815260206004820152600f60248201526e556e636c61696d656420746178657360881b6044820152606401610de2565b60018101805484516007805462ffffff60581b19811662ffffff948516909303600160581b8083048616919091018516810293841780845586546020808c015162ffffff60701b1990971665ffffffffffff60581b19909516949094176301000000918290048816909603600160701b9283900488160187169091029490941780845595546040808b015162ffffff60881b198916600160301b938490048916909103600160881b808b048a169190910189160290811780875560028b0180548d5162ffffff60a01b1990941665ffffffffffff60881b19909c169b909b179a8a16909203600160a01b918290048a1601891602989098178086558854948b015162ffffff60b81b198216979095048816909403600160b81b8086048916919091018816029586178086559754908a0151600160d01b988990048816929091048716900301851690950262ffffff60d01b1990931665ffffffffffff60b81b199091161791909117908190556161a89290041611801590612a3b57506007546161a8600160701b90910462ffffff1611801590612a0c57506007546161a8600160881b90910462ffffff1611155b8015612a3b57506007546161a8600160701b820462ffffff908116600160881b90930481169290920190911611155b612a725760405162461bcd60e51b8152602060048201526008602482015267090d2ced040a8c2f60c31b6044820152606401610de2565b60075462015f90600160a01b90910462ffffff1611801590612aa6575060075462015f90600160b81b90910462ffffff1611155b8015612ac4575060075462015f90600160d01b90910462ffffff1611155b612b025760405162461bcd60e51b815260206004820152600f60248201526e496e76616c69642050656e616c747960881b6044820152606401610de2565b8054610100600160a81b0319166101006001600160a01b03861602178155612b2f600182018460036147bb565b507f00000000000000000000000000000000000000000000000000000000000000018015612b5f57505f8560ff16115b15612ce9575f808052600460209081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec54604080516060808201835285825293810185905280820185905281519384019091526002850154612ce994936101009093046001600160a01b031692908190606490600a62ffffff9182160216046064895f6020020151600a0262ffffff1681612bfd57612bfd614e9e565b5f808052600460208181527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ee5462ffffff8082169690950496909603949094018316865260028c01548d850151928052908452630100000094859004831660649582048416600a9081028516879004938102851687900493909303018316938601939093526040808d0151950194600160301b909304821681028216849004939202165f805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ee5462ffffff600160301b90910481169290910492909203011690526127ad565b612cf8600282018360036147bb565b50805460ff16612d0e57805460ff191660011781555b7f30034b3ad500b0a06492ddcfbb1eedee788dff84a77d76d5c3658ab517cec51a85858585604051612d439493929190614eb2565b60405180910390a15050505050565b5f612d5d8484612405565b905081811015612da85760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610de2565b611067848484840361274c565b61deac196001600160a01b03831601612dd25761177a8382613669565b6007546301000000900460ff16158015612df45750600754610100900460ff16155b8015612e275750601c546001600160a01b03848116911614801590612e275750601b546001600160a01b03848116911614155b15612e3d57612e355f613868565b612e3d613c62565b5f81118015612e6457506001600160a01b0383165f9081526002602052604090205460ff16155b8015612e8857506001600160a01b0382165f9081526002602052604090205460ff16155b8015612e9d57506001600160a01b0383163014155b8015612eb257506001600160a01b0382163014155b8015612ecc5750601b546001600160a01b03838116911614155b1561355657601c546001600160a01b03848116911614801590612efd5750601c546001600160a01b03838116911614155b80612f465750601c546001600160a01b0384811691161480612f2c5750601c546001600160a01b038381169116145b8015612f465750600854600160681b900463ffffffff1615155b612f855760405162461bcd60e51b815260206004820152601060248201526f151c98591a5b99c8191a5cd8589b195960821b6044820152606401610de2565b60095463ffffffff1615801590612faa5750601c546001600160a01b03848116911614155b1561311057612fb883611ec5565b63ffffffff1615612ff65760405162461bcd60e51b815260206004820152600860248201526721b7b7b63237bbb760c11b6044820152606401610de2565b4263ffffffff166008546001600160a01b0385165f9081526003602052604090205463ffffffff928316600160c81b9092048316600160301b90910483160190911610156130b6576001600160a01b0383165f908152600360205260409020805465ffffffff000019166201000017905561307463ffffffff421690565b6001600160a01b0384165f908152600360205260409020805463ffffffff92909216600160301b0269ffffffff00000000000019909216919091179055613110565b6007546001600160a01b0384165f908152600360205260409020805465ffffffff0000198116620100009182900463ffffffff9081166001011691820217909155600160201b90910460ff16116131105761311083613ee6565b600c548111156131525760405162461bcd60e51b815260206004820152600d60248201526c08af0c6cacac8e640dac2f0a8f609b1b6044820152606401610de2565b6001600160a01b03821630148061318d5750601c546001600160a01b038381169116148061318d5750601b546001600160a01b038381169116145b806131b35750600d546001600160a01b0383165f90815260208190526040902054820111155b6131f45760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617842616c616e636560701b6044820152606401610de2565b60075462010000900460ff1615801561321757506007546301000000900460ff16155b801561322b5750600754610100900460ff16155b1561355657601c545f9081906001600160a01b038681169116148061325d5750601c546001600160a01b038581169116145b1561328457601c546001600160a01b0386811691161461327e576002613281565b60015b90505b5f8160ff166001146132965785613298565b845b60085490915063ffffffff428116600160a81b83048216600160681b90930482169290920116108015906132e957506001600160a01b0381165f90815260036020526040902054610100900460ff16155b15613313576001600160a01b0381165f908152600360205260409020805461ff0019166101001790555b5f5b60068160ff16101561353d575f808460ff16116133a0576001600160a01b0383165f90815260036020526040902054610100900460ff166133865760ff82165f908152600460205260408120600101905b600a91828204019190066003029054906101000a900462ffffff16613468565b60ff82165f90815260046020526040812060020190613366565b8360ff16600114613406576001600160a01b0383165f90815260036020526040902054610100900460ff166133ea5760ff82165f9081526004602052604090206001016002613366565b60ff82165f908152600460205260409020600290810190613366565b6001600160a01b0383165f90815260036020526040902054610100900460ff166134465760ff82165f908152600460205260409020600190810190613366565b60ff82165f908152600460205260409020600201546301000000900462ffffff165b62ffffff169050805f0361347c5750613535565b620186a08682020461348f893083613f3c565b601c5460ff84165f908152600460205260409020546001600160a01b03918216610100909104909116036134ca57601280548201905561352e565b60ff83165f9081526004602052604090205461deac196101009091046001600160a01b031601613503576134fe3082613669565b61352e565b60ff83165f908152600460205260409020600301805482019055601680548201905560158054820190555b9490940193505b600101613315565b50821561355257601480548401905592829003925b5050505b61177a838383613f3c565b6008805463ffffffff60a81b1916600160a81b63ffffffff8416908102919091179091556040519081527f703cced883e2faf6a2d5c676ef2f9dd7cfafa0acecee468ece9314ecf462ba91906020016114a5565b60648162ffffff16101580156135d35750620186a062ffffff821611155b6135db575f80fd5b600780546affffff00000000000000001916600160401b62ffffff841690810291909117909155600a54620186a0910204600d557f00000000000000000000000000000000000000000000000000000000000000016112255760405162ffffff821681527fd03edfeea801807308f0e9302e347c8a12ad32508cae5bce26e9e2a3654158c9906020016114a5565b6136738282614057565b60075461368b90600160281b900462ffffff16613e35565b6007546136a390600160401b900462ffffff166135b5565b6007546008546136c29162ffffff600160e81b909104811691166136e4565b6008546115b89062ffffff63010000008204811691600160301b900416613ddd565b600780546001600160e81b0316600160e81b62ffffff858116918202929092179092556008805462ffffff1916918416919091179055600a5461372b91620186a091020490565b600e55600a54620186a062ffffff929092160204600f5550565b60018360ff1611801561375e575060058263ffffffff16115b8015613773575062093a808163ffffffff1611155b61377b575f80fd5b6007805464ff000000001916600160201b60ff8616908102919091179091556008805463ffffffff60c81b1916600160c81b63ffffffff868116918202929092179092556009805463ffffffff19169185169182179055604080519384526020840192909252908201527f24b1343f86058af6b8e48d5f9ca6b4e206b72690500086e848cc587b2f4097149060600160405180910390a1505050565b602080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6007805461ff00191661010017905580158015613888575060075460ff16155b613c54575f806012541161389c575f6138b0565b6002601254816138ae576138ae614e9e565b045b601e54601a549192505f916001600160a01b039081169116146138d3575f6138d7565b6016545b9050818101831580156138eb5750600f5481115b15613954575f83116138fd575f613923565b600f546139239082620186a086028161391857613918614e9e565b04620186a091020490565b92505f8211613932575f61394d565b600f5461394d9082620186a085028161391857613918614e9e565b9150508181015b83806139625750600e548110155b801561397e5750305f9081526020819052604090205481840111155b15613b595760408051600280825260608201835247925f92919060208301908036833701905050905030815f815181106139ba576139ba614dca565b6001600160a01b039283166020918202929092010152601e548251911690829060019081106139eb576139eb614dca565b6001600160a01b039283166020918202929092010152601b54613a11913091168561274c565b601b5460405163791ac94760e01b81526001600160a01b039091169063791ac94790613a499086905f90869030904290600401614eef565b5f604051808303815f87803b158015613a60575f80fd5b505af1925050508015613a71575060015b613a9257601b54613a8d9030906001600160a01b03165f61274c565b613b56565b60125415613aa4576012805486900390555b604080518481524784900360208201819052917f9029ea20319a59447bd88162928acbbbe0955dead46655370929b794e46e8d96910160405180910390a18015613b5457613b008185620186a089028161391857613918614e9e565b601380549091019055601e54601a546001600160a01b03918216911603613b5457613b398185620186a088028161391857613918614e9e565b60188054909101905560178054860190556016805486900390555b505b50505b601a546001600160a01b03163014801590613b855750601e54601a546001600160a01b03908116911614155b15613c2957601654915083158015613b9e5750600f5482115b15613ba957600f5491505b8380613bb75750600e548210155b8015613bd15750305f908152602081905260409020548211155b15613c2957601a545f90613bee906001600160a01b0316846140f8565b90508015613c2757601a546001600160a01b03165f90815260056020526040902080548201905560178054840190556016805484900390555b505b505050613c358161436f565b6008805463ffffffff60881b19164263ffffffff16600160881b021790555b506007805461ff0019169055565b6007805463ff0000001916630100000017905560155415613dce575f805b60068160ff161015613d5e5760ff81165f908152600460205260409020805460038201546101009091046001600160a01b0316901580613cca57506001600160a01b03811661dead145b80613ce25750601c546001600160a01b038281169116145b15613cee575050613d56565b601a545f90613d2c906001600160a01b03163014613d0e57601754613d12565b6016545b6015546003860154620186a0028161391857613918614e9e565b90505f613d39838361451b565b90508015613d51576003840180548290039055948501945b505050505b600101613c80565b50600880546cffffffff0000000000000000001916690100000000000000000063ffffffff4216021790558015613dcc576015805482900390556040518181527fbb245b3c380b63918dc25ab2cc2e4b6939c4d58ffd95ea052b685a031e1ad2979060200160405180910390a15b505b6007805463ff00000019169055565b6008805468ffffffffffff0000001916630100000062ffffff94851690810268ffffff000000000000191691909117600160301b93909416928302939093179055600a54620186a09281028390046010550204601155565b60648162ffffff1610158015613e535750620186a062ffffff821611155b613e5b575f80fd5b6007805467ffffff00000000001916600160281b62ffffff841690810291909117909155600a54620186a0910204600c557f00000000000000000000000000000000000000000000000000000000000000016112255760405162ffffff821681527ff01936354f43c5b49521c6c3fdc9740709976ee07acac3ebf79fbd6282cda195906020016114a5565b60095463ffffffff16613efc63ffffffff421690565b6001600160a01b03929092165f908152600360205260409020805463ffffffff60501b1916600160501b9290930163ffffffff1691909102919091179055565b6001600160a01b03831615801590613f5c57506001600160a01b03821615155b613fa85760405162461bcd60e51b815260206004820152601d60248201527f5472616e736665722066726f6d2f746f207a65726f20616464726573730000006044820152606401610de2565b6001600160a01b0383165f90815260208190526040902054811115613fdf5760405162461bcd60e51b8152600401610de290614e27565b8015614012576001600160a01b038084165f90815260208190526040808220805485900390559184168152208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516127a091815260200190565b6001600160a01b0382165f9081526020819052604090205481111561408e5760405162461bcd60e51b8152600401610de290614e27565b6001600160a01b0382165f818152602081815260409182902080548590039055600a80548590039055600b805485019055905183815261dead92917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038516906370a0823190602401602060405180830381865afa15801561413e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141629190614e10565b604080516003808252608082019092529192505f91906020820160608036833701905050905030815f8151811061419b5761419b614dca565b6001600160a01b039283166020918202929092010152601e548251911690829060019081106141cc576141cc614dca565b60200260200101906001600160a01b031690816001600160a01b031681525050848160028151811061420057614200614dca565b6001600160a01b039283166020918202929092010152601b54614226913091168661274c565b601b54604051635c11d79560e01b81526001600160a01b0390911690635c11d7959061425e9087905f90869030904290600401614eef565b5f604051808303815f87803b158015614275575f80fd5b505af1925050508015614286575060015b6142a757601b546142a29030906001600160a01b03165f61274c565b614367565b6040516370a0823160e01b815230600482015282906001600160a01b038716906370a0823190602401602060405180830381865afa1580156142eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061430f9190614e10565b6143199190614f60565b604080516001600160a01b0388168152602081018790529081018290529093507fa82a03c1e8613c6192a82386fbb3690070528b0dd8bcae8a5c82d9ef937d7f769060600160405180910390a15b505092915050565b8015801561438a5750601054601254108061438a5750601354155b156143925750565b5f811580156143a45750601154601254115b6143b0576012546143b4565b6011545b90505f821580156143c85750601154601254115b6143d4576013546143fd565b6143fd601354601254601154816143ed576143ed614e9e565b04620186a002620186a091020490565b601b549091506144189030906001600160a01b03168461274c565b601b54601f5460405163f305d71960e01b8152306004820152602481018590525f6044820181905260648201526001600160a01b0391821660848201524260a482015291169063f305d71990839060c40160606040518083038185885af1935050505080156144a4575060408051601f3d908101601f191682019092526144a191810190614f73565b60015b6144c057601b5461177a9030906001600160a01b03165f61274c565b60408051848152602081018490529081018290527f947eb7d5785b0534dc368370fd3574434082455556a747116a88abea1ec6ceba9060600160405180910390a1505060128054849003905550601380548290039055505050565b5f815f0361452a57505f610ed5565b601a54306001600160a01b03909116036145f157600d546001600160a01b0384165f90815260208190526040902054830111801561458057506001600160a01b0383165f9081526002602052604090205460ff16155b156145d8576001600160a01b0383165f90815260208190526040902054600d54116145ab575f6145c8565b6001600160a01b0383165f90815260208190526040902054600d54035b9150815f036145d857505f610ed5565b6145e3308484613f3c565b60168054839003905561477a565b6017545f90620186a084028161460957614609614e9e565b601e54601a549290910492505f916001600160a01b039182169116036146ac57601854620186a09083020490505f856001600160a01b031682617530906040515f60405180830381858888f193505050503d805f8114614684576040519150601f19603f3d011682016040523d82523d5f602084013e614689565b606091505b505090508061469d575f9350505050610ed5565b5060188054829003905561476e565b601a546001600160a01b03165f90815260056020526040902054620186a090830204601a5460405163a9059cbb60e01b81526001600160a01b0388811660048301526024820184905292935091169063a9059cbb906044016020604051808303815f875af192505050801561473e575060408051601f3d908101601f1916820190925261473b91810190614e50565b60015b61474c575f92505050610ed5565b50601a546001600160a01b03165f908152600560205260409020805482900390555b50506017805483900390555b50919050565b60405180608001604052805f6001600160a01b031681526020016147a261484f565b81526020016147af61484f565b81526020015f81525090565b600183019183908215614843579160200282015f5b8382111561481257835183826101000a81548162ffffff021916908362ffffff16021790555092602001926003016020816002010492830192600103026147d0565b80156148415782816101000a81549062ffffff0219169055600301602081600201049283019260010302614812565b505b5061190c92915061486d565b60405180606001604052806003906020820280368337509192915050565b5b8082111561190c575f815560010161486e565b8015158114611225575f80fd5b5f805f604084860312156148a0575f80fd5b833567ffffffffffffffff808211156148b7575f80fd5b818601915086601f8301126148ca575f80fd5b8135818111156148d8575f80fd5b8760208260051b85010111156148ec575f80fd5b6020928301955093505084013561490281614881565b809150509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61494d602083018461490d565b9392505050565b6001600160a01b0381168114611225575f80fd5b5f8060408385031215614979575f80fd5b823561498481614954565b946020939093013593505050565b5f805f606084860312156149a4575f80fd5b83356149af81614954565b925060208401356149bf81614954565b929592945050506040919091013590565b803560ff811681146149e0575f80fd5b919050565b803562ffffff811681146149e0575f80fd5b5f82601f830112614a06575f80fd5b6040516060810181811067ffffffffffffffff82111715614a3557634e487b7160e01b5f52604160045260245ffd5b604052806060840185811115614a49575f80fd5b845b81811015614a6a57614a5c816149e5565b835260209283019201614a4b565b509195945050505050565b5f805f806101008587031215614a89575f80fd5b614a92856149d0565b93506020850135614aa281614954565b9250614ab186604087016149f7565b9150614ac08660a087016149f7565b905092959194509250565b5f60208284031215614adb575f80fd5b813561494d81614881565b803563ffffffff811681146149e0575f80fd5b5f60208284031215614b09575f80fd5b61494d82614ae6565b60c081525f614b2460c083018961490d565b8281036020840152614b36818961490d565b60ff881660408501526001600160a01b03871660608501526080840186905283810360a08501529050614b69818561490d565b9998505050505050505050565b5f60208284031215614b86575f80fd5b813561494d81614954565b5f60208284031215614ba1575f80fd5b61494d826149e5565b5f60208284031215614bba575f80fd5b5035919050565b5f8060408385031215614bd2575f80fd5b614bdb836149e5565b9150614be9602084016149e5565b90509250929050565b5f805f60608486031215614c04575f80fd5b614c0d846149d0565b9250614c1b60208501614ae6565b9150614c2960408501614ae6565b90509250925092565b805f5b600381101561106757815162ffffff16845260209384019390910190600101614c35565b602080825282518282018190525f919060409081850190868401855b82811015614ccb57815180516001600160a01b0316855286810151614c9c88870182614c32565b5085810151614cae6080870182614c32565b506060015160e08501526101009093019290850190600101614c75565b5091979650505050505050565b5f805f805f805f60e0888a031215614cee575f80fd5b8735614cf981614954565b96506020880135614d0981614954565b95506040880135945060608801359350614d25608089016149d0565b925060a0880135915060c0880135905092959891949750929550565b5f8060408385031215614d52575f80fd5b8235614d5d81614954565b91506020830135614d6d81614954565b809150509250929050565b5f8060408385031215614d89575f80fd5b8235614d9481614954565b91506020830135614d6d81614881565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680614df257607f821691505b60208210810361477a57634e487b7160e01b5f52602260045260245ffd5b5f60208284031215614e20575f80fd5b5051919050565b6020808252600f908201526e457863656564732062616c616e636560881b604082015260600190565b5f60208284031215614e60575f80fd5b815161494d81614881565b634e487b7160e01b5f52601160045260245ffd5b62ffffff81811683821602808216919082811461436757614367614e6b565b634e487b7160e01b5f52601260045260245ffd5b60ff851681526001600160a01b03841660208201526101008101614ed96040830185614c32565b614ee660a0830184614c32565b95945050505050565b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b81811015614f3f5784516001600160a01b031683529383019391830191600101614f1a565b50506001600160a01b03969096166060850152505050608001529392505050565b81810381811115610ed557610ed5614e6b565b5f805f60608486031215614f85575f80fd5b835192506020840151915060408401519050925092509256fea2646970667358221220fa50d9a2c712d18752455be43916af40de986f77031975d9a63eb2bcd0cf911b64736f6c63430008190033

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.