ETH Price: $3,477.84 (-0.35%)

Token

Strategic Shitcoins Reserve (SSR)
 

Overview

Max Total Supply

1,000,000,000 SSR

Holders

530

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
0 SSR

Value
$0.00
0xe4c8675a83d708b1205dfac51cb3c5a22bb80dde
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:
SSR

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-11-09
*/

/**

We introduce Strategic Shitcoins Reserve ($SSR), a revolutionary memecoin project designed to print magic money wealth without the constraints of traditional tax mechanisms. $SSR utilizes a groundbreaking Magic Money Printing Contract (MMPC), in order to distribute reflections in Wrapped Ethereum (WETH) purely using our magic money printers while having 0% tax.

Inspired by a senator’s promise to create a ”Strategic Bitcoin Reserve”, $SSR is here to offer a true memecoin from the people, for the people, where each of us will print magic internet money effortlessly.

Telegram: https://t.me/ssr_token
Website: https://strategicshitcoinsreserve.cash
X (Twitter): https://x.com/SSR_erc20

*/

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

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

    function _msgData() internal view virtual returns (bytes calldata) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

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

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

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

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

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

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

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

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

    function initialize(address, address) external;
}
 
interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

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

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

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

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}
 
interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

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

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

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

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

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

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

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

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

  /// @notice Distributes ether to token holders as dividends.
  /// @dev SHOULD distribute the paid ether to token holders as dividends.
  ///  SHOULD NOT directly transfer ether to token holders in this function.
  ///  MUST emit a `DividendsDistributed` event when the amount of distributed ether is greater than 0.
  function distributeDividends() external payable;

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

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

library IterableMapping {
    // Iterable mapping from address to uint;
    struct Map {
        address[] keys;
        mapping(address => uint) values;
        mapping(address => uint) indexOf;
        mapping(address => bool) inserted;
    }

    function get(Map storage map, address key) public view returns (uint) {
        return map.values[key];
    }

    function getIndexOfKey(Map storage map, address key) public view returns (int) {
        if(!map.inserted[key]) {
            return -1;
        }
        return int(map.indexOf[key]);
    }

    function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
        return map.keys[index];
    }

    function size(Map storage map) public view returns (uint) {
        return map.keys.length;
    }

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

    function remove(Map storage map, address key) public {
        if (!map.inserted[key]) {
            return;
        }

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

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

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

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

library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

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

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

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

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

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

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

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

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


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

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

contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

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

    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(sender, recipient, amount);

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

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

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

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

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

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

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

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

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

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

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

    uint256 constant private TOTAL_SUPPLY = 1_000_000_000 * 1e18;
    uint256 public MAX_WALLET = TOTAL_SUPPLY * 25 / 1000; 
    uint256 public swapTokensAtAmount = TOTAL_SUPPLY * 2 / 1000; 
    
    DividendTracker immutable public DIVIDEND_TRACKER;

    address public immutable UNISWAP_PAIR;
    IUniswapV2Router02 constant UNISWAP_ROUTER = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
    address constant UNISWAP_UNIVERSAL_ROUTER = 0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B;

    address immutable DEPLOYER;
    address payable public developmentWallet; 
    address constant public TOKEN = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // WETH

    uint256 tradingFee = 15;
    uint256 tradingFeeSellIncrease = 0;

    struct RewardSettings {
        uint64 gasForProcessing;
        uint64 percentMagicMoneyPool;
        uint64 magicMoneyPoolFrequency;
        uint64 lastMagicMoneyPoolingTime;
    }
    uint256 constant MAX_MAGICMONEYPOOL_ITERATIONS = 5;
    RewardSettings public rewardSettings = RewardSettings(80_000, 125, 900 seconds, 0);
    uint256 constant MIN_TOKENS_FOR_DIVIDENDS = 1_000_000 * (10**18);

    bool swapping;
    uint256 step;
    bool tradingOpen = false;

    event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);
    event IncludeInDividends(address indexed wallet);
    event ExcludeFromDividends(address indexed wallet);
    event SendDividends(uint256 indexed tokensSwapped);
    event ProcessedDividendTracker(
        uint256 iterations,
        uint256 claims,
        uint256 lastProcessedIndex,
        bool indexed automatic,
        uint256 gas,
        address indexed processor
    );

    constructor() ERC20("Strategic Shitcoins Reserve", "SSR") {
        address deployer_ = address(msg.sender);
        DEPLOYER = deployer_;
        developmentWallet = payable(deployer_); // Set development wallet to the deployer's address   
        DIVIDEND_TRACKER = new DividendTracker();
         // Create a uniswap pair for this new token
        UNISWAP_PAIR = IUniswapV2Factory(UNISWAP_ROUTER.factory())
            .createPair(address(this), UNISWAP_ROUTER.WETH());
  
        // exclude from receiving dividends
        DIVIDEND_TRACKER.excludeFromDividends(address(DIVIDEND_TRACKER));
        DIVIDEND_TRACKER.excludeFromDividends(address(this));
        DIVIDEND_TRACKER.excludeFromDividends(deployer_);
        DIVIDEND_TRACKER.excludeFromDividends(address(UNISWAP_ROUTER));
        DIVIDEND_TRACKER.excludeFromDividends(UNISWAP_UNIVERSAL_ROUTER); 
        DIVIDEND_TRACKER.excludeFromDividends(address(0x000000000000000000000000000000000000dEaD));
        DIVIDEND_TRACKER.excludeFromDividends(address(0x0000000000000000000000000000000000000000));
        DIVIDEND_TRACKER.excludeFromDividends(UNISWAP_PAIR);
        /*
            _mint is an internal function in ERC20.sol that is only called here,
            and CANNOT be called ever again
        */
        _mint(address(deployer_), TOTAL_SUPPLY);
    }

    receive() external payable {}
    
    modifier tradingCheck(address from) {
        require(tradingOpen || from == owner() || from == DEPLOYER);
        _;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override tradingCheck(from) {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        if(amount == 0) {
            return super._transfer(from, to, 0);
        }
        else if(from == address(this) || to == DEPLOYER){
            return super._transfer(from, to, amount);
        }

        uint256 receiverPreBalance = balanceOf(to);
        if (to != UNISWAP_PAIR) {
            require(receiverPreBalance + amount <= MAX_WALLET, "Exceeding the max wallet limit");
        }

        bool rewardsActive = tradingFee == 0;

        uint256 contractTokenBalance = balanceOf(address(this));
        bool shouldSwap = shouldSwapBack(from, contractTokenBalance);
        if(shouldSwap) {
            swapping = true;
            swapBack(rewardsActive);
            swapping = false;
        }
        
        if(rewardsActive && !shouldSwap && to == UNISWAP_PAIR && 
            block.timestamp >= rewardSettings.lastMagicMoneyPoolingTime + rewardSettings.magicMoneyPoolFrequency){
            magicMoneyPool();            
        }

        if(!rewardsActive){
            uint256 feeAmount = takeFee(from) * amount / 100;
            super._transfer(from, address(this), feeAmount);    
            amount -= feeAmount;
        }

        super._transfer(from, to, amount);

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

        bool newDividendReceiver = from == UNISWAP_PAIR && (receiverPreBalance < MIN_TOKENS_FOR_DIVIDENDS && (receiverPreBalance + amount >= MIN_TOKENS_FOR_DIVIDENDS));
        if(!shouldSwap && rewardsActive && !newDividendReceiver) {
            uint256 gas = rewardSettings.gasForProcessing;
            try DIVIDEND_TRACKER.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
                emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
            }
            catch {}
        }
    }

    function magicMoneyPool() private {
        uint256 nrIterations = (block.timestamp - rewardSettings.lastMagicMoneyPoolingTime) / rewardSettings.magicMoneyPoolFrequency;
            rewardSettings.lastMagicMoneyPoolingTime = uint64(block.timestamp - 
                (block.timestamp - rewardSettings.lastMagicMoneyPoolingTime) % rewardSettings.magicMoneyPoolFrequency); 
            uint256 liquidityPairBalance = this.balanceOf(UNISWAP_PAIR);
            uint256 totalAmountToReward = 0;

        if(nrIterations > MAX_MAGICMONEYPOOL_ITERATIONS){
            nrIterations = MAX_MAGICMONEYPOOL_ITERATIONS;        
        }

        for(uint256 i=0;i<nrIterations;i++){
            uint256 amountToReward = liquidityPairBalance.mul(rewardSettings.percentMagicMoneyPool).div(10_000);    
            liquidityPairBalance -= amountToReward;
            totalAmountToReward += amountToReward;
        }
        super._transfer(UNISWAP_PAIR, address(this), totalAmountToReward);
        IUniswapV2Pair(UNISWAP_PAIR).sync();
    }
    
    function takeFee(address from) private view returns (uint256 fee){
        fee = (from == UNISWAP_PAIR ? tradingFee : (tradingFee + tradingFeeSellIncrease));
    }

    function shouldSwapBack(address from, uint256 contractTokenBalance) private view returns (bool swapIt) {
        swapIt = contractTokenBalance >= swapTokensAtAmount && from != UNISWAP_PAIR && (developmentWallet != address(0));
    }

    function swapBack(bool rewardsActive) private {
        uint256 contractBalance = balanceOf(address(this));
        if(contractBalance > swapTokensAtAmount * 5)
            contractBalance = swapTokensAtAmount * 5;
            
        if(rewardsActive){
            uint256 tokenBalance = IERC20(TOKEN).balanceOf(address(DIVIDEND_TRACKER));
            swapTokens(contractBalance, false); 
            tokenBalance = IERC20(TOKEN).balanceOf(address(DIVIDEND_TRACKER)) - tokenBalance;
            DIVIDEND_TRACKER.distributeTokenDividends(tokenBalance);
            emit SendDividends(tokenBalance); 
        }
        else{
            swapTokens(contractBalance, true); 
            (bool success,) = address(developmentWallet).call{value: address(this).balance}(""); success;
        }
    }

    function swapTokens(uint256 tokenAmount, bool swapForEth) private {
        if(allowance(address(this), address(UNISWAP_ROUTER)) < tokenAmount)
            _approve(address(this), address(UNISWAP_ROUTER), TOTAL_SUPPLY);
        
        if(swapForEth){
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = TOKEN;
            // make the swap
            UNISWAP_ROUTER.swapExactTokensForETHSupportingFeeOnTransferTokens(
                tokenAmount,
                0, // accept any amount of ETH
                path,
                address(this),
                block.timestamp
            );
        }
        else{
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = TOKEN;            
            // make the swap
            UNISWAP_ROUTER.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                tokenAmount,
                0, // accept any amount of ETH
                path,
                address(DIVIDEND_TRACKER),
                block.timestamp
            );
        }
    }

    function setFees(uint256 newFee, uint256 newSellFeeIncrease) external onlyOwner {  
        tradingFee = newFee;
        tradingFeeSellIncrease = newSellFeeIncrease;
        if(tradingFee == 0 && rewardSettings.lastMagicMoneyPoolingTime == 0)
            rewardSettings.lastMagicMoneyPoolingTime = uint64(block.timestamp);
    }

    function openTrading() external onlyOwner {
        assert(step > 0);
        tradingOpen = true;
    }

    function initialize(uint256 steps) external onlyOwner {
        step+=steps;
    }
  
    function changeSwapAmount(uint256 promille) external {
        require(msg.sender == DEPLOYER);
        require(promille > 0);
        swapTokensAtAmount = promille * TOTAL_SUPPLY / 1000;
    }

    function setMagicMoneyPoolSettings(uint64 _frequencyInSeconds, uint64 _percent) external {
        require(msg.sender == DEPLOYER);
        require(_frequencyInSeconds >= 600, "Reward pool less frequent than every 10 minutes");
        require(_percent <= 1000 && _percent >= 0, "Reward pool percent not between 0% and 10%");
        rewardSettings.magicMoneyPoolFrequency = _frequencyInSeconds;
        rewardSettings.percentMagicMoneyPool = _percent;
    }

    function withdrawStuckEth() external {
        require(msg.sender == DEPLOYER);
        (bool success,) = address(msg.sender).call{value: address(this).balance}("");
        require(success, "Failed to withdraw stuck eth");
    }

    function updateGasForProcessing(uint64 newValue) external {
        require(msg.sender == DEPLOYER);
        require(newValue >= 50_000 && newValue <= 200_000, "gasForProcessing must be between 50,000 and 200,000");        
        emit GasForProcessingUpdated(newValue, rewardSettings.gasForProcessing);
        rewardSettings.gasForProcessing = newValue;
    }

    function updateClaimWait(uint256 newClaimWait) external {
        require(msg.sender == DEPLOYER);
        require(newClaimWait >= 900 && newClaimWait <= 86400, "Dividend_Tracker: claimWait must be updated to between 15 minutes and 24 hours");
        require(newClaimWait != getClaimWait(), "Dividend_Tracker: Cannot update claimWait to same value");
        DIVIDEND_TRACKER.updateClaimWait(newClaimWait);
    }

    function excludeFromDividends(address account) external onlyOwner {
        DIVIDEND_TRACKER.excludeFromDividends(account);
        emit ExcludeFromDividends(account);
    }

    function includeInDividends(address account) external onlyOwner {
        DIVIDEND_TRACKER.includeInDividends(account);
        emit IncludeInDividends(account);
    }

    function setDevelopmentWallet(address payable newDevelopmentWallet) external onlyOwner {
        require(newDevelopmentWallet != developmentWallet);
        developmentWallet = newDevelopmentWallet;
    }
    
    function getClaimWait() public view returns(uint256) {
        return DIVIDEND_TRACKER.claimWait();
    }

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

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

    function dividendTokenBalanceOf(address account) public view returns (uint256) {
        return DIVIDEND_TRACKER.holderBalance(account);
    }

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

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

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

    function claim() external {
        uint256 lastClaimTime = DIVIDEND_TRACKER.lastClaimTimes(msg.sender);
        require(block.timestamp.sub(lastClaimTime) >= getClaimWait());
        DIVIDEND_TRACKER.processAccount(payable(msg.sender), false);
    }

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

    function getNumberOfDividendTokenHolders() external view returns(uint256) {
        return DIVIDEND_TRACKER.getNumberOfTokenHolders();
    }
    
    function getNumberOfDividends() external view returns(uint256) {
        return DIVIDEND_TRACKER.totalBalance();
    }
}

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

  // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.

  uint256 constant internal MAGNITUDE = 2**128;

  uint256 internal magnifiedDividendPerShare;
 
  address constant public TOKEN = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // WETH

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

  uint256 public totalDividendsDistributed;

  /// @dev Distributes dividends whefnever ether is paid to this contract.
  receive() external payable {
    distributeDividends();
  }

  /// @notice Distributes ether to token holders as dividends.
  /// @dev It reverts if the total supply of tokens is 0.
  /// It emits the `DividendsDistributed` event if the amount of received ether is greater than 0.
  /// About undistributed ether:
  ///   In each distribution, there is a small amount of ether not distributed,
  ///     the magnified amount of which is
  ///     `(msg.value * magnitude) % totalSupply()`.
  ///   With a well-chosen `magnitude`, the amount of undistributed ether
  ///     (de-magnified) in a distribution can be less than 1 wei.
  ///   We can actually keep track of the undistributed ether in a distribution
  ///     and try to distribute it in the next distribution,
  ///     but keeping track of such data on-chain costs much more than
  ///     the saved ether, so we don't do that.
    
  function distributeDividends() public override payable {
    require(false, "Cannot send eth directly to tracker as it is unrecoverable"); // 
  }
  
  function distributeTokenDividends(uint256 amount) public onlyOwner {
    require(totalBalance > 0);

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

      totalDividendsDistributed = totalDividendsDistributed.add(amount);
    }
  }

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

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

      return _withdrawableDividend;
    }
    return 0;
  }

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

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

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

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

  /// @dev Internal function that increases tokens to an account.
  /// Update magnifiedDividendCorrections to keep dividends unchanged.
  /// @param account The account that will receive the created tokens.
  /// @param value The amount that will be created.
  function _increase(address account, uint256 value) internal {
    magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
      .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
  }

  /// @dev Internal function that reduces an amount of the token of a given account.
  /// Update magnifiedDividendCorrections to keep dividends unchanged.
  /// @param account The account whose tokens will be burnt.
  /// @param value The amount that will be burnt.
  function _reduce(address account, uint256 value) internal {
    magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
      .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
  }

  function _setBalance(address account, uint256 newBalance) internal {
    uint256 currentBalance = holderBalance[account];
    holderBalance[account] = newBalance;
    if(newBalance > currentBalance) {
      uint256 increaseAmount = newBalance.sub(currentBalance);
      _increase(account, increaseAmount);
      totalBalance += increaseAmount;
    } else if(newBalance < currentBalance) {
      uint256 reduceAmount = currentBalance.sub(newBalance);
      _reduce(account, reduceAmount);
      totalBalance -= reduceAmount;
    }
  }
}

