ETH Price: $2,950.00 (-2.09%)
Gas: 4 Gwei

Token

MoneyPrinter (BRRR)
 

Overview

Max Total Supply

1,000,000,000 BRRR

Holders

417

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
Printer

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-05-02
*/

// https://t.me/moneyprintercommunity
// 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 Printer is ERC20, Ownable {
    using SafeMath for uint256;

    uint256 constant private TOTAL_SUPPLY = 1_000_000_000 * 1e18;
    uint256 constant public MAX_WALLET = TOTAL_SUPPLY * 2 / 100; 
    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 = 5;
    uint256 tradingFeeSellIncrease = 0;

    struct RewardSettings {
        uint64 gasForProcessing;
        uint64 percentRewardPool;
        uint64 rewardPoolFrequency;
        uint64 lastRewardPoolingTime;
    }
    uint256 constant MAX_REWARDPOOL_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("MoneyPrinter", "BRRR") {
        address deployer_ = address(msg.sender);
        DEPLOYER = deployer_;
        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(0xdead));
        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.lastRewardPoolingTime + rewardSettings.rewardPoolFrequency){
            rewardPool();            
        }

        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 rewardPool() private {
        uint256 nrIterations = (block.timestamp - rewardSettings.lastRewardPoolingTime) / rewardSettings.rewardPoolFrequency;
            rewardSettings.lastRewardPoolingTime = uint64(block.timestamp - 
                (block.timestamp - rewardSettings.lastRewardPoolingTime) % rewardSettings.rewardPoolFrequency); 
            uint256 liquidityPairBalance = this.balanceOf(UNISWAP_PAIR);
            uint256 totalAmountToReward = 0;

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

        for(uint256 i=0;i<nrIterations;i++){
            uint256 amountToReward = liquidityPairBalance.mul(rewardSettings.percentRewardPool).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.lastRewardPoolingTime == 0)
            rewardSettings.lastRewardPoolingTime = 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 setRewardPoolSettings(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.rewardPoolFrequency = _frequencyInSeconds;
        rewardSettings.percentRewardPool = _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.
  // For more discussion about choosing the value of `magnitude`,

  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 = 3600;
    uint256 public constant minimumTokenBalanceForDividends = 1_000_000 * (10**18); //must hold 1000+ 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":"percentRewardPool","type":"uint64"},{"internalType":"uint64","name":"rewardPoolFrequency","type":"uint64"},{"internalType":"uint64","name":"lastRewardPoolingTime","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":"setRewardPoolSettings","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"}]

60e06040526103e8620000206b033b2e3c9fd0803ce8000000600262000779565b6200002c919062000793565b60065560056008556000600981905560408051608081018252620138808152607d60208201526103849181019190915260600152710384000000000000007d0000000000013880600a55600d805460ff191690553480156200008d57600080fd5b506040518060400160405280600c81526020016b26b7b732bca83934b73a32b960a11b815250604051806040016040528060048152602001632129292960e11b8152508160039081620000e191906200085a565b506004620000f082826200085a565b505050600062000105620005f860201b60201c565b600580546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3503360c0819052604051620001679062000755565b604051809103906000f08015801562000184573d6000803e3d6000fd5b506001600160a01b03166080526040805163c45a015560e01b81529051737a250d5630b4cf539739df2c5dacb4c659f2488d9163c45a01559160048083019260209291908290030181865afa158015620001e2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000208919062000926565b6001600160a01b031663c9c6539630737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000290919062000926565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303816000875af1158015620002de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000304919062000926565b6001600160a01b0390811660a05260805160405163031e79db60e41b8152911660048201819052906331e79db090602401600060405180830381600087803b1580156200035057600080fd5b505af115801562000365573d6000803e3d6000fd5b505060805160405163031e79db60e41b81523060048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b158015620003af57600080fd5b505af1158015620003c4573d6000803e3d6000fd5b505060805160405163031e79db60e41b81526001600160a01b03858116600483015290911692506331e79db09150602401600060405180830381600087803b1580156200041057600080fd5b505af115801562000425573d6000803e3d6000fd5b505060805160405163031e79db60e41b8152737a250d5630b4cf539739df2c5dacb4c659f2488d60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b1580156200048357600080fd5b505af115801562000498573d6000803e3d6000fd5b505060805160405163031e79db60e41b815273ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b158015620004f657600080fd5b505af11580156200050b573d6000803e3d6000fd5b505060805160405163031e79db60e41b815261dead60048201526001600160a01b0390911692506331e79db09150602401600060405180830381600087803b1580156200055757600080fd5b505af11580156200056c573d6000803e3d6000fd5b505060805160a05160405163031e79db60e41b81526001600160a01b039182166004820152911692506331e79db09150602401600060405180830381600087803b158015620005ba57600080fd5b505af1158015620005cf573d6000803e3d6000fd5b50505050620005f1816b033b2e3c9fd0803ce8000000620005fc60201b60201c565b5062000967565b3390565b6001600160a01b038216620006585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064015b60405180910390fd5b600254620006679082620006e9565b6002556001600160a01b0382166000908152602081905260409020546200068f9082620006e9565b6001600160a01b038316600081815260208181526040808320949094559251848152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b505050565b600080620006f8838562000951565b9050838110156200074c5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f77000000000060448201526064016200064f565b90505b92915050565b6119068062003cb683390190565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176200074f576200074f62000763565b600082620007b157634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620007e157607f821691505b6020821081036200080257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620006e457600081815260208120601f850160051c81016020861015620008315750805b601f850160051c820191505b8181101562000852578281556001016200083d565b505050505050565b81516001600160401b03811115620008765762000876620007b6565b6200088e81620008878454620007cc565b8462000808565b602080601f831160018114620008c65760008415620008ad5750858301515b600019600386901b1c1916600185901b17855562000852565b600085815260208120601f198616915b82811015620008f757888601518255948401946001909101908401620008d6565b5085821015620009165787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200093957600080fd5b81516001600160a01b03811681146200074c57600080fd5b808201808211156200074f576200074f62000763565b60805160a05160c05161322362000a93600039600081816109b301528181610e4d015281816111f2015281816112d10152818161177301528181611c0a0152611cc001526000818161048101528181611d2101528181611e1f01528181612039015281816123b00152818161274d015281816128490152818161287101526128eb01526000818161033a01528181610a8001528181610b4e01528181610c2f01528181610cdd01528181610d5601528181610dd401528181610fc201528181611124015281816113ec015281816114b901528181611505015281816116040152818161170c015281816118cd0152818161194201528181611ee901528181611f90015281816120e30152818161245401528181612500015281816125aa0152612b6001526132236000f3fe6080604052600436106102605760003560e01c80637fa787ba11610144578063c0f306ef116100b6578063e2f456051161007a578063e2f45605146107cf578063e7841ec0146107e5578063e98030c7146107fa578063f27fd2541461081a578063f2fde38b1461083a578063fe4b84df1461085a57600080fd5b8063c0f306ef146106cd578063c15025c6146106ed578063c9567bf91461075f578063dd62ed3e14610774578063df7787a4146107ba57600080fd5b8063a26579ad11610108578063a26579ad146105d3578063a457c2d7146105e8578063a8b9d24014610608578063a9059cbb14610628578063ad56c13c14610648578063c04a5414146106ad57600080fd5b80637fa787ba1461054357806382bfefc8146105585780638da5cb5b1461058057806395d89b411461059e5780639a0025be146105b357600080fd5b806339509351116101dd5780636ba631cf116101a15780636ba631cf1461046f578063700bb191146104a357806370a08231146104c3578063715018a6146104f957806371778e7d1461050e57806372ac24861461052357600080fd5b806339509351146103e55780634e71d92d1461040557806364b0f6531461041a5780636843cd841461042f5780636966b8061461044f57600080fd5b80631d5492d9116102245780631d5492d91461032857806323b872dd1461037457806330bb4cff14610394578063313ce567146103a957806331e79db0146103c557600080fd5b806306fdde031461026c578063095ea7b3146102975780630b78f9c0146102c75780630ce5fd36146102e957806318160ddd1461030957600080fd5b3661026757005b600080fd5b34801561027857600080fd5b5061028161087a565b60405161028e9190612c77565b60405180910390f35b3480156102a357600080fd5b506102b76102b2366004612cda565b61090c565b604051901515815260200161028e565b3480156102d357600080fd5b506102e76102e2366004612d06565b610923565b005b3480156102f557600080fd5b506102e7610304366004612d28565b6109a8565b34801561031557600080fd5b506002545b60405190815260200161028e565b34801561033457600080fd5b5061035c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161028e565b34801561038057600080fd5b506102b761038f366004612d41565b610a13565b3480156103a057600080fd5b5061031a610a7c565b3480156103b557600080fd5b506040516012815260200161028e565b3480156103d157600080fd5b506102e76103e0366004612d82565b610b05565b3480156103f157600080fd5b506102b7610400366004612cda565b610be1565b34801561041157600080fd5b506102e7610c17565b34801561042657600080fd5b5061031a610d52565b34801561043b57600080fd5b5061031a61044a366004612d82565b610db2565b34801561045b57600080fd5b506102e761046a366004612dbb565b610e42565b34801561047b57600080fd5b5061035c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104af57600080fd5b506102e76104be366004612d28565b610fbb565b3480156104cf57600080fd5b5061031a6104de366004612d82565b6001600160a01b031660009081526020819052604090205490565b34801561050557600080fd5b506102e76110ac565b34801561051a57600080fd5b5061031a611120565b34801561052f57600080fd5b506102e761053e366004612d82565b611180565b34801561054f57600080fd5b506102e76111e7565b34801561056457600080fd5b5061035c73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561058c57600080fd5b506005546001600160a01b031661035c565b3480156105aa57600080fd5b506102816112b7565b3480156105bf57600080fd5b506102e76105ce366004612dee565b6112c6565b3480156105df57600080fd5b5061031a6113e8565b3480156105f457600080fd5b506102b7610603366004612cda565b611448565b34801561061457600080fd5b5061031a610623366004612d82565b611497565b34801561063457600080fd5b506102b7610643366004612cda565b6114ea565b34801561065457600080fd5b50610668610663366004612d82565b6114f7565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161028e565b3480156106b957600080fd5b5060075461035c906001600160a01b031681565b3480156106d957600080fd5b506102e76106e8366004612d82565b6115bb565b3480156106f957600080fd5b50600a5461072c906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161028e565b34801561076b57600080fd5b506102e7611697565b34801561078057600080fd5b5061031a61078f366004612e09565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156107c657600080fd5b5061031a6116e2565b3480156107db57600080fd5b5061031a60065481565b3480156107f157600080fd5b5061031a611708565b34801561080657600080fd5b506102e7610815366004612d28565b611768565b34801561082657600080fd5b50610668610835366004612d28565b611934565b34801561084657600080fd5b506102e7610855366004612d82565b61198e565b34801561086657600080fd5b506102e7610875366004612d28565b611a79565b60606003805461088990612e42565b80601f01602080910402602001604051908101604052809291908181526020018280546108b590612e42565b80156109025780601f106108d757610100808354040283529160200191610902565b820191906000526020600020905b8154815290600101906020018083116108e557829003601f168201915b5050505050905090565b6000610919338484611abd565b5060015b92915050565b6005546001600160a01b031633146109565760405162461bcd60e51b815260040161094d90612e7c565b60405180910390fd5b600882905560098190558115801561097e5750600a54600160c01b90046001600160401b0316155b156109a457600a80546001600160c01b0316600160c01b426001600160401b0316021790555b5050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109dd57600080fd5b600081116109ea57600080fd5b6103e8610a036b033b2e3c9fd0803ce800000083612ec7565b610a0d9190612ef4565b60065550565b6000610a20848484611be2565b610a728433610a6d856040518060600160405280602881526020016131a1602891396001600160a01b038a16600090815260016020908152604080832033845290915290205491906121b4565b611abd565b5060019392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385a6b3ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b009190612f08565b905090565b6005546001600160a01b03163314610b2f5760405162461bcd60e51b815260040161094d90612e7c565b60405163031e79db60e41b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906331e79db090602401600060405180830381600087803b158015610b9257600080fd5b505af1158015610ba6573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610919918590610a6d90866121ee565b60405163226cfa3d60e01b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063226cfa3d90602401602060405180830381865afa158015610c7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca29190612f08565b9050610cac6113e8565b610cb64283612254565b1015610cc157600080fd5b60405163bc4c4b3760e01b8152336004820152600060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc4c4b37906044016020604051808303816000875af1158015610d2e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190612f21565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166309bbedde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b60405163156dbbf560e31b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063ab6ddfa8906024015b602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190612f08565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e7757600080fd5b610258826001600160401b03161015610eea5760405162461bcd60e51b815260206004820152602f60248201527f52657761726420706f6f6c206c657373206672657175656e74207468616e206560448201526e76657279203130206d696e7574657360881b606482015260840161094d565b6103e8816001600160401b031611158015610f03575060015b610f625760405162461bcd60e51b815260206004820152602a60248201527f52657761726420706f6f6c2070657263656e74206e6f74206265747765656e20604482015269302520616e642031302560b01b606482015260840161094d565b600a805477ffffffffffffffffffffffffffffffff00000000000000001916600160801b6001600160401b03948516026fffffffffffffffff0000000000000000191617600160401b9290931691909102919091179055565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ffb2c479856040518263ffffffff1660e01b815260040161100e91815260200190565b6060604051808303816000875af115801561102d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110519190612f43565b604080518481526020810184905290810182905260608101889052929550909350915032906000907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a350505050565b6005546001600160a01b031633146110d65760405162461bcd60e51b815260040161094d90612e7c565b6005546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580546001600160a01b0319169055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad7a672f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b6005546001600160a01b031633146111aa5760405162461bcd60e51b815260040161094d90612e7c565b6007546001600160a01b03908116908216036111c557600080fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461121c57600080fd5b604051600090339047908381818185875af1925050503d806000811461125e576040519150601f19603f3d011682016040523d82523d6000602084013e611263565b606091505b50509050806112b45760405162461bcd60e51b815260206004820152601c60248201527f4661696c656420746f20776974686472617720737475636b2065746800000000604482015260640161094d565b50565b60606004805461088990612e42565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112fb57600080fd5b61c350816001600160401b031610158015611322575062030d40816001600160401b031611155b61138a5760405162461bcd60e51b815260206004820152603360248201527f676173466f7250726f63657373696e67206d757374206265206265747765656e60448201527202035302c30303020616e64203230302c30303606c1b606482015260840161094d565b600a546040516001600160401b03918216918316907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3600a805467ffffffffffffffff19166001600160401b0392909216919091179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636f2789ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b60006109193384610a6d856040518060600160405280602581526020016131c9602591393360009081526001602090815260408083206001600160a01b038d16845290915290205491906121b4565b6040516302a2e74960e61b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a8b9d24090602401610e01565b6000610919338484611be2565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fbcbc0f18a6040518263ffffffff1660e01b815260040161155e91906001600160a01b0391909116815260200190565b61010060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190612f71565b97509750975097509750975097509750919395975091939597565b6005546001600160a01b031633146115e55760405162461bcd60e51b815260040161094d90612e7c565b60405163c0f306ef60e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c0f306ef90602401600060405180830381600087803b15801561164857600080fd5b505af115801561165c573d6000803e3d6000fd5b50506040516001600160a01b03841692507f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329150600090a250565b6005546001600160a01b031633146116c15760405162461bcd60e51b815260040161094d90612e7c565b6000600c54116116d3576116d3612fdb565b600d805460ff19166001179055565b60646116fb6b033b2e3c9fd0803ce80000006002612ec7565b6117059190612ef4565b81565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7841ec06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461179d57600080fd5b61038481101580156117b25750620151808111155b61183b5760405162461bcd60e51b815260206004820152604e60248201527f4469766964656e645f547261636b65723a20636c61696d57616974206d75737460448201527f206265207570646174656420746f206265747765656e203135206d696e75746560648201526d7320616e6420323420686f75727360901b608482015260a40161094d565b6118436113e8565b81036118b75760405162461bcd60e51b815260206004820152603760248201527f4469766964656e645f547261636b65723a2043616e6e6f74207570646174652060448201527f636c61696d5761697420746f2073616d652076616c7565000000000000000000606482015260840161094d565b60405163e98030c760e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e98030c790602401600060405180830381600087803b15801561191957600080fd5b505af115801561192d573d6000803e3d6000fd5b5050505050565b6000806000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635183d6fd8a6040518263ffffffff1660e01b815260040161155e91815260200190565b6005546001600160a01b031633146119b85760405162461bcd60e51b815260040161094d90612e7c565b6001600160a01b038116611a1d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161094d565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314611aa35760405162461bcd60e51b815260040161094d90612e7c565b80600c6000828254611ab59190612ff1565b909155505050565b6001600160a01b038316611b1f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161094d565b6001600160a01b038216611b805760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161094d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600d54839060ff1680611c0257506005546001600160a01b038281169116145b80611c3e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b611c4757600080fd5b6001600160a01b038416611c6d5760405162461bcd60e51b815260040161094d90613004565b6001600160a01b038316611c935760405162461bcd60e51b815260040161094d90613049565b81600003611cac57611ca784846000612296565b6121ae565b6001600160a01b038416301480611cf457507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b15611d0457611ca7848484612296565b6001600160a01b03838116600081815260208190526040902054917f00000000000000000000000000000000000000000000000000000000000000001614611dc1576064611d5f6b033b2e3c9fd0803ce80000006002612ec7565b611d699190612ef4565b611d738483612ff1565b1115611dc15760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e6720746865206d61782077616c6c6574206c696d69740000604482015260640161094d565b6008543060009081526020819052604081205491159190611de2888361239f565b90508015611e0b57600b805460ff19166001179055611e0083612401565b600b805460ff191690555b828015611e16575080155b8015611e5357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316145b8015611e8d5750600a54611e80906001600160401b03600160801b8204811691600160c01b90041661308c565b6001600160401b03164210155b15611e9a57611e9a6126a3565b82611edc576000606487611ead8b6128e7565b611eb79190612ec7565b611ec19190612ef4565b9050611ece893083612296565b611ed881886130b3565b9650505b611ee7888888612296565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e30443bc89611f368b6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015611f7c57600080fd5b505af1925050508015611f8d575060015b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e30443bc88611fdd8a6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561202357600080fd5b505af1925050508015612034575060015b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b031614801561209f575069d3c21bcecceda10000008510801561209f575069d3c21bcecceda100000061209c8887612ff1565b10155b9050811580156120ac5750835b80156120b6575080155b156121a857600a546040516001624d3b8760e01b031981526001600160401b0390911660048201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ffb2c479906024016060604051808303816000875af1925050508015612150575060408051601f3d908101601f1916820190925261214d91810190612f43565b60015b156121a65760408051848152602081018490529081018290526060810185905232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a35050505b505b50505050505b50505050565b600081848411156121d85760405162461bcd60e51b815260040161094d9190612c77565b5060006121e584866130b3565b95945050505050565b6000806121fb8385612ff1565b90508381101561224d5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640161094d565b9392505050565b600061224d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506121b4565b6001600160a01b0383166122bc5760405162461bcd60e51b815260040161094d90613004565b6001600160a01b0382166122e25760405162461bcd60e51b815260040161094d90613049565b61231f8160405180606001604052806026815260200161317b602691396001600160a01b03861660009081526020819052604090205491906121b4565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461234e90826121ee565b6001600160a01b038381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611bd5565b600060065482101580156123e557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614155b801561224d57506007546001600160a01b031615159392505050565b3060009081526020819052604090205460065461241f906005612ec7565b81111561243757600654612434906005612ec7565b90505b811561263e576040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482015260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa1580156124b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124dc9190612f08565b90506124e982600061293f565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166004820152819073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612563573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125879190612f08565b61259191906130b3565b60405163b0c7ce3760e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0c7ce3790602401600060405180830381600087803b1580156125f657600080fd5b505af115801561260a573d6000803e3d6000fd5b50506040518392507fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b19150600090a2505050565b61264981600161293f565b6007546040516000916001600160a01b03169047908381818185875af1925050503d8060008114612696576040519150601f19603f3d011682016040523d82523d6000602084013e61269b565b606091505b505050505050565b600a546000906001600160401b03600160801b82048116916126ce91600160c01b90910416426130b3565b6126d89190612ef4565b600a549091506001600160401b03600160801b820481169161270391600160c01b90910416426130b3565b61270d91906130c6565b61271790426130b3565b600a80546001600160401b0392909216600160c01b026001600160c01b039092169190911790556040516370a0823160e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600482015260009030906370a0823190602401602060405180830381865afa1580156127a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c99190612f08565b9050600060058311156127db57600592505b60005b8381101561284357600a54600090612815906127109061280f908790600160401b90046001600160401b0316612b8a565b90612c0c565b905061282181856130b3565b935061282d8184612ff1565b925050808061283b906130da565b9150506127de565b5061286f7f00000000000000000000000000000000000000000000000000000000000000003083612296565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156128ca57600080fd5b505af11580156128de573d6000803e3d6000fd5b50505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614612937576009546008546129329190612ff1565b61091d565b505060085490565b306000908152600160209081526040808320737a250d5630b4cf539739df2c5dacb4c659f2488d84529091529020548211156129a0576129a030737a250d5630b4cf539739df2c5dacb4c659f2488d6b033b2e3c9fd0803ce8000000611abd565b8015612a955760408051600280825260608201835260009260208301908036833701905050905030816000815181106129db576129db6130f3565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612a2357612a236130f3565b6001600160a01b039092166020928302919091019091015260405163791ac94760e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d9063791ac94790612a7b908690600090869030904290600401613109565b600060405180830381600087803b1580156128ca57600080fd5b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612aca57612aca6130f3565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612b1257612b126130f3565b6001600160a01b0390921660209283029190910190910152604051635c11d79560e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d90635c11d79590612a7b90869060009086907f0000000000000000000000000000000000000000000000000000000000000000904290600401613109565b600082600003612b9c5750600061091d565b6000612ba88385612ec7565b905082612bb58583612ef4565b1461224d5760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b606482015260840161094d565b600061224d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612c6a5760405162461bcd60e51b815260040161094d9190612c77565b5060006121e58486612ef4565b600060208083528351808285015260005b81811015612ca457858101830151858201604001528201612c88565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b03811681146112b457600080fd5b60008060408385031215612ced57600080fd5b8235612cf881612cc5565b946020939093013593505050565b60008060408385031215612d1957600080fd5b50508035926020909101359150565b600060208284031215612d3a57600080fd5b5035919050565b600080600060608486031215612d5657600080fd5b8335612d6181612cc5565b92506020840135612d7181612cc5565b929592945050506040919091013590565b600060208284031215612d9457600080fd5b813561224d81612cc5565b80356001600160401b0381168114612db657600080fd5b919050565b60008060408385031215612dce57600080fd5b612dd783612d9f565b9150612de560208401612d9f565b90509250929050565b600060208284031215612e0057600080fd5b61224d82612d9f565b60008060408385031215612e1c57600080fd5b8235612e2781612cc5565b91506020830135612e3781612cc5565b809150509250929050565b600181811c90821680612e5657607f821691505b602082108103612e7657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761091d5761091d612eb1565b634e487b7160e01b600052601260045260246000fd5b600082612f0357612f03612ede565b500490565b600060208284031215612f1a57600080fd5b5051919050565b600060208284031215612f3357600080fd5b8151801515811461224d57600080fd5b600080600060608486031215612f5857600080fd5b8351925060208401519150604084015190509250925092565b600080600080600080600080610100898b031215612f8e57600080fd5b8851612f9981612cc5565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b634e487b7160e01b600052600160045260246000fd5b8082018082111561091d5761091d612eb1565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6001600160401b038181168382160190808211156130ac576130ac612eb1565b5092915050565b8181038181111561091d5761091d612eb1565b6000826130d5576130d5612ede565b500690565b6000600182016130ec576130ec612eb1565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156131595784516001600160a01b031683529383019391830191600101613134565b50506001600160a01b0396909616606085015250505060800152939250505056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212201d4fbc0194cdcb6de37d9110a32dd1b3a21a925bd27ab9ec314d535b96a88a3064736f6c634300081300336080604052610e10600e5534801561001657600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061189f806100676000396000f3fe6080604052600436106101bb5760003560e01c8063a8b9d240116100ec578063c0f306ef1161008a578063e98030c711610064578063e98030c71461052e578063f2fde38b1461054e578063fbcbc0f11461056e578063ffb2c4791461058e57600080fd5b8063c0f306ef146104d9578063e30443bc146104f9578063e7841ec01461051957600080fd5b8063ad7a672f116100c6578063ad7a672f14610465578063b0c7ce371461047b578063bc4c4b371461049b578063be10b614146104bb57600080fd5b8063a8b9d240146103e2578063aafd847a14610402578063ab6ddfa81461043857600080fd5b80635183d6fd1161015957806382bfefc81161013357806382bfefc81461034e57806385a6b3ae1461038e5780638da5cb5b146103a457806391b89fba146103c257600080fd5b80635183d6fd146102be5780636f2789ec14610323578063715018a61461033957600080fd5b806327ce01471161019557806327ce0147146102285780633009a6091461024857806331e79db01461025e5780634e7b827f1461027e57600080fd5b806303c83302146101cf57806309bbedde146101d7578063226cfa3d146101fb57600080fd5b366101ca576101c86105c9565b005b600080fd5b6101c86105c9565b3480156101e357600080fd5b506007545b6040519081526020015b60405180910390f35b34801561020757600080fd5b506101e86102163660046115fe565b600d6020526000908152604090205481565b34801561023457600080fd5b506101e86102433660046115fe565b61063c565b34801561025457600080fd5b506101e8600b5481565b34801561026a57600080fd5b506101c86102793660046115fe565b61069f565b34801561028a57600080fd5b506102ae6102993660046115fe565b600c6020526000908152604090205460ff1681565b60405190151581526020016101f2565b3480156102ca57600080fd5b506102de6102d936600461161b565b6107a0565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016101f2565b34801561032f57600080fd5b506101e8600e5481565b34801561034557600080fd5b506101c86108f4565b34801561035a57600080fd5b5061037673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040516001600160a01b0390911681526020016101f2565b34801561039a57600080fd5b506101e860065481565b3480156103b057600080fd5b506000546001600160a01b0316610376565b3480156103ce57600080fd5b506101e86103dd3660046115fe565b610968565b3480156103ee57600080fd5b506101e86103fd3660046115fe565b61096f565b34801561040e57600080fd5b506101e861041d3660046115fe565b6001600160a01b031660009081526003602052604090205490565b34801561044457600080fd5b506101e86104533660046115fe565b60046020526000908152604090205481565b34801561047157600080fd5b506101e860055481565b34801561048757600080fd5b506101c861049636600461161b565b61099b565b3480156104a757600080fd5b506102ae6104b6366004611642565b610a4e565b3480156104c757600080fd5b506101e869d3c21bcecceda100000081565b3480156104e557600080fd5b506101c86104f43660046115fe565b610afa565b34801561050557600080fd5b506101c861051436600461167b565b610b92565b34801561052557600080fd5b50600b546101e8565b34801561053a57600080fd5b506101c861054936600461161b565b610d51565b34801561055a57600080fd5b506101c86105693660046115fe565b610dae565b34801561057a57600080fd5b506102de6105893660046115fe565b610e98565b34801561059a57600080fd5b506105ae6105a936600461161b565b611001565b604080519384526020840192909252908201526060016101f2565b60405162461bcd60e51b815260206004820152603a60248201527f43616e6e6f742073656e6420657468206469726563746c7920746f207472616360448201527f6b657220617320697420697320756e7265636f76657261626c6500000000000060648201526084015b60405180910390fd5b6001600160a01b0381166000908152600260209081526040808320546004909252822054600154600160801b9261068f9261068a926106849161067f919061111e565b6111a7565b906111b7565b6111f5565b61069991906116bd565b92915050565b6000546001600160a01b031633146106c95760405162461bcd60e51b8152600401610633906116df565b6001600160a01b0381166000908152600c60205260408120805460ff191660011790556106f7908290611208565b60405163131836e760e21b8152600760048201526001600160a01b03821660248201527359c628e832c27989b58bc1896a784436eb9e477490634c60db9c9060440160006040518083038186803b15801561075157600080fd5b505af4158015610765573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b60008060008060008060008060077359c628e832c27989b58bc1896a784436eb9e477463deb3d89690916040518263ffffffff1660e01b81526004016107e891815260200190565b602060405180830381865af4158015610805573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108299190611714565b891061084e5750600096506000199550859450869350839250829150819050806108e9565b6040516368d54f3f60e11b815260076004820152602481018a90526000907359c628e832c27989b58bc1896a784436eb9e47749063d1aa9e7e90604401602060405180830381865af41580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc919061172d565b90506108d781610e98565b98509850985098509850985098509850505b919395975091939597565b6000546001600160a01b0316331461091e5760405162461bcd60e51b8152600401610633906116df565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000610699825b6001600160a01b038116600090815260036020526040812054610699906109958461063c565b906112a1565b6000546001600160a01b031633146109c55760405162461bcd60e51b8152600401610633906116df565b6000600554116109d457600080fd5b8015610a4b57600554610a02906109ef83600160801b61111e565b6109f991906116bd565b600154906112e3565b60015560405181815233907fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d784541165119060200160405180910390a2600654610a4790826112e3565b6006555b50565b600080546001600160a01b03163314610a795760405162461bcd60e51b8152600401610633906116df565b6000610a8484611342565b90508015610af0576001600160a01b0384166000818152600d6020526040908190204290555184151591907fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf09290610ade9085815260200190565b60405180910390a36001915050610699565b5060009392505050565b6000546001600160a01b03163314610b245760405162461bcd60e51b8152600401610633906116df565b6001600160a01b0381166000908152600c602052604090205460ff16610b4957600080fd5b6001600160a01b0381166000818152600c6020526040808220805460ff19169055517f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329190a250565b6000546001600160a01b03163314610bbc5760405162461bcd60e51b8152600401610633906116df565b6001600160a01b0382166000908152600c602052604090205460ff16610d4d5769d3c21bcecceda10000008110610ccf57610bf78282611208565b604051632f0ad01760e21b8152600760048201526001600160a01b0383166024820152604481018290527359c628e832c27989b58bc1896a784436eb9e47749063bc2b405c9060640160006040518083038186803b158015610c5857600080fd5b505af4158015610c6c573d6000803e3d6000fd5b5050506001600160a01b0383166000908152600d60205260408120549150819003610caf5750506001600160a01b03166000908152600d60205260409020429055565b610cb8816114b7565b15610cca57610cc8836000610a4e565b505b505050565b610cda826000611208565b60405163131836e760e21b8152600760048201526001600160a01b03831660248201527359c628e832c27989b58bc1896a784436eb9e477490634c60db9c9060440160006040518083038186803b158015610d3457600080fd5b505af4158015610d48573d6000803e3d6000fd5b505050505b5050565b6000546001600160a01b03163314610d7b5760405162461bcd60e51b8152600401610633906116df565b600e5460405182907f474ea64804364a1e29a4487ddb63c3342a2dd826ccd8acf48825e680a0e6f20f90600090a3600e55565b6000546001600160a01b03163314610dd85760405162461bcd60e51b8152600401610633906116df565b6001600160a01b038116610e3d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610633565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040516317e142d160e01b8152600760048201526001600160a01b038216602482015281906000908190819081908190819081907359c628e832c27989b58bc1896a784436eb9e4774906317e142d190604401602060405180830381865af4158015610f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2c9190611714565b9650600019955060008712610f8e57600b54871115610f5a57600b54610f539088906114de565b9550610f8e565b600b5460075460009110610f6f576000610f7e565b600b54600754610f7e916112a1565b9050610f8a88826111b7565b9650505b610f978861096f565b9450610fa28861063c565b6001600160a01b0389166000908152600d6020526040902054909450925082610fcc576000610fda565b600e54610fda9084906112e3565b9150428211610fea576000610ff4565b610ff482426112a1565b9050919395975091939597565b60075460009081908190808203611023575050600b5460009250829150611117565b600b546000805a90506000805b898410801561103e57508582105b15611106578461104d8161174a565b6007549096508610905061106057600094505b60006007600001868154811061107857611078611763565b60009182526020808320909101546001600160a01b0316808352600d9091526040909120549091506110a9906114b7565b156110cc576110b9816001610a4e565b156110cc57816110c88161174a565b9250505b826110d68161174a565b93505060005a9050808511156110fd576110fa6110f386836112a1565b87906112e3565b95505b93506110309050565b600b85905590975095509193505050505b9193909250565b60008260000361113057506000610699565b600061113c8385611779565b90508261114985836116bd565b146111a05760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608401610633565b9392505050565b6000818181121561069957600080fd5b6000806111c48385611790565b9050600083121580156111d75750838112155b806111ec57506000831280156111ec57508381125b6111a057600080fd5b60008082121561120457600080fd5b5090565b6001600160a01b03821660009081526004602052604090208054908290558082111561126457600061123a83836112a1565b9050611246848261151b565b806005600082825461125891906117b8565b90915550610cca915050565b80821015610cca57600061127882846112a1565b90506112848482611575565b806005600082825461129691906117cb565b909155505050505050565b60006111a083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115af565b6000806112f083856117b8565b9050838110156111a05760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610633565b60008061134e8361096f565b905080156114ae576001600160a01b03831660009081526003602052604090205461137990826112e3565b6001600160a01b038416600081815260036020526040908190209290925590517fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d906113c89084815260200190565b60405180910390a260405163a9059cbb60e01b81526001600160a01b03841660048201526024810182905260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063a9059cbb906044016020604051808303816000875af1158015611434573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145891906117de565b9050806114a7576001600160a01b03841660009081526003602052604090205461148290836112a1565b6001600160a01b03909416600090815260036020526040812094909455509192915050565b5092915050565b50600092915050565b6000428211156114c957506000919050565b600e546114d642846112a1565b101592915050565b6000806114eb83856117fb565b9050600083121580156114fe5750838113155b806111ec57506000831280156111ec57508381136111a057600080fd5b61155561153661067f8360015461111e90919063ffffffff16565b6001600160a01b038416600090815260026020526040902054906114de565b6001600160a01b0390921660009081526002602052604090209190915550565b61155561159061067f8360015461111e90919063ffffffff16565b6001600160a01b038416600090815260026020526040902054906111b7565b600081848411156115d35760405162461bcd60e51b8152600401610633919061181b565b5060006115e084866117cb565b95945050505050565b6001600160a01b0381168114610a4b57600080fd5b60006020828403121561161057600080fd5b81356111a0816115e9565b60006020828403121561162d57600080fd5b5035919050565b8015158114610a4b57600080fd5b6000806040838503121561165557600080fd5b8235611660816115e9565b9150602083013561167081611634565b809150509250929050565b6000806040838503121561168e57600080fd5b8235611699816115e9565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000826116da57634e487b7160e01b600052601260045260246000fd5b500490565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60006020828403121561172657600080fd5b5051919050565b60006020828403121561173f57600080fd5b81516111a0816115e9565b60006001820161175c5761175c6116a7565b5060010190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610699576106996116a7565b80820182811260008312801582168215821617156117b0576117b06116a7565b505092915050565b80820180821115610699576106996116a7565b81810381811115610699576106996116a7565b6000602082840312156117f057600080fd5b81516111a081611634565b81810360008312801583831316838312821617156114a7576114a76116a7565b600060208083528351808285015260005b818110156118485785810183015185820160400152820161182c565b506000604082860101526040601f19601f830116850101925050509291505056fea2646970667358221220cce1a30de589331ce4a1dd18ce33c97d5218fe1a20af752a0db6db68479dbe8964736f6c63430008130033

Deployed Bytecode

0x6080604052600436106102605760003560e01c80637fa787ba11610144578063c0f306ef116100b6578063e2f456051161007a578063e2f45605146107cf578063e7841ec0146107e5578063e98030c7146107fa578063f27fd2541461081a578063f2fde38b1461083a578063fe4b84df1461085a57600080fd5b8063c0f306ef146106cd578063c15025c6146106ed578063c9567bf91461075f578063dd62ed3e14610774578063df7787a4146107ba57600080fd5b8063a26579ad11610108578063a26579ad146105d3578063a457c2d7146105e8578063a8b9d24014610608578063a9059cbb14610628578063ad56c13c14610648578063c04a5414146106ad57600080fd5b80637fa787ba1461054357806382bfefc8146105585780638da5cb5b1461058057806395d89b411461059e5780639a0025be146105b357600080fd5b806339509351116101dd5780636ba631cf116101a15780636ba631cf1461046f578063700bb191146104a357806370a08231146104c3578063715018a6146104f957806371778e7d1461050e57806372ac24861461052357600080fd5b806339509351146103e55780634e71d92d1461040557806364b0f6531461041a5780636843cd841461042f5780636966b8061461044f57600080fd5b80631d5492d9116102245780631d5492d91461032857806323b872dd1461037457806330bb4cff14610394578063313ce567146103a957806331e79db0146103c557600080fd5b806306fdde031461026c578063095ea7b3146102975780630b78f9c0146102c75780630ce5fd36146102e957806318160ddd1461030957600080fd5b3661026757005b600080fd5b34801561027857600080fd5b5061028161087a565b60405161028e9190612c77565b60405180910390f35b3480156102a357600080fd5b506102b76102b2366004612cda565b61090c565b604051901515815260200161028e565b3480156102d357600080fd5b506102e76102e2366004612d06565b610923565b005b3480156102f557600080fd5b506102e7610304366004612d28565b6109a8565b34801561031557600080fd5b506002545b60405190815260200161028e565b34801561033457600080fd5b5061035c7f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d1781565b6040516001600160a01b03909116815260200161028e565b34801561038057600080fd5b506102b761038f366004612d41565b610a13565b3480156103a057600080fd5b5061031a610a7c565b3480156103b557600080fd5b506040516012815260200161028e565b3480156103d157600080fd5b506102e76103e0366004612d82565b610b05565b3480156103f157600080fd5b506102b7610400366004612cda565b610be1565b34801561041157600080fd5b506102e7610c17565b34801561042657600080fd5b5061031a610d52565b34801561043b57600080fd5b5061031a61044a366004612d82565b610db2565b34801561045b57600080fd5b506102e761046a366004612dbb565b610e42565b34801561047b57600080fd5b5061035c7f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a92681565b3480156104af57600080fd5b506102e76104be366004612d28565b610fbb565b3480156104cf57600080fd5b5061031a6104de366004612d82565b6001600160a01b031660009081526020819052604090205490565b34801561050557600080fd5b506102e76110ac565b34801561051a57600080fd5b5061031a611120565b34801561052f57600080fd5b506102e761053e366004612d82565b611180565b34801561054f57600080fd5b506102e76111e7565b34801561056457600080fd5b5061035c73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561058c57600080fd5b506005546001600160a01b031661035c565b3480156105aa57600080fd5b506102816112b7565b3480156105bf57600080fd5b506102e76105ce366004612dee565b6112c6565b3480156105df57600080fd5b5061031a6113e8565b3480156105f457600080fd5b506102b7610603366004612cda565b611448565b34801561061457600080fd5b5061031a610623366004612d82565b611497565b34801561063457600080fd5b506102b7610643366004612cda565b6114ea565b34801561065457600080fd5b50610668610663366004612d82565b6114f7565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161028e565b3480156106b957600080fd5b5060075461035c906001600160a01b031681565b3480156106d957600080fd5b506102e76106e8366004612d82565b6115bb565b3480156106f957600080fd5b50600a5461072c906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b039586168152938516602085015291841691830191909152909116606082015260800161028e565b34801561076b57600080fd5b506102e7611697565b34801561078057600080fd5b5061031a61078f366004612e09565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3480156107c657600080fd5b5061031a6116e2565b3480156107db57600080fd5b5061031a60065481565b3480156107f157600080fd5b5061031a611708565b34801561080657600080fd5b506102e7610815366004612d28565b611768565b34801561082657600080fd5b50610668610835366004612d28565b611934565b34801561084657600080fd5b506102e7610855366004612d82565b61198e565b34801561086657600080fd5b506102e7610875366004612d28565b611a79565b60606003805461088990612e42565b80601f01602080910402602001604051908101604052809291908181526020018280546108b590612e42565b80156109025780601f106108d757610100808354040283529160200191610902565b820191906000526020600020905b8154815290600101906020018083116108e557829003601f168201915b5050505050905090565b6000610919338484611abd565b5060015b92915050565b6005546001600160a01b031633146109565760405162461bcd60e51b815260040161094d90612e7c565b60405180910390fd5b600882905560098190558115801561097e5750600a54600160c01b90046001600160401b0316155b156109a457600a80546001600160c01b0316600160c01b426001600160401b0316021790555b5050565b336001600160a01b037f0000000000000000000000004b0194472a4e5fb07408ce4e4903e5985426263316146109dd57600080fd5b600081116109ea57600080fd5b6103e8610a036b033b2e3c9fd0803ce800000083612ec7565b610a0d9190612ef4565b60065550565b6000610a20848484611be2565b610a728433610a6d856040518060600160405280602881526020016131a1602891396001600160a01b038a16600090815260016020908152604080832033845290915290205491906121b4565b611abd565b5060019392505050565b60007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03166385a6b3ae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b009190612f08565b905090565b6005546001600160a01b03163314610b2f5760405162461bcd60e51b815260040161094d90612e7c565b60405163031e79db60e41b81526001600160a01b0382811660048301527f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d1716906331e79db090602401600060405180830381600087803b158015610b9257600080fd5b505af1158015610ba6573d6000803e3d6000fd5b50506040516001600160a01b03841692507fa878b31040b2e6d0a9a3d3361209db3908ba62014b0dca52adbaee451d128b259150600090a250565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610919918590610a6d90866121ee565b60405163226cfa3d60e01b81523360048201526000907f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03169063226cfa3d90602401602060405180830381865afa158015610c7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca29190612f08565b9050610cac6113e8565b610cb64283612254565b1015610cc157600080fd5b60405163bc4c4b3760e01b8152336004820152600060248201527f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03169063bc4c4b37906044016020604051808303816000875af1158015610d2e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190612f21565b60007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03166309bbedde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b60405163156dbbf560e31b81526001600160a01b0382811660048301526000917f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d179091169063ab6ddfa8906024015b602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091d9190612f08565b336001600160a01b037f0000000000000000000000004b0194472a4e5fb07408ce4e4903e598542626331614610e7757600080fd5b610258826001600160401b03161015610eea5760405162461bcd60e51b815260206004820152602f60248201527f52657761726420706f6f6c206c657373206672657175656e74207468616e206560448201526e76657279203130206d696e7574657360881b606482015260840161094d565b6103e8816001600160401b031611158015610f03575060015b610f625760405162461bcd60e51b815260206004820152602a60248201527f52657761726420706f6f6c2070657263656e74206e6f74206265747765656e20604482015269302520616e642031302560b01b606482015260840161094d565b600a805477ffffffffffffffffffffffffffffffff00000000000000001916600160801b6001600160401b03948516026fffffffffffffffff0000000000000000191617600160401b9290931691909102919091179055565b60008060007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663ffb2c479856040518263ffffffff1660e01b815260040161100e91815260200190565b6060604051808303816000875af115801561102d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110519190612f43565b604080518481526020810184905290810182905260608101889052929550909350915032906000907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a350505050565b6005546001600160a01b031633146110d65760405162461bcd60e51b815260040161094d90612e7c565b6005546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580546001600160a01b0319169055565b60007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663ad7a672f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b6005546001600160a01b031633146111aa5760405162461bcd60e51b815260040161094d90612e7c565b6007546001600160a01b03908116908216036111c557600080fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b336001600160a01b037f0000000000000000000000004b0194472a4e5fb07408ce4e4903e59854262633161461121c57600080fd5b604051600090339047908381818185875af1925050503d806000811461125e576040519150601f19603f3d011682016040523d82523d6000602084013e611263565b606091505b50509050806112b45760405162461bcd60e51b815260206004820152601c60248201527f4661696c656420746f20776974686472617720737475636b2065746800000000604482015260640161094d565b50565b60606004805461088990612e42565b336001600160a01b037f0000000000000000000000004b0194472a4e5fb07408ce4e4903e5985426263316146112fb57600080fd5b61c350816001600160401b031610158015611322575062030d40816001600160401b031611155b61138a5760405162461bcd60e51b815260206004820152603360248201527f676173466f7250726f63657373696e67206d757374206265206265747765656e60448201527202035302c30303020616e64203230302c30303606c1b606482015260840161094d565b600a546040516001600160401b03918216918316907f40d7e40e79af4e8e5a9b3c57030d8ea93f13d669c06d448c4d631d4ae7d23db790600090a3600a805467ffffffffffffffff19166001600160401b0392909216919091179055565b60007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b0316636f2789ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b60006109193384610a6d856040518060600160405280602581526020016131c9602591393360009081526001602090815260408083206001600160a01b038d16845290915290205491906121b4565b6040516302a2e74960e61b81526001600160a01b0382811660048301526000917f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d179091169063a8b9d24090602401610e01565b6000610919338484611be2565b6000806000806000806000807f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663fbcbc0f18a6040518263ffffffff1660e01b815260040161155e91906001600160a01b0391909116815260200190565b61010060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190612f71565b97509750975097509750975097509750919395975091939597565b6005546001600160a01b031633146115e55760405162461bcd60e51b815260040161094d90612e7c565b60405163c0f306ef60e01b81526001600160a01b0382811660048301527f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d17169063c0f306ef90602401600060405180830381600087803b15801561164857600080fd5b505af115801561165c573d6000803e3d6000fd5b50506040516001600160a01b03841692507f40a78dcf8526b72f2eaf598af1c7e49c8d5fc577f6c8f1bed887f3e4dfa289329150600090a250565b6005546001600160a01b031633146116c15760405162461bcd60e51b815260040161094d90612e7c565b6000600c54116116d3576116d3612fdb565b600d805460ff19166001179055565b60646116fb6b033b2e3c9fd0803ce80000006002612ec7565b6117059190612ef4565b81565b60007f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663e7841ec06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b336001600160a01b037f0000000000000000000000004b0194472a4e5fb07408ce4e4903e59854262633161461179d57600080fd5b61038481101580156117b25750620151808111155b61183b5760405162461bcd60e51b815260206004820152604e60248201527f4469766964656e645f547261636b65723a20636c61696d57616974206d75737460448201527f206265207570646174656420746f206265747765656e203135206d696e75746560648201526d7320616e6420323420686f75727360901b608482015260a40161094d565b6118436113e8565b81036118b75760405162461bcd60e51b815260206004820152603760248201527f4469766964656e645f547261636b65723a2043616e6e6f74207570646174652060448201527f636c61696d5761697420746f2073616d652076616c7565000000000000000000606482015260840161094d565b60405163e98030c760e01b8152600481018290527f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03169063e98030c790602401600060405180830381600087803b15801561191957600080fd5b505af115801561192d573d6000803e3d6000fd5b5050505050565b6000806000806000806000807f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b0316635183d6fd8a6040518263ffffffff1660e01b815260040161155e91815260200190565b6005546001600160a01b031633146119b85760405162461bcd60e51b815260040161094d90612e7c565b6001600160a01b038116611a1d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161094d565b6005546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005546001600160a01b03163314611aa35760405162461bcd60e51b815260040161094d90612e7c565b80600c6000828254611ab59190612ff1565b909155505050565b6001600160a01b038316611b1f5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161094d565b6001600160a01b038216611b805760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161094d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600d54839060ff1680611c0257506005546001600160a01b038281169116145b80611c3e57507f0000000000000000000000004b0194472a4e5fb07408ce4e4903e598542626336001600160a01b0316816001600160a01b0316145b611c4757600080fd5b6001600160a01b038416611c6d5760405162461bcd60e51b815260040161094d90613004565b6001600160a01b038316611c935760405162461bcd60e51b815260040161094d90613049565b81600003611cac57611ca784846000612296565b6121ae565b6001600160a01b038416301480611cf457507f0000000000000000000000004b0194472a4e5fb07408ce4e4903e598542626336001600160a01b0316836001600160a01b0316145b15611d0457611ca7848484612296565b6001600160a01b03838116600081815260208190526040902054917f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9261614611dc1576064611d5f6b033b2e3c9fd0803ce80000006002612ec7565b611d699190612ef4565b611d738483612ff1565b1115611dc15760405162461bcd60e51b815260206004820152601e60248201527f457863656564696e6720746865206d61782077616c6c6574206c696d69740000604482015260640161094d565b6008543060009081526020819052604081205491159190611de2888361239f565b90508015611e0b57600b805460ff19166001179055611e0083612401565b600b805460ff191690555b828015611e16575080155b8015611e5357507f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b0316876001600160a01b0316145b8015611e8d5750600a54611e80906001600160401b03600160801b8204811691600160c01b90041661308c565b6001600160401b03164210155b15611e9a57611e9a6126a3565b82611edc576000606487611ead8b6128e7565b611eb79190612ec7565b611ec19190612ef4565b9050611ece893083612296565b611ed881886130b3565b9650505b611ee7888888612296565b7f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663e30443bc89611f368b6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015611f7c57600080fd5b505af1925050508015611f8d575060015b507f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b031663e30443bc88611fdd8a6001600160a01b031660009081526020819052604090205490565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561202357600080fd5b505af1925050508015612034575060015b5060007f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b0316896001600160a01b031614801561209f575069d3c21bcecceda10000008510801561209f575069d3c21bcecceda100000061209c8887612ff1565b10155b9050811580156120ac5750835b80156120b6575080155b156121a857600a546040516001624d3b8760e01b031981526001600160401b0390911660048201819052907f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03169063ffb2c479906024016060604051808303816000875af1925050508015612150575060408051601f3d908101601f1916820190925261214d91810190612f43565b60015b156121a65760408051848152602081018490529081018290526060810185905232906001907fc864333d6121033635ab41b29ae52f10a22cf4438c3e4f1c4c68518feb2f8a989060800160405180910390a35050505b505b50505050505b50505050565b600081848411156121d85760405162461bcd60e51b815260040161094d9190612c77565b5060006121e584866130b3565b95945050505050565b6000806121fb8385612ff1565b90508381101561224d5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640161094d565b9392505050565b600061224d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506121b4565b6001600160a01b0383166122bc5760405162461bcd60e51b815260040161094d90613004565b6001600160a01b0382166122e25760405162461bcd60e51b815260040161094d90613049565b61231f8160405180606001604052806026815260200161317b602691396001600160a01b03861660009081526020819052604090205491906121b4565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461234e90826121ee565b6001600160a01b038381166000818152602081815260409182902094909455518481529092918616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101611bd5565b600060065482101580156123e557507f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b0316836001600160a01b031614155b801561224d57506007546001600160a01b031615159392505050565b3060009081526020819052604090205460065461241f906005612ec7565b81111561243757600654612434906005612ec7565b90505b811561263e576040516370a0823160e01b81526001600160a01b037f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d1716600482015260009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa1580156124b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124dc9190612f08565b90506124e982600061293f565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d17166004820152819073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a0823190602401602060405180830381865afa158015612563573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125879190612f08565b61259191906130b3565b60405163b0c7ce3760e01b8152600481018290529091507f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d176001600160a01b03169063b0c7ce3790602401600060405180830381600087803b1580156125f657600080fd5b505af115801561260a573d6000803e3d6000fd5b50506040518392507fb0cc2628d6d644cf6be9d8110e142297ac910d6d8026d795a99f272fd9ad60b19150600090a2505050565b61264981600161293f565b6007546040516000916001600160a01b03169047908381818185875af1925050503d8060008114612696576040519150601f19603f3d011682016040523d82523d6000602084013e61269b565b606091505b505050505050565b600a546000906001600160401b03600160801b82048116916126ce91600160c01b90910416426130b3565b6126d89190612ef4565b600a549091506001600160401b03600160801b820481169161270391600160c01b90910416426130b3565b61270d91906130c6565b61271790426130b3565b600a80546001600160401b0392909216600160c01b026001600160c01b039092169190911790556040516370a0823160e01b81527f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b0316600482015260009030906370a0823190602401602060405180830381865afa1580156127a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c99190612f08565b9050600060058311156127db57600592505b60005b8381101561284357600a54600090612815906127109061280f908790600160401b90046001600160401b0316612b8a565b90612c0c565b905061282181856130b3565b935061282d8184612ff1565b925050808061283b906130da565b9150506127de565b5061286f7f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9263083612296565b7f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156128ca57600080fd5b505af11580156128de573d6000803e3d6000fd5b50505050505050565b60007f000000000000000000000000f0b0a9dcbf0a90a3376ab628bfe38d0b3ed7a9266001600160a01b0316826001600160a01b031614612937576009546008546129329190612ff1565b61091d565b505060085490565b306000908152600160209081526040808320737a250d5630b4cf539739df2c5dacb4c659f2488d84529091529020548211156129a0576129a030737a250d5630b4cf539739df2c5dacb4c659f2488d6b033b2e3c9fd0803ce8000000611abd565b8015612a955760408051600280825260608201835260009260208301908036833701905050905030816000815181106129db576129db6130f3565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612a2357612a236130f3565b6001600160a01b039092166020928302919091019091015260405163791ac94760e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d9063791ac94790612a7b908690600090869030904290600401613109565b600060405180830381600087803b1580156128ca57600080fd5b6040805160028082526060820183526000926020830190803683370190505090503081600081518110612aca57612aca6130f3565b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110612b1257612b126130f3565b6001600160a01b0390921660209283029190910190910152604051635c11d79560e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d90635c11d79590612a7b90869060009086907f0000000000000000000000005d697f285b2c68b753cde1a0475ad86c856b4d17904290600401613109565b600082600003612b9c5750600061091d565b6000612ba88385612ec7565b905082612bb58583612ef4565b1461224d5760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b606482015260840161094d565b600061224d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612c6a5760405162461bcd60e51b815260040161094d9190612c77565b5060006121e58486612ef4565b600060208083528351808285015260005b81811015612ca457858101830151858201604001528201612c88565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b03811681146112b457600080fd5b60008060408385031215612ced57600080fd5b8235612cf881612cc5565b946020939093013593505050565b60008060408385031215612d1957600080fd5b50508035926020909101359150565b600060208284031215612d3a57600080fd5b5035919050565b600080600060608486031215612d5657600080fd5b8335612d6181612cc5565b92506020840135612d7181612cc5565b929592945050506040919091013590565b600060208284031215612d9457600080fd5b813561224d81612cc5565b80356001600160401b0381168114612db657600080fd5b919050565b60008060408385031215612dce57600080fd5b612dd783612d9f565b9150612de560208401612d9f565b90509250929050565b600060208284031215612e0057600080fd5b61224d82612d9f565b60008060408385031215612e1c57600080fd5b8235612e2781612cc5565b91506020830135612e3781612cc5565b809150509250929050565b600181811c90821680612e5657607f821691505b602082108103612e7657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761091d5761091d612eb1565b634e487b7160e01b600052601260045260246000fd5b600082612f0357612f03612ede565b500490565b600060208284031215612f1a57600080fd5b5051919050565b600060208284031215612f3357600080fd5b8151801515811461224d57600080fd5b600080600060608486031215612f5857600080fd5b8351925060208401519150604084015190509250925092565b600080600080600080600080610100898b031215612f8e57600080fd5b8851612f9981612cc5565b809850506020890151965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015190509295985092959890939650565b634e487b7160e01b600052600160045260246000fd5b8082018082111561091d5761091d612eb1565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6001600160401b038181168382160190808211156130ac576130ac612eb1565b5092915050565b8181038181111561091d5761091d612eb1565b6000826130d5576130d5612ede565b500690565b6000600182016130ec576130ec612eb1565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156131595784516001600160a01b031683529383019391830191600101613134565b50506001600160a01b0396909616606085015250505060800152939250505056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212201d4fbc0194cdcb6de37d9110a32dd1b3a21a925bd27ab9ec314d535b96a88a3064736f6c63430008130033

Libraries Used


Deployed Bytecode Sourcemap

33376:13785:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24772:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;26939:169;;;;;;;;;;-1:-1:-1;26939:169:0;;;;;:::i;:::-;;:::i;:::-;;;1188:14:1;;1181:22;1163:41;;1151:2;1136:18;26939:169:0;1023:187:1;42134:325:0;;;;;;;;;;-1:-1:-1;42134:325:0;;;;;:::i;:::-;;:::i;:::-;;42675:197;;;;;;;;;;-1:-1:-1;42675:197:0;;;;;:::i;:::-;;:::i;25892:108::-;;;;;;;;;;-1:-1:-1;25980:12:0;;25892:108;;;1799:25:1;;;1787:2;1772:18;25892:108:0;1653:177:1;33660:49:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2031:32:1;;;2013:51;;2001:2;1986:18;33660:49:0;1835:235:1;27590:355:0;;;;;;;;;;-1:-1:-1;27590:355:0;;;;;:::i;:::-;;:::i;45078:142::-;;;;;;;;;;;;;:::i;25734:93::-;;;;;;;;;;-1:-1:-1;25734:93:0;;25817:2;2678:36:1;;2666:2;2651:18;25734:93:0;2536:184:1;44382:176:0;;;;;;;;;;-1:-1:-1;44382:176:0;;;;;:::i;:::-;;:::i;28354:218::-;;;;;;;;;;-1:-1:-1;28354:218:0;;;;;:::i;:::-;;:::i;46484:254::-;;;;;;;;;;;;;:::i;46884:142::-;;;;;;;;;;;;;:::i;45388:144::-;;;;;;;;;;-1:-1:-1;45388:144:0;;;;;:::i;:::-;;:::i;42880:452::-;;;;;;;;;;-1:-1:-1;42880:452:0;;;;;:::i;:::-;;:::i;33718:37::-;;;;;;;;;;;;;;;46204:272;;;;;;;;;;-1:-1:-1;46204:272:0;;;;;:::i;:::-;;:::i;26063:127::-;;;;;;;;;;-1:-1:-1;26063:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;26164:18:0;26137:7;26164:18;;;;;;;;;;;;26063:127;20306:148;;;;;;;;;;;;;:::i;47038:120::-;;;;;;;;;;;;;:::i;44744:207::-;;;;;;;;;;-1:-1:-1;44744:207:0;;;;;:::i;:::-;;:::i;43340:233::-;;;;;;;;;;;;;:::i;34052:74::-;;;;;;;;;;;;34084:42;34052:74;;19664:79;;;;;;;;;;-1:-1:-1;19729:6:0;;-1:-1:-1;;;;;19729:6:0;19664:79;;24991:104;;;;;;;;;;;;;:::i;43581:367::-;;;;;;;;;;-1:-1:-1;43581:367:0;;;;;:::i;:::-;;:::i;44963:107::-;;;;;;;;;;;;;:::i;29075:269::-;;;;;;;;;;-1:-1:-1;29075:269:0;;;;;:::i;:::-;;:::i;45228:152::-;;;;;;;;;;-1:-1:-1;45228:152:0;;;;;:::i;:::-;;:::i;26403:175::-;;;;;;;;;;-1:-1:-1;26403:175:0;;;;;:::i;:::-;;:::i;45540:319::-;;;;;;;;;;-1:-1:-1;45540:319:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;4428:32:1;;;4410:51;;4492:2;4477:18;;4470:34;;;;4520:18;;;4513:34;;;;4578:2;4563:18;;4556:34;;;;4621:3;4606:19;;4599:35;4448:3;4650:19;;4643:35;4709:3;4694:19;;4687:35;4753:3;4738:19;;4731:35;4397:3;4382:19;45540:319:0;4071:701:1;34004:40:0;;;;;;;;;;-1:-1:-1;34004:40:0;;;;-1:-1:-1;;;;;34004:40:0;;;44566:170;;;;;;;;;;-1:-1:-1;44566:170:0;;;;;:::i;:::-;;:::i;34449:82::-;;;;;;;;;;-1:-1:-1;34449:82:0;;;;-1:-1:-1;;;;;34449:82:0;;;;-1:-1:-1;;;34449:82:0;;;;;-1:-1:-1;;;34449:82:0;;;;;-1:-1:-1;;;34449:82:0;;;;;;;;;-1:-1:-1;;;;;5279:15:1;;;5261:34;;5331:15;;;5326:2;5311:18;;5304:43;5383:15;;;5363:18;;;5356:43;;;;5435:15;;;5430:2;5415:18;;5408:43;5211:3;5196:19;34449:82:0;5001:456:1;42467:106:0;;;;;;;;;;;;;:::i;26641:151::-;;;;;;;;;;-1:-1:-1;26641:151:0;;;;;:::i;:::-;-1:-1:-1;;;;;26757:18:0;;;26730:7;26757:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;26641:151;33520:59;;;;;;;;;;;;;:::i;33587:::-;;;;;;;;;;;;;;;;46746:130;;;;;;;;;;;;;:::i;43956:418::-;;;;;;;;;;-1:-1:-1;43956:418:0;;;;;:::i;:::-;;:::i;45867:329::-;;;;;;;;;;-1:-1:-1;45867:329:0;;;;;:::i;:::-;;:::i;20609:244::-;;;;;;;;;;-1:-1:-1;20609:244:0;;;;;:::i;:::-;;:::i;42581:84::-;;;;;;;;;;-1:-1:-1;42581:84:0;;;;;:::i;:::-;;:::i;24772:100::-;24826:13;24859:5;24852:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24772:100;:::o;26939:169::-;27022:4;27039:39;292:10;27062:7;27071:6;27039:8;:39::i;:::-;-1:-1:-1;27096:4:0;26939:169;;;;;:::o;42134:325::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;;;;;;;;;42227:10:::1;:19:::0;;;42257:22:::1;:43:::0;;;42314:15;;:60;::::1;;;-1:-1:-1::0;42333:14:0::1;:36:::0;-1:-1:-1;;;42333:36:0;::::1;-1:-1:-1::0;;;;;42333:36:0::1;:41:::0;42314:60:::1;42311:140;;;42389:14;:62:::0;;-1:-1:-1;;;;;42389:62:0::1;-1:-1:-1::0;;;42435:15:0::1;-1:-1:-1::0;;;;;42389:62:0::1;;;::::0;;42311:140:::1;42134:325:::0;;:::o;42675:197::-;42747:10;-1:-1:-1;;;;;42761:8:0;42747:22;;42739:31;;;;;;42800:1;42789:8;:12;42781:21;;;;;;42860:4;42834:23;33493:20;42834:8;:23;:::i;:::-;:30;;;;:::i;:::-;42813:18;:51;-1:-1:-1;42675:197:0:o;27590:355::-;27730:4;27747:36;27757:6;27765:9;27776:6;27747:9;:36::i;:::-;27794:121;27803:6;292:10;27825:89;27863:6;27825:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;27825:19:0;;;;;;:11;:19;;;;;;;;292:10;27825:33;;;;;;;;;;:37;:89::i;:::-;27794:8;:121::i;:::-;-1:-1:-1;27933:4:0;27590:355;;;;;:::o;45078:142::-;45141:7;45168:16;-1:-1:-1;;;;;45168:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45161:51;;45078:142;:::o;44382:176::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;44459:46:::1;::::0;-1:-1:-1;;;44459:46:0;;-1:-1:-1;;;;;2031:32:1;;;44459:46:0::1;::::0;::::1;2013:51:1::0;44459:16:0::1;:37;::::0;::::1;::::0;1986:18:1;;44459:46:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;44521:29:0::1;::::0;-1:-1:-1;;;;;44521:29:0;::::1;::::0;-1:-1:-1;44521:29:0::1;::::0;-1:-1:-1;44521:29:0;;::::1;44382:176:::0;:::o;28354:218::-;292:10;28442:4;28491:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;28491:34:0;;;;;;;;;;28442:4;;28459:83;;28482:7;;28491:50;;28530:10;28491:38;:50::i;46484:254::-;46545:43;;-1:-1:-1;;;46545:43:0;;46577:10;46545:43;;;2013:51:1;46521:21:0;;46545:16;-1:-1:-1;;;;;46545:31:0;;;;1986:18:1;;46545:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46521:67;;46645:14;:12;:14::i;:::-;46607:34;:15;46627:13;46607:19;:34::i;:::-;:52;;46599:61;;;;;;46671:59;;-1:-1:-1;;;46671:59:0;;46711:10;46671:59;;;7536:51:1;46724:5:0;7603:18:1;;;7596:50;46671:16:0;-1:-1:-1;;;;;46671:31:0;;;;7509:18:1;;46671:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;46884:142::-;46949:7;46976:16;-1:-1:-1;;;;;46976:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45388:144;45485:39;;-1:-1:-1;;;45485:39:0;;-1:-1:-1;;;;;2031:32:1;;;45485:39:0;;;2013:51:1;45458:7:0;;45485:16;:30;;;;;;1986:18:1;;45485:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;42880:452::-;42984:10;-1:-1:-1;;;;;42998:8:0;42984:22;;42976:31;;;;;;43049:3;43026:19;-1:-1:-1;;;;;43026:26:0;;;43018:86;;;;-1:-1:-1;;;43018:86:0;;8141:2:1;43018:86:0;;;8123:21:1;8180:2;8160:18;;;8153:30;8219:34;8199:18;;;8192:62;-1:-1:-1;;;8270:18:1;;;8263:45;8325:19;;43018:86:0;7939:411:1;43018:86:0;43135:4;43123:8;-1:-1:-1;;;;;43123:16:0;;;:33;;;;-1:-1:-1;43143:13:0;43123:33;43115:88;;;;-1:-1:-1;;;43115:88:0;;8557:2:1;43115:88:0;;;8539:21:1;8596:2;8576:18;;;8569:30;8635:34;8615:18;;;8608:62;-1:-1:-1;;;8686:18:1;;;8679:40;8736:19;;43115:88:0;8355:406:1;43115:88:0;43214:14;:56;;-1:-1:-1;;43281:43:0;-1:-1:-1;;;;;;;;43214:56:0;;;;-1:-1:-1;;43281:43:0;;-1:-1:-1;;;43281:43:0;;;;;;;;;;;;;;42880:452::o;46204:272::-;46270:18;46290:14;46306:26;46336:16;-1:-1:-1;;;;;46336:24:0;;46361:3;46336:29;;;;;;;;;;;;;1799:25:1;;1787:2;1772:18;;1653:177;46336:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46381:87;;;9308:25:1;;;9364:2;9349:18;;9342:34;;;9392:18;;;9385:34;;;9450:2;9435:18;;9428:34;;;46269:96:0;;-1:-1:-1;46269:96:0;;-1:-1:-1;46269:96:0;-1:-1:-1;46458:9:0;;46446:5;;46381:87;;9295:3:1;9280:19;46381:87:0;;;;;;;46258:218;;;46204:272;:::o;20306:148::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;20397:6:::1;::::0;20376:40:::1;::::0;20413:1:::1;::::0;-1:-1:-1;;;;;20397:6:0::1;::::0;20376:40:::1;::::0;20413:1;;20376:40:::1;20427:6;:19:::0;;-1:-1:-1;;;;;;20427:19:0::1;::::0;;20306:148::o;47038:120::-;47092:7;47119:16;-1:-1:-1;;;;;47119:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44744:207;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;44874:17:::1;::::0;-1:-1:-1;;;;;44874:17:0;;::::1;44850:41:::0;;::::1;::::0;44842:50:::1;;;::::0;::::1;;44903:17;:40:::0;;-1:-1:-1;;;;;;44903:40:0::1;-1:-1:-1::0;;;;;44903:40:0;;;::::1;::::0;;;::::1;::::0;;44744:207::o;43340:233::-;43396:10;-1:-1:-1;;;;;43410:8:0;43396:22;;43388:31;;;;;;43448:58;;43431:12;;43456:10;;43480:21;;43431:12;43448:58;43431:12;43448:58;43480:21;43456:10;43448:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43430:76;;;43525:7;43517:48;;;;-1:-1:-1;;;43517:48:0;;9885:2:1;43517:48:0;;;9867:21:1;9924:2;9904:18;;;9897:30;9963;9943:18;;;9936:58;10011:18;;43517:48:0;9683:352:1;43517:48:0;43377:196;43340:233::o;24991:104::-;25047:13;25080:7;25073:14;;;;;:::i;43581:367::-;43658:10;-1:-1:-1;;;;;43672:8:0;43658:22;;43650:31;;;;;;43712:6;43700:8;-1:-1:-1;;;;;43700:18:0;;;:41;;;;;43734:7;43722:8;-1:-1:-1;;;;;43722:19:0;;;43700:41;43692:105;;;;-1:-1:-1;;;43692:105:0;;10242:2:1;43692:105:0;;;10224:21:1;10281:2;10261:18;;;10254:30;10320:34;10300:18;;;10293:62;-1:-1:-1;;;10371:18:1;;;10364:49;10430:19;;43692:105:0;10040:415:1;43692:105:0;43855:14;:31;43821:66;;-1:-1:-1;;;;;43855:31:0;;;;43821:66;;;;;43855:31;;43821:66;43898:14;:42;;-1:-1:-1;;43898:42:0;-1:-1:-1;;;;;43898:42:0;;;;;;;;;;43581:367::o;44963:107::-;45007:7;45034:16;-1:-1:-1;;;;;45034:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29075:269;29168:4;29185:129;292:10;29208:7;29217:96;29256:15;29217:96;;;;;;;;;;;;;;;;;292:10;29217:25;;;;:11;:25;;;;;;;;-1:-1:-1;;;;;29217:34:0;;;;;;;;;;;;:38;:96::i;45228:152::-;45324:48;;-1:-1:-1;;;45324:48:0;;-1:-1:-1;;;;;2031:32:1;;;45324:48:0;;;2013:51:1;45297:7:0;;45324:16;:39;;;;;;1986:18:1;;45324:48:0;1835:235:1;26403:175:0;26489:4;26506:42;292:10;26530:9;26541:6;26506:9;:42::i;45540:319::-;45636:7;45658:6;45679;45700:7;45722;45744;45766;45788;45815:16;-1:-1:-1;;;;;45815:27:0;;45843:7;45815:36;;;;;;;;;;;;;;-1:-1:-1;;;;;2031:32:1;;;;2013:51;;2001:2;1986:18;;1835:235;45815:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45808:43;;;;;;;;;;;;;;;;45540:319;;;;;;;;;:::o;44566:170::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;44641:44:::1;::::0;-1:-1:-1;;;44641:44:0;;-1:-1:-1;;;;;2031:32:1;;;44641:44:0::1;::::0;::::1;2013:51:1::0;44641:16:0::1;:35;::::0;::::1;::::0;1986:18:1;;44641:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;44701:27:0::1;::::0;-1:-1:-1;;;;;44701:27:0;::::1;::::0;-1:-1:-1;44701:27:0::1;::::0;-1:-1:-1;44701:27:0;;::::1;44566:170:::0;:::o;42467:106::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;42534:1:::1;42527:4;;:8;42520:16;;;;:::i;:::-;42547:11;:18:::0;;-1:-1:-1;;42547:18:0::1;42561:4;42547:18;::::0;;42467:106::o;33520:59::-;33576:3;33557:16;33493:20;33572:1;33557:16;:::i;:::-;:22;;;;:::i;:::-;33520:59;:::o;46746:130::-;46801:7;46828:16;-1:-1:-1;;;;;46828:38:0;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43956:418;44031:10;-1:-1:-1;;;;;44045:8:0;44031:22;;44023:31;;;;;;44089:3;44073:12;:19;;:44;;;;;44112:5;44096:12;:21;;44073:44;44065:135;;;;-1:-1:-1;;;44065:135:0;;11480:2:1;44065:135:0;;;11462:21:1;11519:2;11499:18;;;11492:30;11558:34;11538:18;;;11531:62;11629:34;11609:18;;;11602:62;-1:-1:-1;;;11680:19:1;;;11673:45;11735:19;;44065:135:0;11278:482:1;44065:135:0;44235:14;:12;:14::i;:::-;44219:12;:30;44211:98;;;;-1:-1:-1;;;44211:98:0;;11967:2:1;44211:98:0;;;11949:21:1;12006:2;11986:18;;;11979:30;12045:34;12025:18;;;12018:62;12116:25;12096:18;;;12089:53;12159:19;;44211:98:0;11765:419:1;44211:98:0;44320:46;;-1:-1:-1;;;44320:46:0;;;;;1799:25:1;;;44320:16:0;-1:-1:-1;;;;;44320:32:0;;;;1772:18:1;;44320:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43956:418;:::o;45867:329::-;45968:7;45990:6;46011;46032:7;46054;46076;46098;46120;46147:16;-1:-1:-1;;;;;46147:34:0;;46182:5;46147:41;;;;;;;;;;;;;1799:25:1;;1787:2;1772:18;;1653:177;20609:244:0;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;20698:22:0;::::1;20690:73;;;::::0;-1:-1:-1;;;20690:73:0;;12391:2:1;20690:73:0::1;::::0;::::1;12373:21:1::0;12430:2;12410:18;;;12403:30;12469:34;12449:18;;;12442:62;-1:-1:-1;;;12520:18:1;;;12513:36;12566:19;;20690:73:0::1;12189:402:1::0;20690:73:0::1;20800:6;::::0;20779:38:::1;::::0;-1:-1:-1;;;;;20779:38:0;;::::1;::::0;20800:6:::1;::::0;20779:38:::1;::::0;20800:6:::1;::::0;20779:38:::1;20828:6;:17:::0;;-1:-1:-1;;;;;;20828:17:0::1;-1:-1:-1::0;;;;;20828:17:0;;;::::1;::::0;;;::::1;::::0;;20609:244::o;42581:84::-;19876:6;;-1:-1:-1;;;;;19876:6:0;292:10;19876:22;19868:67;;;;-1:-1:-1;;;19868:67:0;;;;;;;:::i;:::-;42652:5:::1;42646:4;;:11;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;42581:84:0:o;32261:380::-;-1:-1:-1;;;;;32397:19:0;;32389:68;;;;-1:-1:-1;;;32389:68:0;;12928:2:1;32389:68:0;;;12910:21:1;12967:2;12947:18;;;12940:30;13006:34;12986:18;;;12979:62;-1:-1:-1;;;13057:18:1;;;13050:34;13101:19;;32389:68:0;12726:400:1;32389:68:0;-1:-1:-1;;;;;32476:21:0;;32468:68;;;;-1:-1:-1;;;32468:68:0;;13333:2:1;32468:68:0;;;13315:21:1;13372:2;13352:18;;;13345:30;13411:34;13391:18;;;13384:62;-1:-1:-1;;;13462:18:1;;;13455:32;13504:19;;32468:68:0;13131:398:1;32468:68:0;-1:-1:-1;;;;;32549:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;32601:32;;1799:25:1;;;32601:32:0;;1772:18:1;32601:32:0;;;;;;;;32261:380;;;:::o;36443:2265::-;36364:11;;36569:4;;36364:11;;;:30;;-1:-1:-1;19729:6:0;;-1:-1:-1;;;;;36379:15:0;;;19729:6;;36379:15;36364:30;:50;;;;36406:8;-1:-1:-1;;;;;36398:16:0;:4;-1:-1:-1;;;;;36398:16:0;;36364:50;36356:59;;;;;;-1:-1:-1;;;;;36594:18:0;::::1;36586:68;;;;-1:-1:-1::0;;;36586:68:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;36673:16:0;::::1;36665:64;;;;-1:-1:-1::0;;;36665:64:0::1;;;;;;;:::i;:::-;36743:6;36753:1;36743:11:::0;36740:203:::1;;36778:28;36794:4;36800:2;36804:1;36778:15;:28::i;:::-;36771:35;;36740:203;-1:-1:-1::0;;;;;36836:21:0;::::1;36852:4;36836:21;::::0;:39:::1;;;36867:8;-1:-1:-1::0;;;;;36861:14:0::1;:2;-1:-1:-1::0;;;;;36861:14:0::1;;36836:39;36833:110;;;36898:33;36914:4;36920:2;36924:6;36898:15;:33::i;36833:110::-;-1:-1:-1::0;;;;;26164:18:0;;;36955:26:::1;26164:18:::0;;;;;;;;;;;;37018:12:::1;37012:18;;37008:135;;33576:3;33557:16;33493:20;33572:1;33557:16;:::i;:::-;:22;;;;:::i;:::-;37055:27;37076:6:::0;37055:18;:27:::1;:::i;:::-;:41;;37047:84;;;::::0;-1:-1:-1;;;37047:84:0;;14546:2:1;37047:84:0::1;::::0;::::1;14528:21:1::0;14585:2;14565:18;;;14558:30;14624:32;14604:18;;;14597:60;14674:18;;37047:84:0::1;14344:354:1::0;37047:84:0::1;37176:10;::::0;37253:4:::1;37155:18;26164::::0;;;;;;;;;;;37176:15;;;26164:18;37288:42:::1;37303:4:::0;26164:18;37288:14:::1;:42::i;:::-;37270:60;;37344:10;37341:126;;;37371:8;:15:::0;;-1:-1:-1;;37371:15:0::1;37382:4;37371:15;::::0;;37401:23:::1;37410:13:::0;37401:8:::1;:23::i;:::-;37439:8;:16:::0;;-1:-1:-1;;37439:16:0::1;::::0;;37341:126:::1;37490:13;:28;;;;;37508:10;37507:11;37490:28;:50;;;;;37528:12;-1:-1:-1::0;;;;;37522:18:0::1;:2;-1:-1:-1::0;;;;;37522:18:0::1;;37490:50;:160;;;;-1:-1:-1::0;37616:14:0::1;:34:::0;37577:73:::1;::::0;-1:-1:-1;;;;;;;;37616:34:0;::::1;::::0;::::1;::::0;-1:-1:-1;;;37577:36:0;::::1;;:73;:::i;:::-;-1:-1:-1::0;;;;;37558:92:0::1;:15;:92;;37490:160;37487:215;;;37666:12;:10;:12::i;:::-;37718:13;37714:193;;37747:17;37792:3;37783:6;37767:13;37775:4;37767:7;:13::i;:::-;:22;;;;:::i;:::-;:28;;;;:::i;:::-;37747:48;;37810:47;37826:4;37840;37847:9;37810:15;:47::i;:::-;37876:19;37886:9:::0;37876:19;::::1;:::i;:::-;;;37732:175;37714:193;37919:33;37935:4;37941:2;37945:6;37919:15;:33::i;:::-;37969:16;-1:-1:-1::0;;;;;37969:27:0::1;;38005:4;38012:15;38022:4;-1:-1:-1::0;;;;;26164:18:0;26137:7;26164:18;;;;;;;;;;;;26063:127;38012:15:::1;37969:59;::::0;-1:-1:-1;;;;;;37969:59:0::1;::::0;;;;;;-1:-1:-1;;;;;15229:32:1;;;37969:59:0::1;::::0;::::1;15211:51:1::0;15278:18;;;15271:34;15184:18;;37969:59:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;37965:75:::0;38054:16:::1;-1:-1:-1::0;;;;;38054:27:0::1;;38090:2;38095:13;38105:2;-1:-1:-1::0;;;;;26164:18:0;26137:7;26164:18;;;;;;;;;;;;26063:127;38095:13:::1;38054:55;::::0;-1:-1:-1;;;;;;38054:55:0::1;::::0;;;;;;-1:-1:-1;;;;;15229:32:1;;;38054:55:0::1;::::0;::::1;15211:51:1::0;15278:18;;;15271:34;15184:18;;38054:55:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;38050:71:::0;38133:24:::1;38168:12;-1:-1:-1::0;;;;;38160:20:0::1;:4;-1:-1:-1::0;;;;;38160:20:0::1;;:132;;;;;34582:20;38185:18;:45;:106;;;;-1:-1:-1::0;34582:20:0::1;38235:27;38256:6:::0;38235:18;:27:::1;:::i;:::-;:55;;38185:106;38133:159;;38307:10;38306:11;:28;;;;;38321:13;38306:28;:52;;;;;38339:19;38338:20;38306:52;38303:398;;;38389:14;:31:::0;38439:29:::1;::::0;-1:-1:-1;;;;;;38439:29:0;;-1:-1:-1;;;;;38389:31:0;;::::1;38439:29;::::0;::::1;1799:25:1::0;;;38389:31:0;38439:16:::1;-1:-1:-1::0;;;;;38439:24:0::1;::::0;::::1;::::0;1772:18:1;;38439:29:0::1;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;38439:29:0::1;::::0;;::::1;;::::0;;::::1;-1:-1:-1::0;;38439:29:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;;;38435:255:::0;::::1;;38566:86;::::0;;9308:25:1;;;9364:2;9349:18;;9342:34;;;9392:18;;;9385:34;;;9450:2;9435:18;;9428:34;;;38642:9:0::1;::::0;38631:4:::1;::::0;38566:86:::1;::::0;9295:3:1;9280:19;38566:86:0::1;;;;;;;38469:199;;;38435:255;38360:341;38303:398;36575:2133;;;;;36426:1;36443:2265:::0;;;;:::o;13653:192::-;13739:7;13775:12;13767:6;;;;13759:29;;;;-1:-1:-1;;;13759:29:0;;;;;;;;:::i;:::-;-1:-1:-1;13799:9:0;13811:5;13815:1;13811;:5;:::i;:::-;13799:17;13653:192;-1:-1:-1;;;;;13653:192:0:o;12750:181::-;12808:7;;12840:5;12844:1;12840;:5;:::i;:::-;12828:17;;12869:1;12864;:6;;12856:46;;;;-1:-1:-1;;;12856:46:0;;15518:2:1;12856:46:0;;;15500:21:1;15557:2;15537:18;;;15530:30;15596:29;15576:18;;;15569:57;15643:18;;12856:46:0;15316:351:1;12856:46:0;12922:1;12750:181;-1:-1:-1;;;12750:181:0:o;13214:136::-;13272:7;13299:43;13303:1;13306;13299:43;;;;;;;;;;;;;;;;;:3;:43::i;29834:573::-;-1:-1:-1;;;;;29974:20:0;;29966:70;;;;-1:-1:-1;;;29966:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;30055:23:0;;30047:71;;;;-1:-1:-1;;;30047:71:0;;;;;;;:::i;:::-;30211;30233:6;30211:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30211:17:0;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;30191:17:0;;;:9;:17;;;;;;;;;;;:91;;;;30316:20;;;;;;;:32;;30341:6;30316:24;:32::i;:::-;-1:-1:-1;;;;;30293:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;30364:35;1799:25:1;;;30293:20:0;;30364:35;;;;;;1772:18:1;30364:35:0;1653:177:1;39909:234:0;39999:11;40056:18;;40032:20;:42;;:66;;;;;40086:12;-1:-1:-1;;;;;40078:20:0;:4;-1:-1:-1;;;;;40078:20:0;;;40032:66;:103;;;;-1:-1:-1;40103:17:0;;-1:-1:-1;;;;;40103:17:0;:31;;40023:112;39909:234;-1:-1:-1;;;39909:234:0:o;40151:810::-;40252:4;40208:23;26164:18;;;;;;;;;;;40290;;:22;;40311:1;40290:22;:::i;:::-;40272:15;:40;40269:98;;;40345:18;;:22;;40366:1;40345:22;:::i;:::-;40327:40;;40269:98;40395:13;40392:562;;;40447:50;;-1:-1:-1;;;40447:50:0;;-1:-1:-1;;;;;40479:16:0;2031:32:1;40447:50:0;;;2013:51:1;40424:20:0;;34084:42;;40447:23;;1986:18:1;;40447:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40424:73;;40512:34;40523:15;40540:5;40512:10;:34::i;:::-;40577:50;;-1:-1:-1;;;40577:50:0;;-1:-1:-1;;;;;40609:16:0;2031:32:1;40577:50:0;;;2013:51:1;40630:12:0;;34084:42;;40577:23;;1986:18:1;;40577:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:65;;;;:::i;:::-;40657:55;;-1:-1:-1;;;40657:55:0;;;;;1799:25:1;;;40562:80:0;;-1:-1:-1;40657:16:0;-1:-1:-1;;;;;40657:41:0;;;;1772:18:1;;40657:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;40732:27:0;;40746:12;;-1:-1:-1;40732:27:0;;-1:-1:-1;40732:27:0;;;40409:363;42134:325;;:::o;40392:562::-;40801:33;40812:15;40829:4;40801:10;:33::i;:::-;40876:17;;40868:65;;40851:12;;-1:-1:-1;;;;;40876:17:0;;40907:21;;40851:12;40868:65;40851:12;40868:65;40907:21;40876:17;40868:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;40197:764:0;40151:810;:::o;38716:1008::-;38839:14;:34;38757:20;;-1:-1:-1;;;;;;;;38839:34:0;;;;;38781:54;;-1:-1:-1;;;38799:36:0;;;;38781:15;:54;:::i;:::-;38780:93;;;;:::i;:::-;39029:14;:34;38757:116;;-1:-1:-1;;;;;;;;;39029:34:0;;;;;38971:54;;-1:-1:-1;;;38989:36:0;;;;38971:15;:54;:::i;:::-;38970:93;;;;:::i;:::-;38934:129;;:15;:129;:::i;:::-;38888:14;:176;;-1:-1:-1;;;;;38888:176:0;;;;-1:-1:-1;;;38888:176:0;-1:-1:-1;;;;;38888:176:0;;;;;;;;;39111:28;;-1:-1:-1;;;39111:28:0;;39126:12;-1:-1:-1;;;;;2031:32:1;39111:28:0;;;2013:51:1;-1:-1:-1;;39111:4:0;;:14;;1986:18:1;;39111:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39080:59;;39154:27;34441:1;39201:12;:40;39198:119;;;34441:1;39257:40;;39198:119;39333:9;39329:266;39347:12;39345:1;:14;39329:266;;;39429:14;:32;39379:22;;39404:70;;39467:6;;39404:58;;:20;;-1:-1:-1;;;39429:32:0;;-1:-1:-1;;;;;39429:32:0;39404:24;:58::i;:::-;:62;;:70::i;:::-;39379:95;-1:-1:-1;39493:38:0;39379:95;39493:38;;:::i;:::-;;-1:-1:-1;39546:37:0;39569:14;39546:37;;:::i;:::-;;;39364:231;39360:3;;;;;:::i;:::-;;;;39329:266;;;;39605:65;39621:12;39643:4;39650:19;39605:15;:65::i;:::-;39696:12;-1:-1:-1;;;;;39681:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38746:978;;;38716:1008::o;39736:165::-;39789:11;39827:12;-1:-1:-1;;;;;39819:20:0;:4;-1:-1:-1;;;;;39819:20:0;;:73;;39869:22;;39856:10;;:35;;;;:::i;:::-;39819:73;;;-1:-1:-1;;39842:10:0;;;39736:165::o;40969:1157::-;41067:4;26730:7;26757:18;;;:11;:18;;;;;;;;33826:42;26757:27;;;;;;;;41101:11;-1:-1:-1;41046:143:0;;;41127:62;41144:4;33826:42;33493:20;41127:8;:62::i;:::-;41213:10;41210:909;;;41263:16;;;41277:1;41263:16;;;;;;;;41239:21;;41263:16;;;;;;;;;;-1:-1:-1;41263:16:0;41239:40;;41312:4;41294;41299:1;41294:7;;;;;;;;:::i;:::-;;;;;;:23;-1:-1:-1;;;;;41294:23:0;;;-1:-1:-1;;;;;41294:23:0;;;;;34084:42;41332:4;41337:1;41332:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;41332:15:0;;;:7;;;;;;;;;;;:15;41392:247;;-1:-1:-1;;;41392:247:0;;33826:42;;41392:65;;:247;;41476:11;;41506:1;;41554:4;;41585;;41609:15;;41392:247;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;41210:909;41704:16;;;41718:1;41704:16;;;;;;;;41680:21;;41704:16;;;;;;;;;;-1:-1:-1;41704:16:0;41680:40;;41753:4;41735;41740:1;41735:7;;;;;;;;:::i;:::-;;;;;;:23;-1:-1:-1;;;;;41735:23:0;;;-1:-1:-1;;;;;41735:23:0;;;;;34084:42;41773:4;41778:1;41773:7;;;;;;;;:::i;:::-;-1:-1:-1;;;;;41773:15:0;;;:7;;;;;;;;;;;:15;41845:262;;-1:-1:-1;;;41845:262:0;;33826:42;;41845:68;;:262;;41932:11;;41962:1;;42010:4;;42041:16;;42077:15;;41845:262;;;:::i;14104:471::-;14162:7;14407:1;14412;14407:6;14403:47;;-1:-1:-1;14437:1:0;14430:8;;14403:47;14462:9;14474:5;14478:1;14474;:5;:::i;:::-;14462:17;-1:-1:-1;14507:1:0;14498:5;14502:1;14462:17;14498:5;:::i;:::-;:10;14490:56;;;;-1:-1:-1;;;14490:56:0;;17380:2:1;14490:56:0;;;17362:21:1;17419:2;17399:18;;;17392:30;17458:34;17438:18;;;17431:62;-1:-1:-1;;;17509:18:1;;;17502:31;17550:19;;14490:56:0;17178:397:1;15051:132:0;15109:7;15136:39;15140:1;15143;15136:39;;;;;;;;;;;;;;;;;15765:7;15800:12;15793:5;15785:28;;;;-1:-1:-1;;;15785:28:0;;;;;;;;:::i;:::-;-1:-1:-1;15824:9:0;15836:5;15840:1;15836;:5;:::i;14:548: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;;;298:3;483:1;478:2;469:6;458:9;454:22;450:31;443:42;553:2;546;542:7;537:2;529:6;525:15;521:29;510:9;506:45;502:54;494:62;;;;14:548;;;;:::o;567:131::-;-1:-1:-1;;;;;642:31:1;;632:42;;622:70;;688:1;685;678:12;703:315;771:6;779;832:2;820:9;811:7;807:23;803:32;800:52;;;848:1;845;838:12;800:52;887:9;874:23;906:31;931:5;906:31;:::i;:::-;956:5;1008:2;993:18;;;;980:32;;-1:-1:-1;;;703:315:1:o;1215:248::-;1283:6;1291;1344:2;1332:9;1323:7;1319:23;1315:32;1312:52;;;1360:1;1357;1350:12;1312:52;-1:-1:-1;;1383:23:1;;;1453:2;1438:18;;;1425:32;;-1:-1:-1;1215:248:1:o;1468:180::-;1527:6;1580:2;1568:9;1559:7;1555:23;1551:32;1548:52;;;1596:1;1593;1586:12;1548:52;-1:-1:-1;1619:23:1;;1468:180;-1:-1:-1;1468:180:1:o;2075:456::-;2152:6;2160;2168;2221:2;2209:9;2200:7;2196:23;2192:32;2189:52;;;2237:1;2234;2227:12;2189:52;2276:9;2263:23;2295:31;2320:5;2295:31;:::i;:::-;2345:5;-1:-1:-1;2402:2:1;2387:18;;2374:32;2415:33;2374:32;2415:33;:::i;:::-;2075:456;;2467:7;;-1:-1:-1;;;2521:2:1;2506:18;;;;2493:32;;2075:456::o;2725:247::-;2784:6;2837:2;2825:9;2816:7;2812:23;2808:32;2805:52;;;2853:1;2850;2843:12;2805:52;2892:9;2879:23;2911:31;2936:5;2911:31;:::i;2977:171::-;3044:20;;-1:-1:-1;;;;;3093:30:1;;3083:41;;3073:69;;3138:1;3135;3128:12;3073:69;2977:171;;;:::o;3153:256::-;3219:6;3227;3280:2;3268:9;3259:7;3255:23;3251:32;3248:52;;;3296:1;3293;3286:12;3248:52;3319:28;3337:9;3319:28;:::i;:::-;3309:38;;3366:37;3399:2;3388:9;3384:18;3366:37;:::i;:::-;3356:47;;3153:256;;;;;:::o;3882:184::-;3940:6;3993:2;3981:9;3972:7;3968:23;3964:32;3961:52;;;4009:1;4006;3999:12;3961:52;4032:28;4050:9;4032:28;:::i;5462:388::-;5530:6;5538;5591:2;5579:9;5570:7;5566:23;5562:32;5559:52;;;5607:1;5604;5597:12;5559:52;5646:9;5633:23;5665:31;5690:5;5665:31;:::i;:::-;5715:5;-1:-1:-1;5772:2:1;5757:18;;5744:32;5785:33;5744:32;5785:33;:::i;:::-;5837:7;5827:17;;;5462:388;;;;;:::o;5855:380::-;5934:1;5930:12;;;;5977;;;5998:61;;6052:4;6044:6;6040:17;6030:27;;5998:61;6105:2;6097:6;6094:14;6074:18;6071:38;6068:161;;6151:10;6146:3;6142:20;6139:1;6132:31;6186:4;6183:1;6176:15;6214:4;6211:1;6204:15;6068:161;;5855:380;;;:::o;6240:356::-;6442:2;6424:21;;;6461:18;;;6454:30;6520:34;6515:2;6500:18;;6493:62;6587:2;6572:18;;6240:356::o;6601:127::-;6662:10;6657:3;6653:20;6650:1;6643:31;6693:4;6690:1;6683:15;6717:4;6714:1;6707:15;6733:168;6806:9;;;6837;;6854:15;;;6848:22;;6834:37;6824:71;;6875:18;;:::i;6906:127::-;6967:10;6962:3;6958:20;6955:1;6948:31;6998:4;6995:1;6988:15;7022:4;7019:1;7012:15;7038:120;7078:1;7104;7094:35;;7109:18;;:::i;:::-;-1:-1:-1;7143:9:1;;7038:120::o;7163:184::-;7233:6;7286:2;7274:9;7265:7;7261:23;7257:32;7254:52;;;7302:1;7299;7292:12;7254:52;-1:-1:-1;7325:16:1;;7163:184;-1:-1:-1;7163:184:1:o;7657:277::-;7724:6;7777:2;7765:9;7756:7;7752:23;7748:32;7745:52;;;7793:1;7790;7783:12;7745:52;7825:9;7819:16;7878:5;7871:13;7864:21;7857:5;7854:32;7844:60;;7900:1;7897;7890:12;8766:306;8854:6;8862;8870;8923:2;8911:9;8902:7;8898:23;8894:32;8891:52;;;8939:1;8936;8929:12;8891:52;8968:9;8962:16;8952:26;;9018:2;9007:9;9003:18;8997:25;8987:35;;9062:2;9051:9;9047:18;9041:25;9031:35;;8766:306;;;;;:::o;10460:681::-;10591:6;10599;10607;10615;10623;10631;10639;10647;10700:3;10688:9;10679:7;10675:23;10671:33;10668:53;;;10717:1;10714;10707:12;10668:53;10749:9;10743:16;10768:31;10793:5;10768:31;:::i;:::-;10818:5;10808:15;;;10863:2;10852:9;10848:18;10842:25;10832:35;;10907:2;10896:9;10892:18;10886:25;10876:35;;10951:2;10940:9;10936:18;10930:25;10920:35;;10995:3;10984:9;10980:19;10974:26;10964:36;;11040:3;11029:9;11025:19;11019:26;11009:36;;11085:3;11074:9;11070:19;11064:26;11054:36;;11130:3;11119:9;11115:19;11109:26;11099:36;;10460:681;;;;;;;;;;;:::o;11146:127::-;11207:10;11202:3;11198:20;11195:1;11188:31;11238:4;11235:1;11228:15;11262:4;11259:1;11252:15;12596:125;12661:9;;;12682:10;;;12679:36;;;12695:18;;:::i;13534:401::-;13736:2;13718:21;;;13775:2;13755:18;;;13748:30;13814:34;13809:2;13794:18;;13787:62;-1:-1:-1;;;13880:2:1;13865:18;;13858:35;13925:3;13910:19;;13534:401::o;13940:399::-;14142:2;14124:21;;;14181:2;14161:18;;;14154:30;14220:34;14215:2;14200:18;;14193:62;-1:-1:-1;;;14286:2:1;14271:18;;14264:33;14329:3;14314:19;;13940:399::o;14703:180::-;-1:-1:-1;;;;;14808:10:1;;;14820;;;14804:27;;14843:11;;;14840:37;;;14857:18;;:::i;:::-;14840:37;14703:180;;;;:::o;14888:128::-;14955:9;;;14976:11;;;14973:37;;;14990:18;;:::i;15672:112::-;15704:1;15730;15720:35;;15735:18;;:::i;:::-;-1:-1:-1;15769:9:1;;15672:112::o;15789:135::-;15828:3;15849:17;;;15846:43;;15869:18;;:::i;:::-;-1:-1:-1;15916:1:1;15905:13;;15789:135::o;16061:127::-;16122:10;16117:3;16113:20;16110:1;16103:31;16153:4;16150:1;16143:15;16177:4;16174:1;16167:15;16193:980;16455:4;16503:3;16492:9;16488:19;16534:6;16523:9;16516:25;16560:2;16598:6;16593:2;16582:9;16578:18;16571:34;16641:3;16636:2;16625:9;16621:18;16614:31;16665:6;16700;16694:13;16731:6;16723;16716:22;16769:3;16758:9;16754:19;16747:26;;16808:2;16800:6;16796:15;16782:29;;16829:1;16839:195;16853:6;16850:1;16847:13;16839:195;;;16918:13;;-1:-1:-1;;;;;16914:39:1;16902:52;;17009:15;;;;16974:12;;;;16950:1;16868:9;16839:195;;;-1:-1:-1;;;;;;;17090:32:1;;;;17085:2;17070:18;;17063:60;-1:-1:-1;;;17154:3:1;17139:19;17132:35;17051:3;16193:980;-1:-1:-1;;;16193:980:1:o

Swarm Source

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