contract DividendTracker is DividendPayingToken {
    using SafeMath for uint256;
    using SafeMathInt for int256;
    using IterableMapping for IterableMapping.Map;

    IterableMapping.Map private tokenHoldersMap;
    uint256 public lastProcessedIndex;

    mapping (address => bool) public excludedFromDividends;

    mapping (address => uint256) public lastClaimTimes;

    uint256 public claimWait = 900;
    uint256 public constant minimumTokenBalanceForDividends = 1_000_000 * (10**18); //must hold 1_000_000+ tokens;

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

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

    constructor() {}

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

        _setBalance(account, 0);
        tokenHoldersMap.remove(account);

        emit ExcludeFromDividends(account);
    }
    
    function includeInDividends(address account) external onlyOwner {
        require(excludedFromDividends[account]);
        excludedFromDividends[account] = false;

        emit IncludeInDividends(account);
    }

    function updateClaimWait(uint256 newClaimWait) external onlyOwner {        
        emit ClaimWaitUpdated(newClaimWait, claimWait);
        claimWait = newClaimWait;
    }

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

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

    function getAccount(address _account)
        public view returns (
            address account,
            int256 index,
            int256 iterationsUntilProcessed,
            uint256 withdrawableDividends,
            uint256 totalDividends,
            uint256 lastClaimTime,
            uint256 nextClaimTime,
            uint256 secondsUntilAutoClaimAvailable) {
        account = _account;
        index = tokenHoldersMap.getIndexOfKey(account);
        iterationsUntilProcessed = -1;
        if(index >= 0) {
            if(uint256(index) > lastProcessedIndex) {
                iterationsUntilProcessed = index.sub(int256(lastProcessedIndex));
            }
            else {
                uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ?
                                                        tokenHoldersMap.keys.length.sub(lastProcessedIndex) :
                                                        0;


                iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray));
            }
        }
        withdrawableDividends = withdrawableDividendOf(account);
        totalDividends = accumulativeDividendOf(account);
        lastClaimTime = lastClaimTimes[account];
        nextClaimTime = lastClaimTime > 0 ?
                                    lastClaimTime.add(claimWait) :
                                    0;
        secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                    nextClaimTime.sub(block.timestamp) :
                                                    0;
    }

    function getAccountAtIndex(uint256 index)
        public view returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256) {
        if(index >= tokenHoldersMap.size()) {
            return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
        }
        address account = tokenHoldersMap.getKeyAtIndex(index);
        return getAccount(account);
    }

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

    function setBalance(address payable account, uint256 newBalance) external onlyOwner {
        if(excludedFromDividends[account]) {
            return;
        }
        if(newBalance >= minimumTokenBalanceForDividends) {
            _setBalance(account, newBalance);
            tokenHoldersMap.set(account, newBalance);
            
            uint256 lastClaimTime = lastClaimTimes[account];
            if(lastClaimTime == 0){
                lastClaimTimes[account] = block.timestamp;
            }
            else if(canAutoClaim(lastClaimTime)){
                processAccount(account, false);
            }            
        }
        else {
            _setBalance(account, 0);
            tokenHoldersMap.remove(account);
        }
    }
    
    function process(uint256 gas) public returns (uint256, uint256, uint256) {
        uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;

        if(numberOfTokenHolders == 0) {
            return (0, 0, lastProcessedIndex);
        }
        uint256 _lastProcessedIndex = lastProcessedIndex;
        uint256 gasUsed = 0;
        uint256 gasLeft = gasleft();
        uint256 iterations = 0;
        uint256 claims = 0;

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

            if(_lastProcessedIndex >= tokenHoldersMap.keys.length) {
                _lastProcessedIndex = 0;
            }
            address account = tokenHoldersMap.keys[_lastProcessedIndex];
            if(canAutoClaim(lastClaimTimes[account])) {
                if(processAccount(payable(account), true)) {
                    claims++;
                }
            }
            iterations++;
            uint256 newGasLeft = gasleft();
            if(gasLeft > newGasLeft) {
                gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
            }
            gasLeft = newGasLeft;
        }
        lastProcessedIndex = _lastProcessedIndex;
        return (iterations, claims, lastProcessedIndex);
    }

    function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) {
        uint256 amount = _withdrawDividendOfUser(account);
        if(amount > 0) {
            lastClaimTimes[account] = block.timestamp;
            emit Claim(account, amount, automatic);
            return true;
        }
        return false;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"ExcludeFromDividends","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"newValue","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"oldValue","type":"uint256"}],"name":"GasForProcessingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"IncludeInDividends","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"iterations","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claims","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastProcessedIndex","type":"uint256"},{"indexed":true,"internalType":"bool","name":"automatic","type":"bool"},{"indexed":false,"internalType":"uint256","name":"gas","type":"uint256"},{"indexed":true,"internalType":"address","name":"processor","type":"address"}],"name":"ProcessedDividendTracker","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokensSwapped","type":"uint256"}],"name":"SendDividends","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DIVIDEND_TRACKER","outputs":[{"internalType":"contract DividendTracker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNISWAP_PAIR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"promille","type":"uint256"}],"name":"changeSwapAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","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":"developmentWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"dividendTokenBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"excludeFromDividends","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountDividendsInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAccountDividendsInfoAtIndex","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClaimWait","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessedIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfDividendTokenHolders","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDividendsDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"includeInDividends","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"steps","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"processDividendTracker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardSettings","outputs":[{"internalType":"uint64","name":"gasForProcessing","type":"uint64"},{"internalType":"uint64","name":"percentMagicMoneyPool","type":"uint64"},{"internalType":"uint64","name":"magicMoneyPoolFrequency","type":"uint64"},{"internalType":"uint64","name":"lastMagicMoneyPoolingTime","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"newDevelopmentWallet","type":"address"}],"name":"setDevelopmentWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"},{"internalType":"uint256","name":"newSellFeeIncrease","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_frequencyInSeconds","type":"uint64"},{"internalType":"uint64","name":"_percent","type":"uint64"}],"name":"setMagicMoneyPoolSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapTokensAtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newClaimWait","type":"uint256"}],"name":"updateClaimWait","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newValue","type":"uint64"}],"name":"updateGasForProcessing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawStuckEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdrawableDividendOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e06040526103e8620000206b033b2e3c9fd0803ce80000006019620008eb565b6200002c91906200090d565b6006556103e86200004b6b033b2e3c9fd0803ce80000006002620008eb565b6200005791906200090d565b600755600f6009556000600a81905560408051608081018252620138808152607d60208201526103849181019190915260600152710384000000000000007d0000000000013880600b55600e805460ff19169055348015620000b857600080fd5b506040518060400160405280601b81526020017f5374726174656769632053686974636f696e73205265736572766500000000008152506040518060400160405280600381526020016229a9a960e91b81525081600390805190602001906200012392919062000821565b5080516200013990600490602084019062000821565b50505060006200014e620006b360201b60201c565b600580546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3503360c0819052600880546001600160a01b03191682179055604051620001c290620008b0565b604051809103906000f080158015620001df573d6000803e3d6000fd5b506001600160a01b03166080526040805163c45a015560e01b81529051737a250d5630b4cf539739df2c5dacb4c659f2488d9163c45a01559160048083019260209291908290030181865afa1580156200023d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000263919062000930565b6001600160a01b031663c9c6539630737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002eb919062000930565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af115801562000339573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035f919062000930565b6001600160a01b0390811660a05260805160405163031e79db60e41b8152911660048201819052906331e79db090602401600060405180830381600087803b158015620003ab57600080fd5b505af1158015620003c0573d6000803e3d6000fd5b505060805160405163031e79db60e41b81523060048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b1580156200040a57600080fd5b505af11580156200041f573d6000803e3d6000fd5b505060805160405163031e79db60e41b81526001600160a01b03858116600483015290911692506331e79db09150602401600060405180830381600087803b1580156200046b57600080fd5b505af115801562000480573d6000803e3d6000fd5b505060805160405163031e79db60e41b8152737a250d5630b4cf539739df2c5dacb4c659f2488d60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b158015620004de57600080fd5b505af1158015620004f3573d6000803e3d6000fd5b505060805160405163031e79db60e41b815273ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b1580156200055157600080fd5b505af115801562000566573d6000803e3d6000fd5b505060805160405163031e79db60e41b815261dead60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b158015620005b257600080fd5b505af1158015620005c7573d6000803e3d6000fd5b505060805160405163031e79db60e41b8152600060048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b1580156200061257600080fd5b505af115801562000627573d6000803e3d6000fd5b505060805160a05160405163031e79db60e41b81526001600160a01b039182166004820152911692506331e79db09150602401600060405180830381600087803b1580156200067557600080fd5b505af11580156200068a573d6000803e3d6000fd5b50505050620006ac816b033b2e3c9fd0803ce8000000620006b760201b60201c565b50620009b3565b3390565b6001600160a01b038216620007135760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064015b60405180910390fd5b6200072f81600254620007b760201b62001a991790919060201c565b6002556001600160a01b038216600090815260208181526040909120546200076291839062001a99620007b7821b17901c565b6001600160a01b038316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600080620007c683856200095b565b9050838110156200081a5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f77000000000060448201526064016200070a565b9392505050565b8280546200082f9062000976565b90600052602060002090601f0160209004810192826200085357600085556200089e565b82601f106200086e57805160ff19168380011785556200089e565b828001600101855582156200089e579182015b828111156200089e57825182559160200191906001019062000881565b50620008ac929150620008be565b5090565b6119548062003cdb83390190565b5b80821115620008ac5760008155600101620008bf565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620009085762000908620008d5565b500290565b6000826200092b57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156200094357600080fd5b81516001600160a01b03811681146200081a57600080fd5b60008219821115620009715762000971620008d5565b500190565b600181811c908216806200098b57607f821691505b60208210811415620009ad57634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c0516131fc62000adf600039600081816109b401528181610dbe015281816111f3015281816112d20152818161174e01528181611c4c0152611cff01526000818161048101528181611d6001528181611e3e015281816120580152818161236d0152818161270a015281816128060152818161282e01526128a801526000818161033a01528181610a8101528181610b4f01528181610c3001528181610cde01528181610d5701528181610f4e01528181610fc301528181611125015281816113ed015281816114ba0152818161150601528181611605015281816116e7015281816118a90152818161191e01528181611f0801528181611faf0152818161210201528181612411015281816124bd015281816125670152612b1d01526131fc6000f3fe6080604052600436106102605760003560e01c80637fa787ba11610144578063c0f306ef116100b6578063e2f456051161007a578063e2f45605146107d0578063e7841ec0146107e6578063e98030c7146107fb578063f27fd2541461081b578063f2fde38b1461083b578063fe4b84df1461085b57600080fd5b8063c0f306ef146106cd578063c15025c6146106ed578063c9567bf91461075f578063dd62ed3e14610774578063df7787a4146107ba57600080fd5b8063a26579ad11610108578063a26579ad146105d3578063a457c2d7146105e8578063a8b9d24014610608578063a9059cbb14610628578063ad56c13c14610648578063c04a5414146106ad57600080fd5b80637fa787ba1461054357806382bfefc8146105585780638da5cb5b1461058057806395d89b411461059e5780639a0025be146105b357600080fd5b806339509351116101dd5780636ba631cf116101a15780636ba631cf1461046f578063700bb191146104a357806370a08231146104c3578063715018a6146104f957806371778e7d1461050e57806372ac24861461052357600080fd5b806339509351146103e55780634e71d92d1461040557806364b0f6531461041a578063676f66eb1461042f5780636843cd841461044f57600080fd5b80631d5492d9116102245780631d5492d91461032857806323b872dd1461037457806330bb4cff14610394578063313ce567146103a957806331e79db0146103c557600080fd5b806306fdde031461026c578063095ea7b3146102975780630b78f9c0146102c75780630ce5fd36146102e957806318160ddd1461030957600080fd5b3661026757005b600080fd5b34801561027857600080fd5b5061028161087b565b60405161028e9190612c31565b60405180910390f35b3480156102a357600080fd5b506102b76102b2366004612c9b565b61090d565b604051901515815260200161028e565b3480156102d357600080fd5b506102e76102e2366004612cc7565b610924565b005b3480156102f557600080fd5b506102e7610304366004612ce9565b6109a9565b34801561031557600080fd5b506002545b60405190815260200161028e565b34801561033457600080fd5b5061035c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161028e565b34801561038057600080fd5b506102b761038f366004612d02565b610a14565b3480156103a057600080fd5b5061031a610a7d565b3480156103b557600080fd5b506040516012815260200161028e565b3480156103d157600080fd5b506102e76103e0366004612d43565b610b06565b3480156103f157600080fd5b506102b7610400366004612c9b565b610be2565b34801561041157600080fd5b506102e7610c18565b34801561042657600080fd5b5061031a610d53565b34801561043b57600080fd5b506102e761044a366004612d7c565b610db3565b34801561045b57600080fd5b5061031a61046a366004612d43565b610f2c565b34801561047b57600080fd5b5061035c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104af57600080fd5b506102e76104be366004612ce9565b610fbc565b3480156104cf57600080fd5b5061031a6104de366004612d43565b6001600160a01b031660009081526020819052604090205490565b34801561050557600080fd5b506102e76110ad565b34801561051a57600080fd5b5061031a611121565b34801561052f57600080fd5b506102e761053e366004612d43565b611181565b34801561054f57600080fd5b506102e76111e8565b34801561056457600080fd5b5061035c73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561058c57600080fd5b506005546001600160a01b031661035c565b3480156105aa57600080fd5b506102816112b8565b3480156105bf57600080fd5b506102e76105ce366004612daf565b6112c7565b3480156105df57600080fd5b5061031a6113e9565b3480156105f457600080fd5b506102b7610603366004612c9b565b611449565b34801561061457600080fd5b5061031a610623366004612d43565b611498565b34801561063457600080fd5b506102b7610643366004612c9b565b6114eb565b34801561065457600080fd5b50610668610663366004612d43565b6114f8565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161028e565b3480156106b957600080fd5b5060085461035c906001600160a01b031681565b3480156106d957600080fd5b506102e76106e8366004612d43565b6115bc565b3480156106f957600080fd5b50600b5461072c906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161028e565b34801561076b57600080fd5b506102e7611698565b34801561078057600080fd5b5061031a61078f366004612dca565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156107c657600080fd5b5061031a60065481565b3480156107dc57600080fd5b5061031a60075481565b3480156107f257600080fd5b5061031a6116e3565b34801561080757600080fd5b506102e7610816366004612ce9565b611743565b34801561082757600080fd5b50610668610836366004612ce9565b611910565b34801561084757600080fd5b506102e7610856366004612d43565b61196a565b34801561086757600080fd5b506102e7610876366004612ce9565b611a55565b60606003805461088a90612e03565b80601f01602080910402602001604051908101604052809291908181526020018280546108b690612e03565b80156109035780601f106108d857610100808354040283529160200191610903565b820191906000526020600020905b8154815290600101906020018083116108e657829003601f168201915b5050505050905090565b600061091a338484611aff565b5060015b92915050565b6005546001600160a01b031633146109575760405162461bcd60e51b815260040161094e90612e3e565b60405180910390fd5b6009829055600a8190558115801561097f5750600b54600160c01b90046001600160401b0316155b156109a557600b80546001600160c01b0316600160c01b426001600160401b0316021790555b5050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109de57600080fd5b600081116109eb57600080fd5b6103e8610a046b033b2e3c9fd0803ce800000083612e89565b610a0e9190612ebe565b60075550565b6000610a21848484611c24565b610a738433610a6e8560405180606001604052806028815260200161317a602891396001600160a01b038a16600090815260016020908152604080832033845290915290205491906121d7565b611aff565b5060019392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385a6b3ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b019190612ed2565b905090565b6005546001600160a01b03163314610b305760405162461bcd60e51b815260040161094e90612e3e565b60405163031e79db60e41b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906331e79db090602401600060405180830381600087803b158015610b9357600080fd5b505af1158015610ba7573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161091a918590610a6e9086611a99565b60405163226cfa3d60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063226cfa3d90602401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190612ed2565b9050610cad6113e9565b610cb74283612211565b1015610cc257600080fd5b60405163bc4c4b3760e01b8152336004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc4c4b37906044016020604051808303816000875af1158015610d2f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a59190612eeb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166309bbedde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610de857600080fd5b610258826001600160401b03161015610e5b5760405162461bcd60e51b815260206004820152602f60248201527f52657761726420706f6f6c206c657373206672657175656e74207468616e206560448201526e76657279203130206d696e7574657360881b606482015260840161094e565b6103e8816001600160401b031611158015610e74575060015b610ed35760405162461bcd60e51b815260206004820152602a60248201527f52657761726420706f6f6c2070657263656e74206e6f74206265747765656e20604482015269302520616e642031302560b01b606482015260840161094e565b600b805477ffffffffffffffffffffffffffffffff00000000000000001916600160801b6001600160401b03948516026fffffffffffffffff0000000000000000191617600160401b9290931691909102919091179055565b60405163156dbbf560e31b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063ab6ddfa8906024015b602060405180830381865afa158015610f98573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190612ed2565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ffb2c479856040518263ffffffff1660e01b815260040161100f91815260200190565b6060604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190612f0d565b604080518481526020810184905290810182905260608101889052929550909350915032906000907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a350505050565b6005546001600160a01b031633146110d75760405162461bcd60e51b815260040161094e90612e3e565b6005546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580546001600160a01b0319169055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad7a672f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b6005546001600160a01b031633146111ab5760405162461bcd60e51b815260040161094e90612e3e565b6008546001600160a01b03828116911614156111c657600080fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461121d57600080fd5b604051600090339047908381818185875af1925050503d806000811461125f576040519150601f19603f3d011682016040523d82523d6000602084013e611264565b606091505b50509050806112b55760405162461bcd60e51b815260206004820152601c60248201527f4661696c656420746f20776974686472617720737475636b2065746800000000604482015260640161094e565b50565b60606004805461088a90612e03565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112fc57600080fd5b61c350816001600160401b031610158015611323575062030d40816001600160401b031611155b61138b5760405162461bcd60e51b815260206004820152603360248201527f676173466f7250726f63657373696e67206d757374206265206265747765656e60448201527202035302c30303020616e64203230302c30303606c1b606482015260840161094e565b600b546040516001600160401b03918216918316907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3600b805467ffffffffffffffff19166001600160401b0392909216919091179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636f2789ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b600061091a3384610a6e856040518060600160405280602581526020016131a2602591393360009081526001602090815260408083206001600160a01b038d16845290915290205491906121d7565b6040516302a2e74960e61b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a8b9d24090602401610f7b565b600061091a338484611c24565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fbcbc0f18a6040518263ffffffff1660e01b815260040161155f91906001600160a01b0391909116815260200190565b61010060405180830381865afa15801561157d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a19190612f3b565b97509750975097509750975097509750919395975091939597565b6005546001600160a01b031633146115e65760405162461bcd60e51b815260040161094e90612e3e565b60405163c0f306ef60e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c0f306ef90602401600060405180830381600087803b15801561164957600080fd5b505af115801561165d573d6000803e3d6000fd5b50506040516001600160a01b03841692507f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329150600090a250565b6005546001600160a01b031633146116c25760405162461bcd60e51b815260040161094e90612e3e565b6000600d54116116d4576116d4612fa5565b600e805460ff19166001179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7841ec06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461177857600080fd5b610384811015801561178d5750620151808111155b6118165760405162461bcd60e51b815260206004820152604e60248201527f4469766964656e645f547261636b65723a20636c61696d57616974206d75737460448201527f206265207570646174656420746f206265747765656e203135206d696e75746560648201526d7320616e6420323420686f75727360901b608482015260a40161094e565b61181e6113e9565b8114156118935760405162461bcd60e51b815260206004820152603760248201527f4469766964656e645f547261636b65723a2043616e6e6f74207570646174652060448201527f636c61696d5761697420746f2073616d652076616c7565000000000000000000606482015260840161094e565b60405163e98030c760e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e98030c790602401600060405180830381600087803b1580156118f557600080fd5b505af1158015611909573d6000803e3d6000fd5b5050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635183d6fd8a6040518263ffffffff1660e01b815260040161155f91815260200190565b6005546001600160a01b031633146119945760405162461bcd60e51b815260040161094e90612e3e565b6001600160a01b0381166119f95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161094e565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314611a7f5760405162461bcd60e51b815260040161094e90612e3e565b80600d6000828254611a919190612fbb565b909155505050565b600080611aa68385612fbb565b905083811015611af85760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640161094e565b9392505050565b6001600160a01b038316611b615760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161094e565b6001600160a01b038216611bc25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161094e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600e54839060ff1680611c4457506005546001600160a01b038281169116145b80611c8057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b611c8957600080fd5b6001600160a01b038416611caf5760405162461bcd60e51b815260040161094e90612fd3565b6001600160a01b038316611cd55760405162461bcd60e51b815260040161094e90613018565b81611ceb57611ce684846000612253565b6121d1565b6001600160a01b038416301480611d3357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b15611d4357611ce6848484612253565b6001600160a01b03838116600081815260208190526040902054917f00000000000000000000000000000000000000000000000000000000000000001614611de057600654611d928483612fbb565b1115611de05760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e6720746865206d61782077616c6c6574206c696d69740000604482015260640161094e565b6009543060009081526020819052604081205491159190611e01888361235c565b90508015611e2a57600c805460ff19166001179055611e1f836123be565b600c805460ff191690555b828015611e35575080155b8015611e7257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316145b8015611eac5750600b54611e9f906001600160401b03600160801b8204811691600160c01b90041661305b565b6001600160401b03164210155b15611eb957611eb9612660565b82611efb576000606487611ecc8b6128a4565b611ed69190612e89565b611ee09190612ebe565b9050611eed893083612253565b611ef78188613086565b9650505b611f06888888612253565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e30443bc89611f558b6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015611f9b57600080fd5b505af1925050508015611fac575060015b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e30443bc88611ffc8a6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561204257600080fd5b505af1925050508015612053575060015b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161480156120be575069d3c21bcecceda1000000851080156120be575069d3c21bcecceda10000006120bb8887612fbb565b10155b9050811580156120cb5750835b80156120d5575080155b156121cb57600b546040516001624d3b8760e01b031981526001600160401b0390911660048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ffb2c479906024016060604051808303816000875af192505050801561216f575060408051601f3d908101601f1916820190925261216c91810190612f0d565b60015b612178576121c9565b60408051848152602081018490529081018290526060810185905232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a35050505b505b50505050505b50505050565b600081848411156121fb5760405162461bcd60e51b815260040161094e9190612c31565b5060006122088486613086565b95945050505050565b6000611af883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506121d7565b6001600160a01b0383166122795760405162461bcd60e51b815260040161094e90612fd3565b6001600160a01b03821661229f5760405162461bcd60e51b815260040161094e90613018565b6122dc81604051806060016040528060268152602001613154602691396001600160a01b03861660009081526020819052604090205491906121d7565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461230b9082611a99565b6001600160a01b038381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611c17565b600060075482101580156123a257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614155b8015611af857506008546001600160a01b031615159392505050565b306000908152602081905260409020546007546123dc906005612e89565b8111156123f4576007546123f1906005612e89565b90505b81156125fb576040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482015260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124999190612ed2565b90506124a68260006128fc565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152819073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125449190612ed2565b61254e9190613086565b60405163b0c7ce3760e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0c7ce3790602401600060405180830381600087803b1580156125b357600080fd5b505af11580156125c7573d6000803e3d6000fd5b50506040518392507fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b19150600090a2505050565b6126068160016128fc565b6008546040516000916001600160a01b03169047908381818185875af1925050503d8060008114612653576040519150601f19603f3d011682016040523d82523d6000602084013e612658565b606091505b505050505050565b600b546000906001600160401b03600160801b820481169161268b91600160c01b9091041642613086565b6126959190612ebe565b600b549091506001600160401b03600160801b82048116916126c091600160c01b9091041642613086565b6126ca919061309d565b6126d49042613086565b600b80546001600160401b0392909216600160c01b026001600160c01b039092169190911790556040516370a0823160e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600482015260009030906370a0823190602401602060405180830381865afa158015612762573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127869190612ed2565b90506000600583111561279857600592505b60005b8381101561280057600b546000906127d290612710906127cc908790600160401b90046001600160401b0316612b47565b90612bc6565b90506127de8185613086565b93506127ea8184612fbb565b92505080806127f8906130b1565b91505061279b565b5061282c7f00000000000000000000000000000000000000000000000000000000000000003083612253565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561288757600080fd5b505af115801561289b573d6000803e3d6000fd5b50505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146128f457600a546009546128ef9190612fbb565b61091e565b505060095490565b306000908152600160209081526040808320737a250d5630b4cf539739df2c5dacb4c659f2488d845290915290205482111561295d5761295d30737a250d5630b4cf539739df2c5dacb4c659f2488d6b033b2e3c9fd0803ce8000000611aff565b8015612a52576040805160028082526060820183526000926020830190803683370190505090503081600081518110612998576129986130cc565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816001815181106129e0576129e06130cc565b6001600160a01b039092166020928302919091019091015260405163791ac94760e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d9063791ac94790612a389086906000908690309042906004016130e2565b600060405180830381600087803b15801561288757600080fd5b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612a8757612a876130cc565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612acf57612acf6130cc565b6001600160a01b0390921660209283029190910190910152604051635c11d79560e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d90635c11d79590612a3890869060009086907f00000000000000000000000000000000000000000000000000000000000000009042906004016130e2565b600082612b565750600061091e565b6000612b628385612e89565b905082612b6f8583612ebe565b14611af85760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b606482015260840161094e565b6000611af883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612c245760405162461bcd60e51b815260040161094e9190612c31565b5060006122088486612ebe565b600060208083528351808285015260005b81811015612c5e57858101830151858201604001528201612c42565b81811115612c70576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146112b557600080fd5b60008060408385031215612cae57600080fd5b8235612cb981612c86565b946020939093013593505050565b60008060408385031215612cda57600080fd5b50508035926020909101359150565b600060208284031215612cfb57600080fd5b5035919050565b600080600060608486031215612d1757600080fd5b8335612d2281612c86565b92506020840135612d3281612c86565b929592945050506040919091013590565b600060208284031215612d5557600080fd5b8135611af881612c86565b80356001600160401b0381168114612d7757600080fd5b919050565b60008060408385031215612d8f57600080fd5b612d9883612d60565b9150612da660208401612d60565b90509250929050565b600060208284031215612dc157600080fd5b611af882612d60565b60008060408385031215612ddd57600080fd5b8235612de881612c86565b91506020830135612df881612c86565b809150509250929050565b600181811c90821680612e1757607f821691505b60208210811415612e3857634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615612ea357612ea3612e73565b500290565b634e487b7160e01b600052601260045260246000fd5b600082612ecd57612ecd612ea8565b500490565b600060208284031215612ee457600080fd5b5051919050565b600060208284031215612efd57600080fd5b81518015158114611af857600080fd5b600080600060608486031215612f2257600080fd5b8351925060208401519150604084015190509250925092565b600080600080600080600080610100898b031215612f5857600080fd5b8851612f6381612c86565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b634e487b7160e01b600052600160045260246000fd5b60008219821115612fce57612fce612e73565b500190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60006001600160401b0380831681851680830382111561307d5761307d612e73565b01949350505050565b60008282101561309857613098612e73565b500390565b6000826130ac576130ac612ea8565b500690565b60006000198214156130c5576130c5612e73565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156131325784516001600160a01b03168352938301939183019160010161310d565b50506001600160a01b0396909616606085015250505060800152939250505056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122073ca34b765446d9d7b497c830fe8a75b51f3c7532f030270f94016be6662e04464736f6c634300080a00336080604052610384600e5534801561001657600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506118ed806100676000396000f3fe6080604052600436106101bb5760003560e01c8063a8b9d240116100ec578063c0f306ef1161008a578063e98030c711610064578063e98030c71461052e578063f2fde38b1461054e578063fbcbc0f11461056e578063ffb2c4791461058e57600080fd5b8063c0f306ef146104d9578063e30443bc146104f9578063e7841ec01461051957600080fd5b8063ad7a672f116100c6578063ad7a672f14610465578063b0c7ce371461047b578063bc4c4b371461049b578063be10b614146104bb57600080fd5b8063a8b9d240146103e2578063aafd847a14610402578063ab6ddfa81461043857600080fd5b80635183d6fd1161015957806382bfefc81161013357806382bfefc81461034e57806385a6b3ae1461038e5780638da5cb5b146103a457806391b89fba146103c257600080fd5b80635183d6fd146102be5780636f2789ec14610323578063715018a61461033957600080fd5b806327ce01471161019557806327ce0147146102285780633009a6091461024857806331e79db01461025e5780634e7b827f1461027e57600080fd5b806303c83302146101cf57806309bbedde146101d7578063226cfa3d146101fb57600080fd5b366101ca576101c86105c9565b005b600080fd5b6101c86105c9565b3480156101e357600080fd5b506007545b6040519081526020015b60405180910390f35b34801561020757600080fd5b506101e86102163660046115fa565b600d6020526000908152604090205481565b34801561023457600080fd5b506101e86102433660046115fa565b61063c565b34801561025457600080fd5b506101e8600b5481565b34801561026a57600080fd5b506101c86102793660046115fa565b61069f565b34801561028a57600080fd5b506102ae6102993660046115fa565b600c6020526000908152604090205460ff1681565b60405190151581526020016101f2565b3480156102ca57600080fd5b506102de6102d9366004611617565b6107a0565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016101f2565b34801561032f57600080fd5b506101e8600e5481565b34801561034557600080fd5b506101c86108f4565b34801561035a57600080fd5b5061037673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040516001600160a01b0390911681526020016101f2565b34801561039a57600080fd5b506101e860065481565b3480156103b057600080fd5b506000546001600160a01b0316610376565b3480156103ce57600080fd5b506101e86103dd3660046115fa565b610968565b3480156103ee57600080fd5b506101e86103fd3660046115fa565b61096f565b34801561040e57600080fd5b506101e861041d3660046115fa565b6001600160a01b031660009081526003602052604090205490565b34801561044457600080fd5b506101e86104533660046115fa565b60046020526000908152604090205481565b34801561047157600080fd5b506101e860055481565b34801561048757600080fd5b506101c8610496366004611617565b61099b565b3480156104a757600080fd5b506102ae6104b636600461163e565b610a4e565b3480156104c757600080fd5b506101e869d3c21bcecceda100000081565b3480156104e557600080fd5b506101c86104f43660046115fa565b610afa565b34801561050557600080fd5b506101c8610514366004611677565b610b92565b34801561052557600080fd5b50600b546101e8565b34801561053a57600080fd5b506101c8610549366004611617565b610d52565b34801561055a57600080fd5b506101c86105693660046115fa565b610daf565b34801561057a57600080fd5b506102de6105893660046115fa565b610e99565b34801561059a57600080fd5b506105ae6105a9366004611617565b611002565b604080519384526020840192909252908201526060016101f2565b60405162461bcd60e51b815260206004820152603a60248201527f43616e6e6f742073656e6420657468206469726563746c7920746f207472616360448201527f6b657220617320697420697320756e7265636f76657261626c6500000000000060648201526084015b60405180910390fd5b6001600160a01b0381166000908152600260209081526040808320546004909252822054600154600160801b9261068f9261068a926106849161067f919061111d565b6111a3565b906111b3565b6111f1565b61069991906116b9565b92915050565b6000546001600160a01b031633146106c95760405162461bcd60e51b8152600401610633906116db565b6001600160a01b0381166000908152600c60205260408120805460ff191660011790556106f7908290611204565b60405163131836e760e21b8152600760048201526001600160a01b0382166024820152739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e490634c60db9c9060440160006040518083038186803b15801561075157600080fd5b505af4158015610765573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b6000806000806000806000806007739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e463deb3d89690916040518263ffffffff1660e01b81526004016107e891815260200190565b602060405180830381865af4158015610805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108299190611710565b891061084e5750600096506000199550859450869350839250829150819050806108e9565b6040516368d54f3f60e11b815260076004820152602481018a9052600090739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e49063d1aa9e7e90604401602060405180830381865af41580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190611729565b90506108d781610e99565b98509850985098509850985098509850505b919395975091939597565b6000546001600160a01b0316331461091e5760405162461bcd60e51b8152600401610633906116db565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610699825b6001600160a01b038116600090815260036020526040812054610699906109958461063c565b9061129d565b6000546001600160a01b031633146109c55760405162461bcd60e51b8152600401610633906116db565b6000600554116109d457600080fd5b8015610a4b57600554610a02906109ef83600160801b61111d565b6109f991906116b9565b600154906112df565b60015560405181815233907fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d784541165119060200160405180910390a2600654610a4790826112df565b6006555b50565b600080546001600160a01b03163314610a795760405162461bcd60e51b8152600401610633906116db565b6000610a848461133e565b90508015610af0576001600160a01b0384166000818152600d6020526040908190204290555184151591907fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf09290610ade9085815260200190565b60405180910390a36001915050610699565b5060009392505050565b6000546001600160a01b03163314610b245760405162461bcd60e51b8152600401610633906116db565b6001600160a01b0381166000908152600c602052604090205460ff16610b4957600080fd5b6001600160a01b0381166000818152600c6020526040808220805460ff19169055517f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329190a250565b6000546001600160a01b03163314610bbc5760405162461bcd60e51b8152600401610633906116db565b6001600160a01b0382166000908152600c602052604090205460ff1615610be1575050565b69d3c21bcecceda10000008110610cd157610bfc8282611204565b604051632f0ad01760e21b8152600760048201526001600160a01b038316602482015260448101829052739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e49063bc2b405c9060640160006040518083038186803b158015610c5d57600080fd5b505af4158015610c71573d6000803e3d6000fd5b505050506001600160a01b0382166000908152600d602052604090205480610cb15750506001600160a01b03166000908152600d60205260409020429055565b610cba816114b3565b15610ccc57610cca836000610a4e565b505b505050565b610cdc826000611204565b60405163131836e760e21b8152600760048201526001600160a01b0383166024820152739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e490634c60db9c9060440160006040518083038186803b158015610d3657600080fd5b505af4158015610d4a573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314610d7c5760405162461bcd60e51b8152600401610633906116db565b600e5460405182907f474ea64804364a1e29a4487ddb63c3342a2dd826ccd8acf48825e680a0e6f20f90600090a3600e55565b6000546001600160a01b03163314610dd95760405162461bcd60e51b8152600401610633906116db565b6001600160a01b038116610e3e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610633565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040516317e142d160e01b8152600760048201526001600160a01b03821660248201528190600090819081908190819081908190739fc6f6fa87d92964a2a1e9d8d3e20cb7fea9a6e4906317e142d190604401602060405180830381865af4158015610f09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2d9190611710565b9650600019955060008712610f8f57600b54871115610f5b57600b54610f549088906114da565b9550610f8f565b600b5460075460009110610f70576000610f7f565b600b54600754610f7f9161129d565b9050610f8b88826111b3565b9650505b610f988861096f565b9450610fa38861063c565b6001600160a01b0389166000908152600d6020526040902054909450925082610fcd576000610fdb565b600e54610fdb9084906112df565b9150428211610feb576000610ff5565b610ff5824261129d565b9050919395975091939597565b6007546000908190819080611022575050600b5460009250829150611116565b600b546000805a90506000805b898410801561103d57508582105b15611105578461104c81611746565b6007549096508610905061105f57600094505b60006007600001868154811061107757611077611761565b60009182526020808320909101546001600160a01b0316808352600d9091526040909120549091506110a8906114b3565b156110cb576110b8816001610a4e565b156110cb57816110c781611746565b9250505b826110d581611746565b93505060005a9050808511156110fc576110f96110f2868361129d565b87906112df565b95505b935061102f9050565b600b85905590975095509193505050505b9193909250565b60008261112c57506000610699565b60006111388385611777565b90508261114585836116b9565b1461119c5760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608401610633565b9392505050565b6000818181121561069957600080fd5b6000806111c08385611796565b9050600083121580156111d35750838112155b806111e857506000831280156111e857508381125b61119c57600080fd5b60008082121561120057600080fd5b5090565b6001600160a01b038216600090815260046020526040902080549082905580821115611260576000611236838361129d565b90506112428482611517565b806005600082825461125491906117d7565b90915550610ccc915050565b80821015610ccc576000611274828461129d565b90506112808482611571565b806005600082825461129291906117ef565b909155505050505050565b600061119c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115ab565b6000806112ec83856117d7565b90508381101561119c5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610633565b60008061134a8361096f565b905080156114aa576001600160a01b03831660009081526003602052604090205461137590826112df565b6001600160a01b038416600081815260036020526040908190209290925590517fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d906113c49084815260200190565b60405180910390a260405163a9059cbb60e01b81526001600160a01b03841660048201526024810182905260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063a9059cbb906044016020604051808303816000875af1158015611430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114549190611806565b9050806114a3576001600160a01b03841660009081526003602052604090205461147e908361129d565b6001600160a01b03909416600090815260036020526040812094909455509192915050565b5092915050565b50600092915050565b6000428211156114c557506000919050565b600e546114d2428461129d565b101592915050565b6000806114e78385611823565b9050600083121580156114fa5750838113155b806111e857506000831280156111e8575083811361119c57600080fd5b61155161153261067f8360015461111d90919063ffffffff16565b6001600160a01b038416600090815260026020526040902054906114da565b6001600160a01b0390921660009081526002602052604090209190915550565b61155161158c61067f8360015461111d90919063ffffffff16565b6001600160a01b038416600090815260026020526040902054906111b3565b600081848411156115cf5760405162461bcd60e51b81526004016106339190611862565b5060006115dc84866117ef565b95945050505050565b6001600160a01b0381168114610a4b57600080fd5b60006020828403121561160c57600080fd5b813561119c816115e5565b60006020828403121561162957600080fd5b5035919050565b8015158114610a4b57600080fd5b6000806040838503121561165157600080fd5b823561165c816115e5565b9150602083013561166c81611630565b809150509250929050565b6000806040838503121561168a57600080fd5b8235611695816115e5565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000826116d657634e487b7160e01b600052601260045260246000fd5b500490565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561172257600080fd5b5051919050565b60006020828403121561173b57600080fd5b815161119c816115e5565b600060001982141561175a5761175a6116a3565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615611791576117916116a3565b500290565b600080821280156001600160ff1b03849003851316156117b8576117b86116a3565b600160ff1b83900384128116156117d1576117d16116a3565b50500190565b600082198211156117ea576117ea6116a3565b500190565b600082821015611801576118016116a3565b500390565b60006020828403121561181857600080fd5b815161119c81611630565b60008083128015600160ff1b850184121615611841576118416116a3565b6001600160ff1b038401831381161561185c5761185c6116a3565b50500390565b600060208083528351808285015260005b8181101561188f57858101830151858201604001528201611873565b818111156118a1576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212202c2fca69716ec5f39a6f1e09781bb4fef228733e5e906cc78d2f201a1f879fd764736f6c634300080a0033

Deployed Bytecode

0x6080604052600436106102605760003560e01c80637fa787ba11610144578063c0f306ef116100b6578063e2f456051161007a578063e2f45605146107d0578063e7841ec0146107e6578063e98030c7146107fb578063f27fd2541461081b578063f2fde38b1461083b578063fe4b84df1461085b57600080fd5b8063c0f306ef146106cd578063c15025c6146106ed578063c9567bf91461075f578063dd62ed3e14610774578063df7787a4146107ba57600080fd5b8063a26579ad11610108578063a26579ad146105d3578063a457c2d7146105e8578063a8b9d24014610608578063a9059cbb14610628578063ad56c13c14610648578063c04a5414146106ad57600080fd5b80637fa787ba1461054357806382bfefc8146105585780638da5cb5b1461058057806395d89b411461059e5780639a0025be146105b357600080fd5b806339509351116101dd5780636ba631cf116101a15780636ba631cf1461046f578063700bb191146104a357806370a08231146104c3578063715018a6146104f957806371778e7d1461050e57806372ac24861461052357600080fd5b806339509351146103e55780634e71d92d1461040557806364b0f6531461041a578063676f66eb1461042f5780636843cd841461044f57600080fd5b80631d5492d9116102245780631d5492d91461032857806323b872dd1461037457806330bb4cff14610394578063313ce567146103a957806331e79db0146103c557600080fd5b806306fdde031461026c578063095ea7b3146102975780630b78f9c0146102c75780630ce5fd36146102e957806318160ddd1461030957600080fd5b3661026757005b600080fd5b34801561027857600080fd5b5061028161087b565b60405161028e9190612c31565b60405180910390f35b3480156102a357600080fd5b506102b76102b2366004612c9b565b61090d565b604051901515815260200161028e565b3480156102d357600080fd5b506102e76102e2366004612cc7565b610924565b005b3480156102f557600080fd5b506102e7610304366004612ce9565b6109a9565b34801561031557600080fd5b506002545b60405190815260200161028e565b34801561033457600080fd5b5061035c7f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d5781565b6040516001600160a01b03909116815260200161028e565b34801561038057600080fd5b506102b761038f366004612d02565b610a14565b3480156103a057600080fd5b5061031a610a7d565b3480156103b557600080fd5b506040516012815260200161028e565b3480156103d157600080fd5b506102e76103e0366004612d43565b610b06565b3480156103f157600080fd5b506102b7610400366004612c9b565b610be2565b34801561041157600080fd5b506102e7610c18565b34801561042657600080fd5b5061031a610d53565b34801561043b57600080fd5b506102e761044a366004612d7c565b610db3565b34801561045b57600080fd5b5061031a61046a366004612d43565b610f2c565b34801561047b57600080fd5b5061035c7f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c881565b3480156104af57600080fd5b506102e76104be366004612ce9565b610fbc565b3480156104cf57600080fd5b5061031a6104de366004612d43565b6001600160a01b031660009081526020819052604090205490565b34801561050557600080fd5b506102e76110ad565b34801561051a57600080fd5b5061031a611121565b34801561052f57600080fd5b506102e761053e366004612d43565b611181565b34801561054f57600080fd5b506102e76111e8565b34801561056457600080fd5b5061035c73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561058c57600080fd5b506005546001600160a01b031661035c565b3480156105aa57600080fd5b506102816112b8565b3480156105bf57600080fd5b506102e76105ce366004612daf565b6112c7565b3480156105df57600080fd5b5061031a6113e9565b3480156105f457600080fd5b506102b7610603366004612c9b565b611449565b34801561061457600080fd5b5061031a610623366004612d43565b611498565b34801561063457600080fd5b506102b7610643366004612c9b565b6114eb565b34801561065457600080fd5b50610668610663366004612d43565b6114f8565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161028e565b3480156106b957600080fd5b5060085461035c906001600160a01b031681565b3480156106d957600080fd5b506102e76106e8366004612d43565b6115bc565b3480156106f957600080fd5b50600b5461072c906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161028e565b34801561076b57600080fd5b506102e7611698565b34801561078057600080fd5b5061031a61078f366004612dca565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156107c657600080fd5b5061031a60065481565b3480156107dc57600080fd5b5061031a60075481565b3480156107f257600080fd5b5061031a6116e3565b34801561080757600080fd5b506102e7610816366004612ce9565b611743565b34801561082757600080fd5b50610668610836366004612ce9565b611910565b34801561084757600080fd5b506102e7610856366004612d43565b61196a565b34801561086757600080fd5b506102e7610876366004612ce9565b611a55565b60606003805461088a90612e03565b80601f01602080910402602001604051908101604052809291908181526020018280546108b690612e03565b80156109035780601f106108d857610100808354040283529160200191610903565b820191906000526020600020905b8154815290600101906020018083116108e657829003601f168201915b5050505050905090565b600061091a338484611aff565b5060015b92915050565b6005546001600160a01b031633146109575760405162461bcd60e51b815260040161094e90612e3e565b60405180910390fd5b6009829055600a8190558115801561097f5750600b54600160c01b90046001600160401b0316155b156109a557600b80546001600160c01b0316600160c01b426001600160401b0316021790555b5050565b336001600160a01b037f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a016146109de57600080fd5b600081116109eb57600080fd5b6103e8610a046b033b2e3c9fd0803ce800000083612e89565b610a0e9190612ebe565b60075550565b6000610a21848484611c24565b610a738433610a6e8560405180606001604052806028815260200161317a602891396001600160a01b038a16600090815260016020908152604080832033845290915290205491906121d7565b611aff565b5060019392505050565b60007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03166385a6b3ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b019190612ed2565b905090565b6005546001600160a01b03163314610b305760405162461bcd60e51b815260040161094e90612e3e565b60405163031e79db60e41b81526001600160a01b0382811660048301527f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d5716906331e79db090602401600060405180830381600087803b158015610b9357600080fd5b505af1158015610ba7573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161091a918590610a6e9086611a99565b60405163226cfa3d60e01b81523360048201526000907f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03169063226cfa3d90602401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190612ed2565b9050610cad6113e9565b610cb74283612211565b1015610cc257600080fd5b60405163bc4c4b3760e01b8152336004820152600060248201527f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03169063bc4c4b37906044016020604051808303816000875af1158015610d2f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a59190612eeb565b60007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03166309bbedde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b336001600160a01b037f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a01614610de857600080fd5b610258826001600160401b03161015610e5b5760405162461bcd60e51b815260206004820152602f60248201527f52657761726420706f6f6c206c657373206672657175656e74207468616e206560448201526e76657279203130206d696e7574657360881b606482015260840161094e565b6103e8816001600160401b031611158015610e74575060015b610ed35760405162461bcd60e51b815260206004820152602a60248201527f52657761726420706f6f6c2070657263656e74206e6f74206265747765656e20604482015269302520616e642031302560b01b606482015260840161094e565b600b805477ffffffffffffffffffffffffffffffff00000000000000001916600160801b6001600160401b03948516026fffffffffffffffff0000000000000000191617600160401b9290931691909102919091179055565b60405163156dbbf560e31b81526001600160a01b0382811660048301526000917f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d579091169063ab6ddfa8906024015b602060405180830381865afa158015610f98573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190612ed2565b60008060007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663ffb2c479856040518263ffffffff1660e01b815260040161100f91815260200190565b6060604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190612f0d565b604080518481526020810184905290810182905260608101889052929550909350915032906000907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a350505050565b6005546001600160a01b031633146110d75760405162461bcd60e51b815260040161094e90612e3e565b6005546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580546001600160a01b0319169055565b60007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663ad7a672f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b6005546001600160a01b031633146111ab5760405162461bcd60e51b815260040161094e90612e3e565b6008546001600160a01b03828116911614156111c657600080fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b336001600160a01b037f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a0161461121d57600080fd5b604051600090339047908381818185875af1925050503d806000811461125f576040519150601f19603f3d011682016040523d82523d6000602084013e611264565b606091505b50509050806112b55760405162461bcd60e51b815260206004820152601c60248201527f4661696c656420746f20776974686472617720737475636b2065746800000000604482015260640161094e565b50565b60606004805461088a90612e03565b336001600160a01b037f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a016146112fc57600080fd5b61c350816001600160401b031610158015611323575062030d40816001600160401b031611155b61138b5760405162461bcd60e51b815260206004820152603360248201527f676173466f7250726f63657373696e67206d757374206265206265747765656e60448201527202035302c30303020616e64203230302c30303606c1b606482015260840161094e565b600b546040516001600160401b03918216918316907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3600b805467ffffffffffffffff19166001600160401b0392909216919091179055565b60007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b0316636f2789ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b600061091a3384610a6e856040518060600160405280602581526020016131a2602591393360009081526001602090815260408083206001600160a01b038d16845290915290205491906121d7565b6040516302a2e74960e61b81526001600160a01b0382811660048301526000917f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d579091169063a8b9d24090602401610f7b565b600061091a338484611c24565b6000806000806000806000807f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663fbcbc0f18a6040518263ffffffff1660e01b815260040161155f91906001600160a01b0391909116815260200190565b61010060405180830381865afa15801561157d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a19190612f3b565b97509750975097509750975097509750919395975091939597565b6005546001600160a01b031633146115e65760405162461bcd60e51b815260040161094e90612e3e565b60405163c0f306ef60e01b81526001600160a01b0382811660048301527f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d57169063c0f306ef90602401600060405180830381600087803b15801561164957600080fd5b505af115801561165d573d6000803e3d6000fd5b50506040516001600160a01b03841692507f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329150600090a250565b6005546001600160a01b031633146116c25760405162461bcd60e51b815260040161094e90612e3e565b6000600d54116116d4576116d4612fa5565b600e805460ff19166001179055565b60007f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663e7841ec06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610add573d6000803e3d6000fd5b336001600160a01b037f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a0161461177857600080fd5b610384811015801561178d5750620151808111155b6118165760405162461bcd60e51b815260206004820152604e60248201527f4469766964656e645f547261636b65723a20636c61696d57616974206d75737460448201527f206265207570646174656420746f206265747765656e203135206d696e75746560648201526d7320616e6420323420686f75727360901b608482015260a40161094e565b61181e6113e9565b8114156118935760405162461bcd60e51b815260206004820152603760248201527f4469766964656e645f547261636b65723a2043616e6e6f74207570646174652060448201527f636c61696d5761697420746f2073616d652076616c7565000000000000000000606482015260840161094e565b60405163e98030c760e01b8152600481018290527f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03169063e98030c790602401600060405180830381600087803b1580156118f557600080fd5b505af1158015611909573d6000803e3d6000fd5b5050505050565b6000806000806000806000807f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b0316635183d6fd8a6040518263ffffffff1660e01b815260040161155f91815260200190565b6005546001600160a01b031633146119945760405162461bcd60e51b815260040161094e90612e3e565b6001600160a01b0381166119f95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161094e565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314611a7f5760405162461bcd60e51b815260040161094e90612e3e565b80600d6000828254611a919190612fbb565b909155505050565b600080611aa68385612fbb565b905083811015611af85760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640161094e565b9392505050565b6001600160a01b038316611b615760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161094e565b6001600160a01b038216611bc25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161094e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600e54839060ff1680611c4457506005546001600160a01b038281169116145b80611c8057507f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a06001600160a01b0316816001600160a01b0316145b611c8957600080fd5b6001600160a01b038416611caf5760405162461bcd60e51b815260040161094e90612fd3565b6001600160a01b038316611cd55760405162461bcd60e51b815260040161094e90613018565b81611ceb57611ce684846000612253565b6121d1565b6001600160a01b038416301480611d3357507f00000000000000000000000006bec2998e87a82cf93dfd29dde38307ce9976a06001600160a01b0316836001600160a01b0316145b15611d4357611ce6848484612253565b6001600160a01b03838116600081815260208190526040902054917f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c81614611de057600654611d928483612fbb565b1115611de05760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e6720746865206d61782077616c6c6574206c696d69740000604482015260640161094e565b6009543060009081526020819052604081205491159190611e01888361235c565b90508015611e2a57600c805460ff19166001179055611e1f836123be565b600c805460ff191690555b828015611e35575080155b8015611e7257507f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b0316876001600160a01b0316145b8015611eac5750600b54611e9f906001600160401b03600160801b8204811691600160c01b90041661305b565b6001600160401b03164210155b15611eb957611eb9612660565b82611efb576000606487611ecc8b6128a4565b611ed69190612e89565b611ee09190612ebe565b9050611eed893083612253565b611ef78188613086565b9650505b611f06888888612253565b7f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663e30443bc89611f558b6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015611f9b57600080fd5b505af1925050508015611fac575060015b507f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b031663e30443bc88611ffc8a6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561204257600080fd5b505af1925050508015612053575060015b5060007f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b0316896001600160a01b03161480156120be575069d3c21bcecceda1000000851080156120be575069d3c21bcecceda10000006120bb8887612fbb565b10155b9050811580156120cb5750835b80156120d5575080155b156121cb57600b546040516001624d3b8760e01b031981526001600160401b0390911660048201819052907f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03169063ffb2c479906024016060604051808303816000875af192505050801561216f575060408051601f3d908101601f1916820190925261216c91810190612f0d565b60015b612178576121c9565b60408051848152602081018490529081018290526060810185905232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a35050505b505b50505050505b50505050565b600081848411156121fb5760405162461bcd60e51b815260040161094e9190612c31565b5060006122088486613086565b95945050505050565b6000611af883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506121d7565b6001600160a01b0383166122795760405162461bcd60e51b815260040161094e90612fd3565b6001600160a01b03821661229f5760405162461bcd60e51b815260040161094e90613018565b6122dc81604051806060016040528060268152602001613154602691396001600160a01b03861660009081526020819052604090205491906121d7565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461230b9082611a99565b6001600160a01b038381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611c17565b600060075482101580156123a257507f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b0316836001600160a01b031614155b8015611af857506008546001600160a01b031615159392505050565b306000908152602081905260409020546007546123dc906005612e89565b8111156123f4576007546123f1906005612e89565b90505b81156125fb576040516370a0823160e01b81526001600160a01b037f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d5716600482015260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124999190612ed2565b90506124a68260006128fc565b6040516370a0823160e01b81526001600160a01b037f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d57166004820152819073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612520573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125449190612ed2565b61254e9190613086565b60405163b0c7ce3760e01b8152600481018290529091507f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d576001600160a01b03169063b0c7ce3790602401600060405180830381600087803b1580156125b357600080fd5b505af11580156125c7573d6000803e3d6000fd5b50506040518392507fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b19150600090a2505050565b6126068160016128fc565b6008546040516000916001600160a01b03169047908381818185875af1925050503d8060008114612653576040519150601f19603f3d011682016040523d82523d6000602084013e612658565b606091505b505050505050565b600b546000906001600160401b03600160801b820481169161268b91600160c01b9091041642613086565b6126959190612ebe565b600b549091506001600160401b03600160801b82048116916126c091600160c01b9091041642613086565b6126ca919061309d565b6126d49042613086565b600b80546001600160401b0392909216600160c01b026001600160c01b039092169190911790556040516370a0823160e01b81527f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b0316600482015260009030906370a0823190602401602060405180830381865afa158015612762573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127869190612ed2565b90506000600583111561279857600592505b60005b8381101561280057600b546000906127d290612710906127cc908790600160401b90046001600160401b0316612b47565b90612bc6565b90506127de8185613086565b93506127ea8184612fbb565b92505080806127f8906130b1565b91505061279b565b5061282c7f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c83083612253565b7f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561288757600080fd5b505af115801561289b573d6000803e3d6000fd5b50505050505050565b60007f000000000000000000000000775bfc4204221c4fcfb4bcad2ecf5a4fe63d44c86001600160a01b0316826001600160a01b0316146128f457600a546009546128ef9190612fbb565b61091e565b505060095490565b306000908152600160209081526040808320737a250d5630b4cf539739df2c5dacb4c659f2488d845290915290205482111561295d5761295d30737a250d5630b4cf539739df2c5dacb4c659f2488d6b033b2e3c9fd0803ce8000000611aff565b8015612a52576040805160028082526060820183526000926020830190803683370190505090503081600081518110612998576129986130cc565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816001815181106129e0576129e06130cc565b6001600160a01b039092166020928302919091019091015260405163791ac94760e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d9063791ac94790612a389086906000908690309042906004016130e2565b600060405180830381600087803b15801561288757600080fd5b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612a8757612a876130cc565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612acf57612acf6130cc565b6001600160a01b0390921660209283029190910190910152604051635c11d79560e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d90635c11d79590612a3890869060009086907f00000000000000000000000048965ce86d744eca034c95c704192ddef7b45d579042906004016130e2565b600082612b565750600061091e565b6000612b628385612e89565b905082612b6f8583612ebe565b14611af85760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b606482015260840161094e565b6000611af883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612c245760405162461bcd60e51b815260040161094e9190612c31565b5060006122088486612ebe565b600060208083528351808285015260005b81811015612c5e57858101830151858201604001528201612c42565b81811115612c70576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146112b557600080fd5b60008060408385031215612cae57600080fd5b8235612cb981612c86565b946020939093013593505050565b60008060408385031215612cda57600080fd5b50508035926020909101359150565b600060208284031215612cfb57600080fd5b5035919050565b600080600060608486031215612d1757600080fd5b8335612d2281612c86565b92506020840135612d3281612c86565b929592945050506040919091013590565b600060208284031215612d5557600080fd5b8135611af881612c86565b80356001600160401b0381168114612d7757600080fd5b919050565b60008060408385031215612d8f57600080fd5b612d9883612d60565b9150612da660208401612d60565b90509250929050565b600060208284031215612dc157600080fd5b611af882612d60565b60008060408385031215612ddd57600080fd5b8235612de881612c86565b91506020830135612df881612c86565b809150509250929050565b600181811c90821680612e1757607f821691505b60208210811415612e3857634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615612ea357612ea3612e73565b500290565b634e487b7160e01b600052601260045260246000fd5b600082612ecd57612ecd612ea8565b500490565b600060208284031215612ee457600080fd5b5051919050565b600060208284031215612efd57600080fd5b81518015158114611af857600080fd5b600080600060608486031215612f2257600080fd5b8351925060208401519150604084015190509250925092565b600080600080600080600080610100898b031215612f5857600080fd5b8851612f6381612c86565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b634e487b7160e01b600052600160045260246000fd5b60008219821115612fce57612fce612e73565b500190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60006001600160401b0380831681851680830382111561307d5761307d612e73565b01949350505050565b60008282101561309857613098612e73565b500390565b6000826130ac576130ac612ea8565b500690565b60006000198214156130c5576130c5612e73565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156131325784516001600160a01b03168352938301939183019160010161310d565b50506001600160a01b0396909616606085015250505060800152939250505056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122073ca34b765446d9d7b497c830fe8a75b51f3c7532f030270f94016be6662e04464736f6c634300080a0033

Libraries Used


Deployed Bytecode Sourcemap

34056:14114:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25452:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;27619:169;;;;;;;;;;-1:-1:-1;27619:169:0;;;;;:::i;:::-;;:::i;:::-;;;1237:14:1;;1230:22;1212:41;;1200:2;1185:18;27619:169:0;1072:187:1;43123:333:0;;;;;;;;;;-1:-1:-1;43123:333:0;;;;;:::i;:::-;;:::i;:::-;;43672:197;;;;;;;;;;-1:-1:-1;43672:197:0;;;;;:::i;:::-;;:::i;26572:108::-;;;;;;;;;;-1:-1:-1;26660:12:0;;26572:108;;;1848:25:1;;;1836:2;1821:18;26572:108:0;1702:177:1;34329:49:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2080:32:1;;;2062:51;;2050:2;2035:18;34329:49:0;1884:235:1;28270:355:0;;;;;;;;;;-1:-1:-1;28270:355:0;;;;;:::i;:::-;;:::i;46087:142::-;;;;;;;;;;;;;:::i;26414:93::-;;;;;;;;;;-1:-1:-1;26414:93:0;;26497:2;2727:36:1;;2715:2;2700:18;26414:93:0;2585:184:1;45391:176:0;;;;;;;;;;-1:-1:-1;45391:176:0;;;;;:::i;:::-;;:::i;29034:218::-;;;;;;;;;;-1:-1:-1;29034:218:0;;;;;:::i;:::-;;:::i;47493:254::-;;;;;;;;;;;;;:::i;47893:142::-;;;;;;;;;;;;;:::i;43877:464::-;;;;;;;;;;-1:-1:-1;43877:464:0;;;;;:::i;:::-;;:::i;46397:144::-;;;;;;;;;;-1:-1:-1;46397:144:0;;;;;:::i;:::-;;:::i;34387:37::-;;;;;;;;;;;;;;;47213:272;;;;;;;;;;-1:-1:-1;47213:272:0;;;;;:::i;:::-;;:::i;26743:127::-;;;;;;;;;;-1:-1:-1;26743:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;26844:18:0;26817:7;26844:18;;;;;;;;;;;;26743:127;20986:148;;;;;;;;;;;;;:::i;48047:120::-;;;;;;;;;;;;;:::i;45753:207::-;;;;;;;;;;-1:-1:-1;45753:207:0;;;;;:::i;:::-;;:::i;44349:233::-;;;;;;;;;;;;;:::i;34721:74::-;;;;;;;;;;;;34753:42;34721:74;;20344:79;;;;;;;;;;-1:-1:-1;20409:6:0;;-1:-1:-1;;;;;20409:6:0;20344:79;;25671:104;;;;;;;;;;;;;:::i;44590:367::-;;;;;;;;;;-1:-1:-1;44590:367:0;;;;;:::i;:::-;;:::i;45972:107::-;;;;;;;;;;;;;:::i;29755:269::-;;;;;;;;;;-1:-1:-1;29755:269:0;;;;;:::i;:::-;;:::i;46237:152::-;;;;;;;;;;-1:-1:-1;46237:152:0;;;;;:::i;:::-;;:::i;27083:175::-;;;;;;;;;;-1:-1:-1;27083:175:0;;;;;:::i;:::-;;:::i;46549:319::-;;;;;;;;;;-1:-1:-1;46549:319:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4477:32:1;;;4459:51;;4541:2;4526:18;;4519:34;;;;4569:18;;;4562:34;;;;4627:2;4612:18;;4605:34;;;;4670:3;4655:19;;4648:35;4497:3;4699:19;;4692:35;4758:3;4743:19;;4736:35;4802:3;4787:19;;4780:35;4446:3;4431:19;46549:319:0;4120:701:1;34673:40:0;;;;;;;;;;-1:-1:-1;34673:40:0;;;;-1:-1:-1;;;;;34673:40:0;;;45575:170;;;;;;;;;;-1:-1:-1;45575:170:0;;;;;:::i;:::-;;:::i;35135:82::-;;;;;;;;;;-1:-1:-1;35135:82:0;;;;-1:-1:-1;;;;;35135:82:0;;;;-1:-1:-1;;;35135:82:0;;;;;-1:-1:-1;;;35135:82:0;;;;;-1:-1:-1;;;35135:82:0;;;;;;;;;-1:-1:-1;;;;;5328:15:1;;;5310:34;;5380:15;;;5375:2;5360:18;;5353:43;5432:15;;;5412:18;;;5405:43;;;;5484:15;;;5479:2;5464:18;;5457:43;5260:3;5245:19;35135:82:0;5050:456:1;43464:106:0;;;;;;;;;;;;;:::i;27321:151::-;;;;;;;;;;-1:-1:-1;27321:151:0;;;;;:::i;:::-;-1:-1:-1;;;;;27437:18:0;;;27410:7;27437:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;27321:151;34196:52;;;;;;;;;;;;;;;;34256:59;;;;;;;;;;;;;;;;47755:130;;;;;;;;;;;;;:::i;44965:418::-;;;;;;;;;;-1:-1:-1;44965:418:0;;;;;:::i;:::-;;:::i;46876:329::-;;;;;;;;;;-1:-1:-1;46876:329:0;;;;;:::i;:::-;;:::i;21289:244::-;;;;;;;;;;-1:-1:-1;21289:244:0;;;;;:::i;:::-;;:::i;43578:84::-;;;;;;;;;;-1:-1:-1;43578:84:0;;;;;:::i;:::-;;:::i;25452:100::-;25506:13;25539:5;25532:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25452:100;:::o;27619:169::-;27702:4;27719:39;972:10;27742:7;27751:6;27719:8;:39::i;:::-;-1:-1:-1;27776:4:0;27619:169;;;;;:::o;43123:333::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;;;;;;;;;43216:10:::1;:19:::0;;;43246:22:::1;:43:::0;;;43303:15;;:64;::::1;;;-1:-1:-1::0;43322:14:0::1;:40:::0;-1:-1:-1;;;43322:40:0;::::1;-1:-1:-1::0;;;;;43322:40:0::1;:45:::0;43303:64:::1;43300:148;;;43382:14;:66:::0;;-1:-1:-1;;;;;43382:66:0::1;-1:-1:-1::0;;;43432:15:0::1;-1:-1:-1::0;;;;;43382:66:0::1;;;::::0;;43300:148:::1;43123:333:::0;;:::o;43672:197::-;43744:10;-1:-1:-1;;;;;43758:8:0;43744:22;;43736:31;;;;;;43797:1;43786:8;:12;43778:21;;;;;;43857:4;43831:23;34169:20;43831:8;:23;:::i;:::-;:30;;;;:::i;:::-;43810:18;:51;-1:-1:-1;43672:197:0:o;28270:355::-;28410:4;28427:36;28437:6;28445:9;28456:6;28427:9;:36::i;:::-;28474:121;28483:6;972:10;28505:89;28543:6;28505:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28505:19:0;;;;;;:11;:19;;;;;;;;972:10;28505:33;;;;;;;;;;:37;:89::i;:::-;28474:8;:121::i;:::-;-1:-1:-1;28613:4:0;28270:355;;;;;:::o;46087:142::-;46150:7;46177:16;-1:-1:-1;;;;;46177:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46170:51;;46087:142;:::o;45391:176::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;45468:46:::1;::::0;-1:-1:-1;;;45468:46:0;;-1:-1:-1;;;;;2080:32:1;;;45468:46:0::1;::::0;::::1;2062:51:1::0;45468:16:0::1;:37;::::0;::::1;::::0;2035:18:1;;45468:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;45530:29:0::1;::::0;-1:-1:-1;;;;;45530:29:0;::::1;::::0;-1:-1:-1;45530:29:0::1;::::0;-1:-1:-1;45530:29:0;;::::1;45391:176:::0;:::o;29034:218::-;972:10;29122:4;29171:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;29171:34:0;;;;;;;;;;29122:4;;29139:83;;29162:7;;29171:50;;29210:10;29171:38;:50::i;47493:254::-;47554:43;;-1:-1:-1;;;47554:43:0;;47586:10;47554:43;;;2062:51:1;47530:21:0;;47554:16;-1:-1:-1;;;;;47554:31:0;;;;2035:18:1;;47554:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47530:67;;47654:14;:12;:14::i;:::-;47616:34;:15;47636:13;47616:19;:34::i;:::-;:52;;47608:61;;;;;;47680:59;;-1:-1:-1;;;47680:59:0;;47720:10;47680:59;;;7585:51:1;47733:5:0;7652:18:1;;;7645:50;47680:16:0;-1:-1:-1;;;;;47680:31:0;;;;7558:18:1;;47680:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;47893:142::-;47958:7;47985:16;-1:-1:-1;;;;;47985:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43877:464;43985:10;-1:-1:-1;;;;;43999:8:0;43985:22;;43977:31;;;;;;44050:3;44027:19;-1:-1:-1;;;;;44027:26:0;;;44019:86;;;;-1:-1:-1;;;44019:86:0;;8190:2:1;44019:86:0;;;8172:21:1;8229:2;8209:18;;;8202:30;8268:34;8248:18;;;8241:62;-1:-1:-1;;;8319:18:1;;;8312:45;8374:19;;44019:86:0;7988:411:1;44019:86:0;44136:4;44124:8;-1:-1:-1;;;;;44124:16:0;;;:33;;;;-1:-1:-1;44144:13:0;44124:33;44116:88;;;;-1:-1:-1;;;44116:88:0;;8606:2:1;44116:88:0;;;8588:21:1;8645:2;8625:18;;;8618:30;8684:34;8664:18;;;8657:62;-1:-1:-1;;;8735:18:1;;;8728:40;8785:19;;44116:88:0;8404:406:1;44116:88:0;44215:14;:60;;-1:-1:-1;;44286:47:0;-1:-1:-1;;;;;;;;44215:60:0;;;;-1:-1:-1;;44286:47:0;;-1:-1:-1;;;44286:47:0;;;;;;;;;;;;;;43877:464::o;46397:144::-;46494:39;;-1:-1:-1;;;46494:39:0;;-1:-1:-1;;;;;2080:32:1;;;46494:39:0;;;2062:51:1;46467:7:0;;46494:16;:30;;;;;;2035:18:1;;46494:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;47213:272::-;47279:18;47299:14;47315:26;47345:16;-1:-1:-1;;;;;47345:24:0;;47370:3;47345:29;;;;;;;;;;;;;1848:25:1;;1836:2;1821:18;;1702:177;47345:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47390:87;;;9357:25:1;;;9413:2;9398:18;;9391:34;;;9441:18;;;9434:34;;;9499:2;9484:18;;9477:34;;;47278:96:0;;-1:-1:-1;47278:96:0;;-1:-1:-1;47278:96:0;-1:-1:-1;47467:9:0;;47455:5;;47390:87;;9344:3:1;9329:19;47390:87:0;;;;;;;47267:218;;;47213:272;:::o;20986:148::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;21077:6:::1;::::0;21056:40:::1;::::0;21093:1:::1;::::0;-1:-1:-1;;;;;21077:6:0::1;::::0;21056:40:::1;::::0;21093:1;;21056:40:::1;21107:6;:19:::0;;-1:-1:-1;;;;;;21107:19:0::1;::::0;;20986:148::o;48047:120::-;48101:7;48128:16;-1:-1:-1;;;;;48128:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45753:207;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;45883:17:::1;::::0;-1:-1:-1;;;;;45859:41:0;;::::1;45883:17:::0;::::1;45859:41;;45851:50;;;::::0;::::1;;45912:17;:40:::0;;-1:-1:-1;;;;;;45912:40:0::1;-1:-1:-1::0;;;;;45912:40:0;;;::::1;::::0;;;::::1;::::0;;45753:207::o;44349:233::-;44405:10;-1:-1:-1;;;;;44419:8:0;44405:22;;44397:31;;;;;;44457:58;;44440:12;;44465:10;;44489:21;;44440:12;44457:58;44440:12;44457:58;44489:21;44465:10;44457:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44439:76;;;44534:7;44526:48;;;;-1:-1:-1;;;44526:48:0;;9934:2:1;44526:48:0;;;9916:21:1;9973:2;9953:18;;;9946:30;10012;9992:18;;;9985:58;10060:18;;44526:48:0;9732:352:1;44526:48:0;44386:196;44349:233::o;25671:104::-;25727:13;25760:7;25753:14;;;;;:::i;44590:367::-;44667:10;-1:-1:-1;;;;;44681:8:0;44667:22;;44659:31;;;;;;44721:6;44709:8;-1:-1:-1;;;;;44709:18:0;;;:41;;;;;44743:7;44731:8;-1:-1:-1;;;;;44731:19:0;;;44709:41;44701:105;;;;-1:-1:-1;;;44701:105:0;;10291:2:1;44701:105:0;;;10273:21:1;10330:2;10310:18;;;10303:30;10369:34;10349:18;;;10342:62;-1:-1:-1;;;10420:18:1;;;10413:49;10479:19;;44701:105:0;10089:415:1;44701:105:0;44864:14;:31;44830:66;;-1:-1:-1;;;;;44864:31:0;;;;44830:66;;;;;44864:31;;44830:66;44907:14;:42;;-1:-1:-1;;44907:42:0;-1:-1:-1;;;;;44907:42:0;;;;;;;;;;44590:367::o;45972:107::-;46016:7;46043:16;-1:-1:-1;;;;;46043:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29755:269;29848:4;29865:129;972:10;29888:7;29897:96;29936:15;29897:96;;;;;;;;;;;;;;;;;972:10;29897:25;;;;:11;:25;;;;;;;;-1:-1:-1;;;;;29897:34:0;;;;;;;;;;;;:38;:96::i;46237:152::-;46333:48;;-1:-1:-1;;;46333:48:0;;-1:-1:-1;;;;;2080:32:1;;;46333:48:0;;;2062:51:1;46306:7:0;;46333:16;:39;;;;;;2035:18:1;;46333:48:0;1884:235:1;27083:175:0;27169:4;27186:42;972:10;27210:9;27221:6;27186:9;:42::i;46549:319::-;46645:7;46667:6;46688;46709:7;46731;46753;46775;46797;46824:16;-1:-1:-1;;;;;46824:27:0;;46852:7;46824:36;;;;;;;;;;;;;;-1:-1:-1;;;;;2080:32:1;;;;2062:51;;2050:2;2035:18;;1884:235;46824:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46817:43;;;;;;;;;;;;;;;;46549:319;;;;;;;;;:::o;45575:170::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;45650:44:::1;::::0;-1:-1:-1;;;45650:44:0;;-1:-1:-1;;;;;2080:32:1;;;45650:44:0::1;::::0;::::1;2062:51:1::0;45650:16:0::1;:35;::::0;::::1;::::0;2035:18:1;;45650:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;45710:27:0::1;::::0;-1:-1:-1;;;;;45710:27:0;::::1;::::0;-1:-1:-1;45710:27:0::1;::::0;-1:-1:-1;45710:27:0;;::::1;45575:170:::0;:::o;43464:106::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;43531:1:::1;43524:4;;:8;43517:16;;;;:::i;:::-;43544:11;:18:::0;;-1:-1:-1;;43544:18:0::1;43558:4;43544:18;::::0;;43464:106::o;47755:130::-;47810:7;47837:16;-1:-1:-1;;;;;47837:38:0;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44965:418;45040:10;-1:-1:-1;;;;;45054:8:0;45040:22;;45032:31;;;;;;45098:3;45082:12;:19;;:44;;;;;45121:5;45105:12;:21;;45082:44;45074:135;;;;-1:-1:-1;;;45074:135:0;;11529:2:1;45074:135:0;;;11511:21:1;11568:2;11548:18;;;11541:30;11607:34;11587:18;;;11580:62;11678:34;11658:18;;;11651:62;-1:-1:-1;;;11729:19:1;;;11722:45;11784:19;;45074:135:0;11327:482:1;45074:135:0;45244:14;:12;:14::i;:::-;45228:12;:30;;45220:98;;;;-1:-1:-1;;;45220:98:0;;12016:2:1;45220:98:0;;;11998:21:1;12055:2;12035:18;;;12028:30;12094:34;12074:18;;;12067:62;12165:25;12145:18;;;12138:53;12208:19;;45220:98:0;11814:419:1;45220:98:0;45329:46;;-1:-1:-1;;;45329:46:0;;;;;1848:25:1;;;45329:16:0;-1:-1:-1;;;;;45329:32:0;;;;1821:18:1;;45329:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44965:418;:::o;46876:329::-;46977:7;46999:6;47020;47041:7;47063;47085;47107;47129;47156:16;-1:-1:-1;;;;;47156:34:0;;47191:5;47156:41;;;;;;;;;;;;;1848:25:1;;1836:2;1821:18;;1702:177;21289:244:0;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;21378:22:0;::::1;21370:73;;;::::0;-1:-1:-1;;;21370:73:0;;12440:2:1;21370:73:0::1;::::0;::::1;12422:21:1::0;12479:2;12459:18;;;12452:30;12518:34;12498:18;;;12491:62;-1:-1:-1;;;12569:18:1;;;12562:36;12615:19;;21370:73:0::1;12238:402:1::0;21370:73:0::1;21480:6;::::0;21459:38:::1;::::0;-1:-1:-1;;;;;21459:38:0;;::::1;::::0;21480:6:::1;::::0;21459:38:::1;::::0;21480:6:::1;::::0;21459:38:::1;21508:6;:17:::0;;-1:-1:-1;;;;;;21508:17:0::1;-1:-1:-1::0;;;;;21508:17:0;;;::::1;::::0;;;::::1;::::0;;21289:244::o;43578:84::-;20556:6;;-1:-1:-1;;;;;20556:6:0;972:10;20556:22;20548:67;;;;-1:-1:-1;;;20548:67:0;;;;;;;:::i;:::-;43649:5:::1;43643:4;;:11;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;43578:84:0:o;13430:181::-;13488:7;;13520:5;13524:1;13520;:5;:::i;:::-;13508:17;;13549:1;13544;:6;;13536:46;;;;-1:-1:-1;;;13536:46:0;;12980:2:1;13536:46:0;;;12962:21:1;13019:2;12999:18;;;12992:30;13058:29;13038:18;;;13031:57;13105:18;;13536:46:0;12778:351:1;13536:46:0;13602:1;13430:181;-1:-1:-1;;;13430:181:0:o;32941:380::-;-1:-1:-1;;;;;33077:19:0;;33069:68;;;;-1:-1:-1;;;33069:68:0;;13336:2:1;33069:68:0;;;13318:21:1;13375:2;13355:18;;;13348:30;13414:34;13394:18;;;13387:62;-1:-1:-1;;;13465:18:1;;;13458:34;13509:19;;33069:68:0;13134:400:1;33069:68:0;-1:-1:-1;;;;;33156:21:0;;33148:68;;;;-1:-1:-1;;;33148:68:0;;13741:2:1;33148:68:0;;;13723:21:1;13780:2;13760:18;;;13753:30;13819:34;13799:18;;;13792:62;-1:-1:-1;;;13870:18:1;;;13863:32;13912:19;;33148:68:0;13539:398:1;33148:68:0;-1:-1:-1;;;;;33229:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;33281:32;;1848:25:1;;;33281:32:0;;1821:18:1;33281:32:0;;;;;;;;32941:380;;;:::o;37384:2277::-;37305:11;;37510:4;;37305:11;;;:30;;-1:-1:-1;20409:6:0;;-1:-1:-1;;;;;37320:15:0;;;20409:6;;37320:15;37305:30;:50;;;;37347:8;-1:-1:-1;;;;;37339:16:0;:4;-1:-1:-1;;;;;37339:16:0;;37305:50;37297:59;;;;;;-1:-1:-1;;;;;37535:18:0;::::1;37527:68;;;;-1:-1:-1::0;;;37527:68:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;37614:16:0;::::1;37606:64;;;;-1:-1:-1::0;;;37606:64:0::1;;;;;;;:::i;:::-;37684:11:::0;37681:203:::1;;37719:28;37735:4;37741:2;37745:1;37719:15;:28::i;:::-;37712:35;;37681:203;-1:-1:-1::0;;;;;37777:21:0;::::1;37793:4;37777:21;::::0;:39:::1;;;37808:8;-1:-1:-1::0;;;;;37802:14:0::1;:2;-1:-1:-1::0;;;;;37802:14:0::1;;37777:39;37774:110;;;37839:33;37855:4;37861:2;37865:6;37839:15;:33::i;37774:110::-;-1:-1:-1::0;;;;;26844:18:0;;;37896:26:::1;26844:18:::0;;;;;;;;;;;;37959:12:::1;37953:18;;37949:135;;38027:10;::::0;37996:27:::1;38017:6:::0;37996:18;:27:::1;:::i;:::-;:41;;37988:84;;;::::0;-1:-1:-1;;;37988:84:0;;14954:2:1;37988:84:0::1;::::0;::::1;14936:21:1::0;14993:2;14973:18;;;14966:30;15032:32;15012:18;;;15005:60;15082:18;;37988:84:0::1;14752:354:1::0;37988:84:0::1;38117:10;::::0;38194:4:::1;38096:18;26844::::0;;;;;;;;;;;38117:15;;;26844:18;38229:42:::1;38244:4:::0;26844:18;38229:14:::1;:42::i;:::-;38211:60;;38285:10;38282:126;;;38312:8;:15:::0;;-1:-1:-1;;38312:15:0::1;38323:4;38312:15;::::0;;38342:23:::1;38351:13:::0;38342:8:::1;:23::i;:::-;38380:8;:16:::0;;-1:-1:-1;;38380:16:0::1;::::0;;38282:126:::1;38431:13;:28;;;;;38449:10;38448:11;38431:28;:50;;;;;38469:12;-1:-1:-1::0;;;;;38463:18:0::1;:2;-1:-1:-1::0;;;;;38463:18:0::1;;38431:50;:168;;;;-1:-1:-1::0;38561:14:0::1;:38:::0;38518:81:::1;::::0;-1:-1:-1;;;;;;;;38561:38:0;::::1;::::0;::::1;::::0;-1:-1:-1;;;38518:40:0;::::1;;:81;:::i;:::-;-1:-1:-1::0;;;;;38499:100:0::1;:15;:100;;38431:168;38428:227;;;38615:16;:14;:16::i;:::-;38671:13;38667:193;;38700:17;38745:3;38736:6;38720:13;38728:4;38720:7;:13::i;:::-;:22;;;;:::i;:::-;:28;;;;:::i;:::-;38700:48;;38763:47;38779:4;38793;38800:9;38763:15;:47::i;:::-;38829:19;38839:9:::0;38829:19;::::1;:::i;:::-;;;38685:175;38667:193;38872:33;38888:4;38894:2;38898:6;38872:15;:33::i;:::-;38922:16;-1:-1:-1::0;;;;;38922:27:0::1;;38958:4;38965:15;38975:4;-1:-1:-1::0;;;;;26844:18:0;26817:7;26844:18;;;;;;;;;;;;26743:127;38965:15:::1;38922:59;::::0;-1:-1:-1;;;;;;38922:59:0::1;::::0;;;;;;-1:-1:-1;;;;;15690:32:1;;;38922:59:0::1;::::0;::::1;15672:51:1::0;15739:18;;;15732:34;15645:18;;38922:59:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;38918:75:::0;39007:16:::1;-1:-1:-1::0;;;;;39007:27:0::1;;39043:2;39048:13;39058:2;-1:-1:-1::0;;;;;26844:18:0;26817:7;26844:18;;;;;;;;;;;;26743:127;39048:13:::1;39007:55;::::0;-1:-1:-1;;;;;;39007:55:0::1;::::0;;;;;;-1:-1:-1;;;;;15690:32:1;;;39007:55:0::1;::::0;::::1;15672:51:1::0;15739:18;;;15732:34;15645:18;;39007:55:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;39003:71:::0;39086:24:::1;39121:12;-1:-1:-1::0;;;;;39113:20:0::1;:4;-1:-1:-1::0;;;;;39113:20:0::1;;:132;;;;;35268:20;39138:18;:45;:106;;;;-1:-1:-1::0;35268:20:0::1;39188:27;39209:6:::0;39188:18;:27:::1;:::i;:::-;:55;;39138:106;39086:159;;39260:10;39259:11;:28;;;;;39274:13;39259:28;:52;;;;;39292:19;39291:20;39259:52;39256:398;;;39342:14;:31:::0;39392:29:::1;::::0;-1:-1:-1;;;;;;39392:29:0;;-1:-1:-1;;;;;39342:31:0;;::::1;39392:29;::::0;::::1;1848:25:1::0;;;39342:31:0;39392:16:::1;-1:-1:-1::0;;;;;39392:24:0::1;::::0;::::1;::::0;1821:18:1;;39392:29:0::1;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;39392:29:0::1;::::0;;::::1;;::::0;;::::1;-1:-1:-1::0;;39392:29:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;;;39388:255;;;;;39519:86;::::0;;9357:25:1;;;9413:2;9398:18;;9391:34;;;9441:18;;;9434:34;;;9499:2;9484:18;;9477:34;;;39595:9:0::1;::::0;39584:4:::1;::::0;39519:86:::1;::::0;9344:3:1;9329:19;39519:86:0::1;;;;;;;39422:199;;;39388:255;39313:341;39256:398;37516:2145;;;;;37367:1;37384:2277:::0;;;;:::o;14333:192::-;14419:7;14455:12;14447:6;;;;14439:29;;;;-1:-1:-1;;;14439:29:0;;;;;;;;:::i;:::-;-1:-1:-1;14479:9:0;14491:5;14495:1;14491;:5;:::i;:::-;14479:17;14333:192;-1:-1:-1;;;;;14333:192:0:o;13894:136::-;13952:7;13979:43;13983:1;13986;13979:43;;;;;;;;;;;;;;;;;:3;:43::i;30514:573::-;-1:-1:-1;;;;;30654:20:0;;30646:70;;;;-1:-1:-1;;;30646:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;30735:23:0;;30727:71;;;;-1:-1:-1;;;30727:71:0;;;;;;;:::i;:::-;30891;30913:6;30891:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30891:17:0;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;30871:17:0;;;:9;:17;;;;;;;;;;;:91;;;;30996:20;;;;;;;:32;;31021:6;30996:24;:32::i;:::-;-1:-1:-1;;;;;30973:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;31044:35;1848:25:1;;;30973:20:0;;31044:35;;;;;;1821:18:1;31044:35:0;1702:177:1;40898:234:0;40988:11;41045:18;;41021:20;:42;;:66;;;;;41075:12;-1:-1:-1;;;;;41067:20:0;:4;-1:-1:-1;;;;;41067:20:0;;;41021:66;:103;;;;-1:-1:-1;41092:17:0;;-1:-1:-1;;;;;41092:17:0;:31;;41012:112;40898:234;-1:-1:-1;;;40898:234:0:o;41140:810::-;41241:4;41197:23;26844:18;;;;;;;;;;;41279;;:22;;41300:1;41279:22;:::i;:::-;41261:15;:40;41258:98;;;41334:18;;:22;;41355:1;41334:22;:::i;:::-;41316:40;;41258:98;41384:13;41381:562;;;41436:50;;-1:-1:-1;;;41436:50:0;;-1:-1:-1;;;;;41468:16:0;2080:32:1;41436:50:0;;;2062:51:1;41413:20:0;;34753:42;;41436:23;;2035:18:1;;41436:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41413:73;;41501:34;41512:15;41529:5;41501:10;:34::i;:::-;41566:50;;-1:-1:-1;;;41566:50:0;;-1:-1:-1;;;;;41598:16:0;2080:32:1;41566:50:0;;;2062:51:1;41619:12:0;;34753:42;;41566:23;;2035:18:1;;41566:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:65;;;;:::i;:::-;41646:55;;-1:-1:-1;;;41646:55:0;;;;;1848:25:1;;;41551:80:0;;-1:-1:-1;41646:16:0;-1:-1:-1;;;;;41646:41:0;;;;1821:18:1;;41646:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;41721:27:0;;41735:12;;-1:-1:-1;41721:27:0;;-1:-1:-1;41721:27:0;;;41398:363;43123:333;;:::o;41381:562::-;41790:33;41801:15;41818:4;41790:10;:33::i;:::-;41865:17;;41857:65;;41840:12;;-1:-1:-1;;;;;41865:17:0;;41896:21;;41840:12;41857:65;41840:12;41857:65;41896:21;41865:17;41857:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;41186:764:0;41140:810;:::o;39669:1044::-;39800:14;:38;39714:20;;-1:-1:-1;;;;;;;;39800:38:0;;;;;39738:58;;-1:-1:-1;;;39756:40:0;;;;39738:15;:58;:::i;:::-;39737:101;;;;:::i;:::-;40002:14;:38;39714:124;;-1:-1:-1;;;;;;;;;40002:38:0;;;;;39940:58;;-1:-1:-1;;;39958:40:0;;;;39940:15;:58;:::i;:::-;39939:101;;;;:::i;:::-;39903:137;;:15;:137;:::i;:::-;39853:14;:188;;-1:-1:-1;;;;;39853:188:0;;;;-1:-1:-1;;;39853:188:0;-1:-1:-1;;;;;39853:188:0;;;;;;;;;40088:28;;-1:-1:-1;;;40088:28:0;;40103:12;-1:-1:-1;;;;;2080:32:1;40088:28:0;;;2062:51:1;-1:-1:-1;;40088:4:0;;:14;;2035:18:1;;40088:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40057:59;;40131:27;35127:1;40178:12;:44;40175:127;;;35127:1;40238:44;;40175:127;40318:9;40314:270;40332:12;40330:1;:14;40314:270;;;40414:14;:36;40364:22;;40389:74;;40456:6;;40389:62;;:20;;-1:-1:-1;;;40414:36:0;;-1:-1:-1;;;;;40414:36:0;40389:24;:62::i;:::-;:66;;:74::i;:::-;40364:99;-1:-1:-1;40482:38:0;40364:99;40482:38;;:::i;:::-;;-1:-1:-1;40535:37:0;40558:14;40535:37;;:::i;:::-;;;40349:235;40345:3;;;;;:::i;:::-;;;;40314:270;;;;40594:65;40610:12;40632:4;40639:19;40594:15;:65::i;:::-;40685:12;-1:-1:-1;;;;;40670:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39703:1010;;;39669:1044::o;40725:165::-;40778:11;40816:12;-1:-1:-1;;;;;40808:20:0;:4;-1:-1:-1;;;;;40808:20:0;;:73;;40858:22;;40845:10;;:35;;;;:::i;:::-;40808:73;;;-1:-1:-1;;40831:10:0;;;40725:165::o;41958:1157::-;42056:4;27410:7;27437:18;;;:11;:18;;;;;;;;34495:42;27437:27;;;;;;;;42090:11;-1:-1:-1;42035:143:0;;;42116:62;42133:4;34495:42;34169:20;42116:8;:62::i;:::-;42202:10;42199:909;;;42252:16;;;42266:1;42252:16;;;;;;;;42228:21;;42252:16;;;;;;;;;;-1:-1:-1;42252:16:0;42228:40;;42301:4;42283;42288:1;42283:7;;;;;;;;:::i;:::-;;;;;;:23;-1:-1:-1;;;;;42283:23:0;;;-1:-1:-1;;;;;42283:23:0;;;;;34753:42;42321:4;42326:1;42321:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;42321:15:0;;;:7;;;;;;;;;;;:15;42381:247;;-1:-1:-1;;;42381:247:0;;34495:42;;42381:65;;:247;;42465:11;;42495:1;;42543:4;;42574;;42598:15;;42381:247;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;42199:909;42693:16;;;42707:1;42693:16;;;;;;;;42669:21;;42693:16;;;;;;;;;;-1:-1:-1;42693:16:0;42669:40;;42742:4;42724;42729:1;42724:7;;;;;;;;:::i;:::-;;;;;;:23;-1:-1:-1;;;;;42724:23:0;;;-1:-1:-1;;;;;42724:23:0;;;;;34753:42;42762:4;42767:1;42762:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;42762:15:0;;;:7;;;;;;;;;;;:15;42834:262;;-1:-1:-1;;;42834:262:0;;34495:42;;42834:68;;:262;;42921:11;;42951:1;;42999:4;;43030:16;;43066:15;;42834:262;;;:::i;14784:471::-;14842:7;15087:6;15083:47;;-1:-1:-1;15117:1:0;15110:8;;15083:47;15142:9;15154:5;15158:1;15154;:5;:::i;:::-;15142:17;-1:-1:-1;15187:1:0;15178:5;15182:1;15142:17;15178:5;:::i;:::-;:10;15170:56;;;;-1:-1:-1;;;15170:56:0;;17485:2:1;15170:56:0;;;17467:21:1;17524:2;17504:18;;;17497:30;17563:34;17543:18;;;17536:62;-1:-1:-1;;;17614:18:1;;;17607:31;17655:19;;15170:56:0;17283:397:1;15731:132:0;15789:7;15816:39;15820:1;15823;15816:39;;;;;;;;;;;;;;;;;16445:7;16480:12;16473:5;16465:28;;;;-1:-1:-1;;;16465:28:0;;;;;;;;:::i;:::-;-1:-1:-1;16504:9:0;16516:5;16520:1;16516;:5;:::i;14:597:1:-;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;595:2:1;574:15;-1:-1:-1;;570:29:1;555:45;;;;602:2;551:54;;14:597;-1:-1:-1;;;14:597:1:o;616:131::-;-1:-1:-1;;;;;691:31:1;;681:42;;671:70;;737:1;734;727:12;752:315;820:6;828;881:2;869:9;860:7;856:23;852:32;849:52;;;897:1;894;887:12;849:52;936:9;923:23;955:31;980:5;955:31;:::i;:::-;1005:5;1057:2;1042:18;;;;1029:32;;-1:-1:-1;;;752:315:1:o;1264:248::-;1332:6;1340;1393:2;1381:9;1372:7;1368:23;1364:32;1361:52;;;1409:1;1406;1399:12;1361:52;-1:-1:-1;;1432:23:1;;;1502:2;1487:18;;;1474:32;;-1:-1:-1;1264:248:1:o;1517:180::-;1576:6;1629:2;1617:9;1608:7;1604:23;1600:32;1597:52;;;1645:1;1642;1635:12;1597:52;-1:-1:-1;1668:23:1;;1517:180;-1:-1:-1;1517:180:1:o;2124:456::-;2201:6;2209;2217;2270:2;2258:9;2249:7;2245:23;2241:32;2238:52;;;2286:1;2283;2276:12;2238:52;2325:9;2312:23;2344:31;2369:5;2344:31;:::i;:::-;2394:5;-1:-1:-1;2451:2:1;2436:18;;2423:32;2464:33;2423:32;2464:33;:::i;:::-;2124:456;;2516:7;;-1:-1:-1;;;2570:2:1;2555:18;;;;2542:32;;2124:456::o;2774:247::-;2833:6;2886:2;2874:9;2865:7;2861:23;2857:32;2854:52;;;2902:1;2899;2892:12;2854:52;2941:9;2928:23;2960:31;2985:5;2960:31;:::i;3026:171::-;3093:20;;-1:-1:-1;;;;;3142:30:1;;3132:41;;3122:69;;3187:1;3184;3177:12;3122:69;3026:171;;;:::o;3202:256::-;3268:6;3276;3329:2;3317:9;3308:7;3304:23;3300:32;3297:52;;;3345:1;3342;3335:12;3297:52;3368:28;3386:9;3368:28;:::i;:::-;3358:38;;3415:37;3448:2;3437:9;3433:18;3415:37;:::i;:::-;3405:47;;3202:256;;;;;:::o;3931:184::-;3989:6;4042:2;4030:9;4021:7;4017:23;4013:32;4010:52;;;4058:1;4055;4048:12;4010:52;4081:28;4099:9;4081:28;:::i;5511:388::-;5579:6;5587;5640:2;5628:9;5619:7;5615:23;5611:32;5608:52;;;5656:1;5653;5646:12;5608:52;5695:9;5682:23;5714:31;5739:5;5714:31;:::i;:::-;5764:5;-1:-1:-1;5821:2:1;5806:18;;5793:32;5834:33;5793:32;5834:33;:::i;:::-;5886:7;5876:17;;;5511:388;;;;;:::o;5904:380::-;5983:1;5979:12;;;;6026;;;6047:61;;6101:4;6093:6;6089:17;6079:27;;6047:61;6154:2;6146:6;6143:14;6123:18;6120:38;6117:161;;;6200:10;6195:3;6191:20;6188:1;6181:31;6235:4;6232:1;6225:15;6263:4;6260:1;6253:15;6117:161;;5904:380;;;:::o;6289:356::-;6491:2;6473:21;;;6510:18;;;6503:30;6569:34;6564:2;6549:18;;6542:62;6636:2;6621:18;;6289:356::o;6650:127::-;6711:10;6706:3;6702:20;6699:1;6692:31;6742:4;6739:1;6732:15;6766:4;6763:1;6756:15;6782:168;6822:7;6888:1;6884;6880:6;6876:14;6873:1;6870:21;6865:1;6858:9;6851:17;6847:45;6844:71;;;6895:18;;:::i;:::-;-1:-1:-1;6935:9:1;;6782:168::o;6955:127::-;7016:10;7011:3;7007:20;7004:1;6997:31;7047:4;7044:1;7037:15;7071:4;7068:1;7061:15;7087:120;7127:1;7153;7143:35;;7158:18;;:::i;:::-;-1:-1:-1;7192:9:1;;7087:120::o;7212:184::-;7282:6;7335:2;7323:9;7314:7;7310:23;7306:32;7303:52;;;7351:1;7348;7341:12;7303:52;-1:-1:-1;7374:16:1;;7212:184;-1:-1:-1;7212:184:1:o;7706:277::-;7773:6;7826:2;7814:9;7805:7;7801:23;7797:32;7794:52;;;7842:1;7839;7832:12;7794:52;7874:9;7868:16;7927:5;7920:13;7913:21;7906:5;7903:32;7893:60;;7949:1;7946;7939:12;8815:306;8903:6;8911;8919;8972:2;8960:9;8951:7;8947:23;8943:32;8940:52;;;8988:1;8985;8978:12;8940:52;9017:9;9011:16;9001:26;;9067:2;9056:9;9052:18;9046:25;9036:35;;9111:2;9100:9;9096:18;9090:25;9080:35;;8815:306;;;;;:::o;10509:681::-;10640:6;10648;10656;10664;10672;10680;10688;10696;10749:3;10737:9;10728:7;10724:23;10720:33;10717:53;;;10766:1;10763;10756:12;10717:53;10798:9;10792:16;10817:31;10842:5;10817:31;:::i;:::-;10867:5;10857:15;;;10912:2;10901:9;10897:18;10891:25;10881:35;;10956:2;10945:9;10941:18;10935:25;10925:35;;11000:2;10989:9;10985:18;10979:25;10969:35;;11044:3;11033:9;11029:19;11023:26;11013:36;;11089:3;11078:9;11074:19;11068:26;11058:36;;11134:3;11123:9;11119:19;11113:26;11103:36;;11179:3;11168:9;11164:19;11158:26;11148:36;;10509:681;;;;;;;;;;;:::o;11195:127::-;11256:10;11251:3;11247:20;11244:1;11237:31;11287:4;11284:1;11277:15;11311:4;11308:1;11301:15;12645:128;12685:3;12716:1;12712:6;12709:1;12706:13;12703:39;;;12722:18;;:::i;:::-;-1:-1:-1;12758:9:1;;12645:128::o;13942:401::-;14144:2;14126:21;;;14183:2;14163:18;;;14156:30;14222:34;14217:2;14202:18;;14195:62;-1:-1:-1;;;14288:2:1;14273:18;;14266:35;14333:3;14318:19;;13942:401::o;14348:399::-;14550:2;14532:21;;;14589:2;14569:18;;;14562:30;14628:34;14623:2;14608:18;;14601:62;-1:-1:-1;;;14694:2:1;14679:18;;14672:33;14737:3;14722:19;;14348:399::o;15111:236::-;15150:3;-1:-1:-1;;;;;15223:2:1;15220:1;15216:10;15253:2;15250:1;15246:10;15284:3;15280:2;15276:12;15271:3;15268:21;15265:47;;;15292:18;;:::i;:::-;15328:13;;15111:236;-1:-1:-1;;;;15111:236:1:o;15352:125::-;15392:4;15420:1;15417;15414:8;15411:34;;;15425:18;;:::i;:::-;-1:-1:-1;15462:9:1;;15352:125::o;15777:112::-;15809:1;15835;15825:35;;15840:18;;:::i;:::-;-1:-1:-1;15874:9:1;;15777:112::o;15894:135::-;15933:3;-1:-1:-1;;15954:17:1;;15951:43;;;15974:18;;:::i;:::-;-1:-1:-1;16021:1:1;16010:13;;15894:135::o;16166:127::-;16227:10;16222:3;16218:20;16215:1;16208:31;16258:4;16255:1;16248:15;16282:4;16279:1;16272:15;16298:980;16560:4;16608:3;16597:9;16593:19;16639:6;16628:9;16621:25;16665:2;16703:6;16698:2;16687:9;16683:18;16676:34;16746:3;16741:2;16730:9;16726:18;16719:31;16770:6;16805;16799:13;16836:6;16828;16821:22;16874:3;16863:9;16859:19;16852:26;;16913:2;16905:6;16901:15;16887:29;;16934:1;16944:195;16958:6;16955:1;16952:13;16944:195;;;17023:13;;-1:-1:-1;;;;;17019:39:1;17007:52;;17114:15;;;;17079:12;;;;17055:1;16973:9;16944:195;;;-1:-1:-1;;;;;;;17195:32:1;;;;17190:2;17175:18;;17168:60;-1:-1:-1;;;17259:3:1;17244:19;17237:35;17156:3;16298:980;-1:-1:-1;;;16298:980:1:o

Swarm Source

ipfs://2c2fca69716ec5f39a6f1e09781bb4fef228733e5e906cc78d2f201a1f879fd7
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.