ETH Price: $3,400.01 (+1.96%)
Gas: 3.08 Gwei

Token

BooBanker Research Association (BBRA)
 

Overview

Max Total Supply

12,989.547203154287234918 BBRA

Holders

133 (0.00%)

Market

Price

$1.02 @ 0.000299 ETH

Onchain Market Cap

$13,195.63

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
0.22 BBRA

Value
$0.22 ( ~6.47056653880682E-05 Eth) [0.0017%]
0xe62ee4edbc68b58038afaf5129bffbada0c23afd
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

BooBanker Research Association aims to offer yield-farming DAO protocol that incentives its community to build and take part in the crypto revolution.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
BooBankerResearchAssociation

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-11-27
*/

// SPDX-License-Identifier: MIT

pragma solidity =0.6.12;


// 
/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

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

// 
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
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 () internal {
        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;
    }
}

// 
/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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);
}

// 
/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
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;
    }
}

// 
/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// 
/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20BurnableMaxSupply is Context, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;
        _decimals = 18;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view 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 {_setupDecimals} is
     * called.
     *
     * 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 returns (uint8) {
        return _decimals;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view 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.
     *
     * ADJUSTMENTS: Can only mint up to 13k (13e21) BBRA (burn + farm rewards have to be stable at lower than 13k)
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` 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);

        if (_totalSupply.add(amount) > 13e21) {
            // if supply is over 13k after adding 'amount' check what is available to be minted (13e21 - current supply)
            // if it's greater than 0 then we can mint up to that amount
            // Eg totalSupply = 12,999e18 BBRA and amount to be minted is 10e18 BBRA. We can't mint 10e18 because it takes us over
            // hard cap. However we can mint a partial amount aka 13e21 - 12,999e18 = 1e18
            amount = uint256(13e21).sub(_totalSupply);

            // can't mint even a partial amount so we must exit the function
            if (amount == 0)
                return;
        }

        _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 Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @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 { }
}

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 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;
}

// 
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an admin) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the admin account will be the one that deploys the contract. This
 * can later be changed with {transferAdmin}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyAdmin`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Administrable is Context {
    address private _admin;

    event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);

    /**
     * @dev Initializes the contract setting the deployer as the initial admin.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _admin = msgSender;
        emit AdminTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the admin.
     */
    modifier onlyAdmin() {
        require(_admin == _msgSender(), "Administrable: caller is not the admin");
        _;
    }

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

    /**
     * @dev Transfers admin of the contract to a new account (`newAdmin`).
     * Can only be called by the current ad,om.
     */
    function transferAdmin(address newAdmin) public virtual onlyAdmin {
        require(newAdmin != address(0), "Administrable: new admin is the zero address");
        emit AdminTransferred(_admin, newAdmin);
        _admin = newAdmin;
    }
}

// 
abstract contract ERC20Payable {

    event Received(address indexed sender, uint256 amount);

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }
}

// 
interface ISecondaryToken {
    // placeholder interface for tokens generate from burn
    // could be used in future to pass the responsibility to a contract that
    // would then mint the burn with dynamic variables from nfts

    function mint(
        address account,
        uint256 amount
    ) external;
}

// 
interface IProtocolAdapter {
    // Gets adapted burn divisor
    function getBurnDivisor(address _user, uint256 _currentBurnDivisor) external view returns (uint256);

    // Gets adapted farm rewards multiplier
    function getRewardsMultiplier(address _user, uint256 _currentRewardsMultiplier) external view returns (uint256);
}

// 
/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20BurnableMaxSupply {
    /**
     * @dev Destroys `amount` tokens from the caller. CANNOT BE USED TO BURN OTHER PEOPLES TOKENS
     * ONLY BBRA AND ONLY FROM THE PERSON CALLING THE FUNCTION
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }
}

// 
// Boo with Governance.
// Ownership given to Farming contract and Adminship can be given to DAO contract
contract BooBankerResearchAssociation is ERC20BurnableMaxSupply("BooBanker Research Association", "BBRA"), ERC20Burnable, Ownable, Administrable, ERC20Payable {
    using SafeMath for uint256;

    // uniswap info
    address public uniswapV2Router;
    address public uniswapV2Pair;
    address public uniswapV2Factory;

    // the amount burned tokens every transfer, i.e. 255 = 0.4%, 100 = 1%, 50 = 2%, 40 = 2.5%
    uint256 public burnDivisor;
    // the amount tokens saved for liquidity lock every transfer, i.e. 255 = 0.4%, 100 = 1%, 50 = 2%, 40 = 2.5%
    uint256 public liquidityDivisor;

    // If any token should be minted from burned $bbra (not $brra)
    ISecondaryToken public burnToken;

    // Dynamic burn regulator (less burn with a certain number of nfts etc)
    IProtocolAdapter public protocolAdapter;

    // Whether the protocol should reward those that spend their gas fees locking liquidity
    bool public rewardLiquidityLockCaller;

    // Pause trading after listing until x block - can only be used once
    bool public canPause;
    uint256 public pauseUntilBlock;

    // Timestamp of last liquidity lock call
    uint256 public lastLiquidityLock;

    // 1% of all transfers are sent to marketing fund
    address public _devaddr;

    // Events
    event LiquidityLock(uint256 tokenAmount, uint256 ethAmount);
    event LiquidityBurn(uint256 lpTokenAmount);
    event CallerReward(address caller, uint256 tokenAmount);
    event BuyBack(uint256 ethAmount, uint256 tokenAmount);
    event ProtocolAdapterChange(address _newProtocol);

    constructor(uint256 _burnDivisor, uint256 _liquidityDivisor) public {

        burnDivisor = _burnDivisor;
        liquidityDivisor = _liquidityDivisor;
        _devaddr = msg.sender;
        rewardLiquidityLockCaller = true;
        canPause = true;
        // initial quantity, 13k tokens
        _mint(msg.sender, 13e21);
    }

    function transferFrom(address sender, address recipient, uint256 amount) public checkRunning virtual override returns (bool) {
        uint256 onePct = amount.div(100);
        uint256 liquidityAmount = amount.div(liquidityDivisor);
        // Use dynamic burn divisor if Adapter contract is set
        uint256 burnAmount = amount.div(
            ( address(protocolAdapter) != address(0)
                ? protocolAdapter.getBurnDivisor(pickHuman(sender, recipient), burnDivisor)
                : burnDivisor
            )
        );

        _burn(sender, burnAmount);

        // Should a secondary token be given to recipient from burn amount?
        //
        if(address(burnToken) != address(0)) {
            burnToken.mint(recipient, burnAmount);
        }

        super.transferFrom(sender, _devaddr, onePct);
        super.transferFrom(sender, address(this), liquidityAmount);
        return super.transferFrom(sender, recipient, amount.sub(burnAmount).sub(liquidityAmount).sub(onePct));
    }

    function transfer(address recipient, uint256 amount) public checkRunning virtual override returns (bool) {
        uint256 onePct = amount.div(100);
        uint256 liquidityAmount = amount.div(liquidityDivisor);
        // Use dynamic burn divisor if Adapter contract is set
        uint256 burnAmount = amount.div(
            ( address(protocolAdapter) != address(0)
                ? protocolAdapter.getBurnDivisor(pickHuman(msg.sender, recipient), burnDivisor)
                : burnDivisor
            )
        );

        // do nft adapter
        _burn(msg.sender, burnAmount);

        // Should a secondary token be given to recipient from burn amount?
        if(address(burnToken) != address(0)) {
            burnToken.mint(recipient, burnAmount);
        }

        super.transfer(_devaddr, onePct);
        super.transfer(address(this), liquidityAmount);
        return super.transfer(recipient, amount.sub(burnAmount).sub(liquidityAmount).sub(onePct));
    }

    // Check if _from is human when calculating ProtocolAdapter settings (like burn)
    // so that if you're buying from Uniswap the adjusted burn still works
    function pickHuman(address _from, address _to) public view returns (address) {
        uint256 _codeLength;
        assembly {_codeLength := extcodesize(_from)}
        return _codeLength == 0 ? _from : _to;
    }

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

    // To be used to stop trading at listing - prevent bots from buying
    modifier checkRunning(){
        require(block.number > pauseUntilBlock, "Go away bot");
        _;
    }

    // Trading can only be paused once, ever. Setting pauseUntilBlock to 0 resumes trading after pausing.
    function setPauseUntilBlock(uint256 _pauseUntilBlock) public onlyAdminOrOwner {
        require(canPause || _pauseUntilBlock == 0, 'Pause has already been used once. If disabling pause set block to 0');
        pauseUntilBlock = _pauseUntilBlock;
        // after the first pause we can no longer pause the protocol
        canPause = false;
    }

    /**
     * @dev prevents contracts from interacting with functions that have this modifier
     */
    modifier isHuman() {
        address _addr = msg.sender;
        uint256 _codeLength;

        assembly {_codeLength := extcodesize(_addr)}

//        if (_codeLength == 0) {
//            // use assert to consume all of the bots gas, kek
//            assert(true == false, 'oh boy - bots get rekt');
//        }
        require(_codeLength == 0, "sorry humans only");
        _;
    }

    // Sell half of burned tokens, provides liquidity and locks it away forever
    // can only be called when balance is > 1 and last lock is more than 2 hours ago
    function lockLiquidity() public isHuman() {
        // bbra balance
        uint256 _bal = balanceOf(address(this));
        require(uniswapV2Pair != address(0), "UniswapV2Pair not set in contract yet");
        require(uniswapV2Router != address(0), "UniswapV2Router not set in contract yet");
        require(_bal >= 1e18, "Minimum of 1 BBRA before we can lock liquidity");
        require(balanceOf(msg.sender) >= 5e18, "You must own at least 5 BBra to call lock");

        // caller rewards
        uint256 _callerReward = 0;
        if (rewardLiquidityLockCaller) {
            // subtract caller fee - 2% always
            _callerReward = _bal.div(50);
            _bal = _bal.sub(_callerReward);
        }

        // calculate ratios of bbra-eth for lp
        uint256 bbraToEth = _bal.div(2);
        uint256 brraForLiq = _bal.sub(bbraToEth);

        // Eth Balance before swap
        uint256 startingBalance = address(this).balance;
        swapTokensForWeth(bbraToEth);

        // due to price movements after selling it is likely that less than the amount of
        // eth received will be used for locking
        // instead of making the left over eth locked away forever we can call buyAndBurn() to buy back Bbra with leftover Eth
        uint256 ethFromBbra = address(this).balance.sub(startingBalance);
        addLiquidity(brraForLiq, ethFromBbra);

        emit LiquidityLock(brraForLiq, ethFromBbra);

        // only reward caller after trade to prevent any possible reentrancy
        // check balance is still available
        if (_callerReward != 0) {
            // in case LP takes more tokens than we are expecting reward _callerReward or balanceOf(this) - whichever is smallest
            if(balanceOf(address(this)) >= _callerReward) {
                transfer(msg.sender, _callerReward);
            } else {
                transfer(msg.sender, balanceOf(address(this)));
            }
        }

        lastLiquidityLock = block.timestamp;
    }

    // If for some reason we get more eth than expect from uniswap at time of locking liquidity
    // we buy and burn whatever amount of Bbra we get
    // can optout of burn so that instead it's added to the next liquidity lock instead

    // NOTE: Buy back not working due to address(this) being the token that we're buying from uniswap - apparently they
    // don't accept that. Leaving the code here however for anyone that wishes to adapt it and "fix" it
//    function buyAndBurn(bool _burnTokens) public {
//        // check minimum amount
//        uint256 startingBbra = balanceOf(address(this));
//        uint256 startingEth = address(this).balance;
//
//        require(startingEth >= 5e16, 'Contract balance must be at least 0.05 eth before invoking buyAndBurn');
//
//        swapWethForTokens(address(this).balance);
//        uint256 buyBackAmount = startingBbra.sub(balanceOf(address(this)));
//
//        // if burn is active and we have bought some tokens back successfuly then burnnnn
//        // if burn == false then tokens purchased will be used in liquidity at next lockLiquidity() call
//        if(_burnTokens && buyBackAmount != 0) {
//            // burn whatever amount was bought
//            _burn(address(this), buyBackAmount);
//        }
//        emit BuyBack(startingEth.sub(address(this).balance), buyBackAmount);
//    }
//
//    // buys bbra with left over eth - only called by liquidity lock function or buy&burn function
//    function swapWethForTokens(uint256 ethAmount) internal {
//        address[] memory uniswapPairPath = new address[](2);
//        uniswapPairPath[0] = IUniswapV2Router02(uniswapV2Router).WETH();
//        uniswapPairPath[1] = address(this);
//
//        IUniswapV2Router02(uniswapV2Router)
//        .swapExactETHForTokensSupportingFeeOnTransferTokens{
//        value: ethAmount
//        }(
//            0,
//            uniswapPairPath,
//            address(this),
//            block.timestamp
//        );
//    }

    // swaps bra for eth - only called by liquidity lock function
    function swapTokensForWeth(uint256 tokenAmount) internal {
        address[] memory uniswapPairPath = new address[](2);
        uniswapPairPath[0] = address(this);
        uniswapPairPath[1] = IUniswapV2Router02(uniswapV2Router).WETH();

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

        IUniswapV2Router02(uniswapV2Router)
        .swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            uniswapPairPath,
            address(this),
            block.timestamp
        );
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) internal {
        // approve uniswapV2Router to transfer Brra
        _approve(address(this), uniswapV2Router, tokenAmount);

        // provide liquidity
        IUniswapV2Router02(uniswapV2Router)
        .addLiquidityETH{
            value: ethAmount
        }(
            address(this),
            tokenAmount,
            0,
            0,
            address(this),
            block.timestamp
        );

        // check LP balance
        uint256 _lpBalance = IERC20(uniswapV2Pair).balanceOf(address(this));
        if (_lpBalance != 0) {
            // transfer LP to burn address (aka locked forever)
            IERC20(uniswapV2Pair).transfer(address(0), _lpBalance);
            // any left over eth is sent to marketing for buy backs - will be a very minimal amount
            payable(_devaddr).transfer(address(this).balance);
            emit LiquidityBurn(_lpBalance);
        }
    }

    // returns amount of LP locked permanently
    function lockedLpAmount() public view returns(uint256) {
        if (uniswapV2Pair == address(0)) {
            return 0;
        }

        return IERC20(uniswapV2Pair).balanceOf(address(0));
    }

    // Whether Bbra should reward the person that pays for the gas calling the liquidity lock
    function setRewardLiquidityLockCaller(bool _rewardLiquidityLockCaller) public onlyAdminOrOwner {
        rewardLiquidityLockCaller = _rewardLiquidityLockCaller;
    }

    // Updates secondary token that could be minted from burned supply of BBRA (like BOOB mints ECTO on burn)
    function setSecondaryBurnToken(ISecondaryToken _token) public onlyAdminOrOwner {
        // this prevents the secondary token being itself and therefore negating burn
        require(address(_token) != address(this), 'Secondary token cannot be itself');
        // can be anything else, 0x0 disables secondary token usage
        burnToken = _token;
    }

    // Sets contract that regulates dynamic burn rates (changeable by DAO)
    function setProtocolAdapter(IProtocolAdapter _contract) public onlyAdminOrOwner {
        // setting to 0x0 disabled dynamic burn and is defaulted to regular burn
        protocolAdapter = _contract;
        emit ProtocolAdapterChange(address(_contract));
    }

    // self explanatory
    function setBurnRate(uint256 _burnDivisor) public onlyAdminOrOwner {
        require(_burnDivisor != 0, "Boo: burnDivisor must be bigger than 0");
        burnDivisor = _burnDivisor;
    }

    // self explanatory
    function setLiquidityDivisor(uint256 _liquidityDivisor) public onlyAdminOrOwner {
        require(_liquidityDivisor != 0, "Boo: _liquidityDivisor must be bigger than 0");
        liquidityDivisor = _liquidityDivisor;
    }

    /// @dev Creates `_amount` token to `_to`. Must only be called by the owner (MrBanker), used to mint farming rewards
    // and nothing else
    function mint(address _to, uint256 _amount) public onlyOwner {
        _mint(_to, _amount);
        _moveDelegates(address(0), _delegates[_to], _amount);
    }

    // Sets marketing address (where 1% is deposited)
    // Only owner can modify this (MrBanker)
    function setDevAddr(address _dev) public onlyOwner {
        _devaddr = _dev;
    }

    // sets uniswap router and LP pair addresses (needed for buy-back/sell and liquidity lock)
    function setUniswapAddresses(address _uniswapV2Factory, address _uniswapV2Router) public onlyAdminOrOwner {
        require(_uniswapV2Factory != address(0) && _uniswapV2Router != address(0), 'Uniswap addresses cannot be empty');
        uniswapV2Factory = _uniswapV2Factory;
        uniswapV2Router = _uniswapV2Router;

        if (uniswapV2Pair == address(0)) {
            createUniswapPair();
        }
    }

    // create LP pair if one hasn't been created
    // can be public, doesn't matter who calls it
    function createUniswapPair() public {
        require(uniswapV2Pair == address(0), "Pair has already been created");
        require(uniswapV2Factory != address(0) && uniswapV2Router != address(0), "Uniswap addresses have not been set");

        uniswapV2Pair = IUniswapV2Factory(uniswapV2Factory).createPair(
                IUniswapV2Router02(uniswapV2Router).WETH(),
                address(this)
        );
    }

    // Copied and modified from YAM code:
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
    // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
    // Which is copied and modified from COMPOUND:
    // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol

    /// @dev A record of each accounts delegate
    mapping (address => address) internal _delegates;

    /// @dev A checkpoint for marking number of votes from a given block
    struct Checkpoint {
        uint32 fromBlock;
        uint256 votes;
    }

    /// @dev A record of votes checkpoints for each account, by index
    mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;

    /// @dev The number of checkpoints for each account
    mapping (address => uint32) public numCheckpoints;

    /// @dev The EIP-712 typehash for the contract's domain
    bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

    /// @dev The EIP-712 typehash for the delegation struct used by the contract
    bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    /// @dev A record of states for signing / validating signatures
    mapping (address => uint) public nonces;

    /// @dev An event thats emitted when an account changes its delegate
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /// @dev An event thats emitted when a delegate account's vote balance changes
    event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);

    /**
     * @dev Delegate votes from `msg.sender` to `delegatee`
     * @param delegator The address to get delegatee for
     */
    function delegates(address delegator)
    external
    view
    returns (address)
    {
        return _delegates[delegator];
    }

    /**
     * @dev Delegate votes from `msg.sender` to `delegatee`
     * @param delegatee The address to delegate votes to
     */
    function delegate(address delegatee) external {
        return _delegate(msg.sender, delegatee);
    }

    /**
     * @dev Delegates votes from signatory to `delegatee`
     * @param delegatee The address to delegate votes to
     * @param nonce The contract state required to match the signature
     * @param expiry The time at which to expire the signature
     * @param v The recovery byte of the signature
     * @param r Half of the ECDSA signature pair
     * @param s Half of the ECDSA signature pair
     */
    function delegateBySig(
        address delegatee,
        uint nonce,
        uint expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
    external
    {
        bytes32 domainSeparator = keccak256(
            abi.encode(
                DOMAIN_TYPEHASH,
                keccak256(bytes(name())),
                getChainId(),
                address(this)
            )
        );

        bytes32 structHash = keccak256(
            abi.encode(
                DELEGATION_TYPEHASH,
                delegatee,
                nonce,
                expiry
            )
        );

        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                domainSeparator,
                structHash
            )
        );

        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), "BOOB::delegateBySig: invalid signature");
        require(nonce == nonces[signatory]++, "BOOB::delegateBySig: invalid nonce");
        require(now <= expiry, "BOOB::delegateBySig: signature expired");
        return _delegate(signatory, delegatee);
    }

    /**
     * @dev Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getCurrentVotes(address account)
    external
    view
    returns (uint256)
    {
        uint32 nCheckpoints = numCheckpoints[account];
        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
    }

    /**
     * @dev Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPriorVotes(address account, uint blockNumber)
    external
    view
    returns (uint256)
    {
        require(blockNumber < block.number, "BOOB::getPriorVotes: not yet determined");

        uint32 nCheckpoints = numCheckpoints[account];
        if (nCheckpoints == 0) {
            return 0;
        }

        // First check most recent balance
        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
            return checkpoints[account][nCheckpoints - 1].votes;
        }

        // Next check implicit zero balance
        if (checkpoints[account][0].fromBlock > blockNumber) {
            return 0;
        }

        uint32 lower = 0;
        uint32 upper = nCheckpoints - 1;
        while (upper > lower) {
            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
            Checkpoint memory cp = checkpoints[account][center];
            if (cp.fromBlock == blockNumber) {
                return cp.votes;
            } else if (cp.fromBlock < blockNumber) {
                lower = center;
            } else {
                upper = center - 1;
            }
        }
        return checkpoints[account][lower].votes;
    }

    function _delegate(address delegator, address delegatee)
    internal
    {
        address currentDelegate = _delegates[delegator];
        uint256 delegatorBalance = balanceOf(delegator); // balance of underlying BOOBs (not scaled);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveDelegates(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                // decrease old representative
                uint32 srcRepNum = numCheckpoints[srcRep];
                uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint256 srcRepNew = srcRepOld.sub(amount);
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                // increase new representative
                uint32 dstRepNum = numCheckpoints[dstRep];
                uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint256 dstRepNew = dstRepOld.add(amount);
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(
        address delegatee,
        uint32 nCheckpoints,
        uint256 oldVotes,
        uint256 newVotes
    )
    internal
    {
        uint32 blockNumber = safe32(block.number, "BOOB::_writeCheckpoint: block number exceeds 32 bits");

        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
        } else {
            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
            numCheckpoints[delegatee] = nCheckpoints + 1;
        }

        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
    }

    function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
        require(n < 2**32, errorMessage);
        return uint32(n);
    }

    function getChainId() internal pure returns (uint) {
        uint256 chainId;
        assembly { chainId := chainid() }
        return chainId;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_burnDivisor","type":"uint256"},{"internalType":"uint256","name":"_liquidityDivisor","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"BuyBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"CallerReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lpTokenAmount","type":"uint256"}],"name":"LiquidityBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"LiquidityLock","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":"address","name":"_newProtocol","type":"address"}],"name":"ProtocolAdapterChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Received","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":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_devaddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","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":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnDivisor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnToken","outputs":[{"internalType":"contract ISecondaryToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canPause","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint256","name":"votes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createUniswapPair","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":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastLiquidityLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityDivisor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockedLpAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseUntilBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"pickHuman","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolAdapter","outputs":[{"internalType":"contract IProtocolAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardLiquidityLockCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnDivisor","type":"uint256"}],"name":"setBurnRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dev","type":"address"}],"name":"setDevAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_liquidityDivisor","type":"uint256"}],"name":"setLiquidityDivisor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilBlock","type":"uint256"}],"name":"setPauseUntilBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IProtocolAdapter","name":"_contract","type":"address"}],"name":"setProtocolAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_rewardLiquidityLockCaller","type":"bool"}],"name":"setRewardLiquidityLockCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISecondaryToken","name":"_token","type":"address"}],"name":"setSecondaryBurnToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_uniswapV2Factory","type":"address"},{"internalType":"address","name":"_uniswapV2Router","type":"address"}],"name":"setUniswapAddresses","outputs":[],"stateMutability":"nonpayable","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":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"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":[],"name":"uniswapV2Factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b506040516200518638038062005186833981810160405260408110156200003757600080fd5b508051602091820151604080518082018252601e81527f426f6f42616e6b6572205265736561726368204173736f63696174696f6e0000818601908152825180840190935260048352634242524160e01b958301959095528051939492939092620000a69160039190620004a9565b508051620000bc906004906020840190620004a9565b50506005805460ff19166012179055506000620000d8620001e7565b60058054610100600160a81b0319166101006001600160a01b03841690810291909117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060006200013a620001e7565b600680546001600160a01b0319166001600160a01b038316908117909155604051919250906000907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6908290a350600a829055600b819055601080546001600160a01b03191633908117909155600d805460ff60a81b1960ff60a01b19909116600160a01b1716600160a81b179055620001df906902c0bb3dd30c4e200000620001eb565b505062000545565b3390565b6001600160a01b03821662000247576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b62000255600083836200035d565b6902c0bb3dd30c4e2000006200027c826002546200036260201b620035651790919060201c565b1115620002b757620002a96002546902c0bb3dd30c4e200000620003c460201b620035d91790919060201c565b905080620002b75762000359565b620002d3816002546200036260201b620035651790919060201c565b6002556001600160a01b03821660009081526020818152604090912054620003069183906200356562000362821b17901c565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35b5050565b505050565b600082820183811015620003bd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000620003bd83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506200040e60201b60201c565b60008184841115620004a15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620004655781810151838201526020016200044b565b50505050905090810190601f168015620004935780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004ec57805160ff19168380011785556200051c565b828001600101855582156200051c579182015b828111156200051c578251825591602001919060010190620004ff565b506200052a9291506200052e565b5090565b5b808211156200052a57600081556001016200052f565b614c3180620005556000396000f3fe60806040526004361061034e5760003560e01c806370a08231116101bb578063abf05f5d116100f7578063e19c175d11610095578063f1127ed81161006f578063f1127ed814610ce9578063f2fde38b14610d55578063f851a44014610d95578063faa0a26414610daa5761038b565b8063e19c175d14610c4c578063e7a324dc14610c8c578063ef4a64d414610ca15761038b565b8063bb2f7199116100d1578063bb2f719914610b62578063c3cda52014610b77578063dd62ed3e14610bd8578063e157ee2e14610c205761038b565b8063abf05f5d14610af8578063b4b5ea5714610b0d578063ba52c8b714610b4d5761038b565b80638bad0c0a1161016457806395d89b411161013e57806395d89b4114610a425780639a49f57114610a57578063a457c2d714610a6c578063a9059cbb14610ab25761038b565b80638bad0c0a146109d05780638cf5bf7c146109e55780638da5cb5b14610a2d5761038b565b8063782d6fe111610195578063782d6fe1146109355780637b2798d71461097b5780637ecebe00146109905761038b565b806370a08231146108a0578063715018a6146108e057806375829def146108f55761038b565b8063395093511161028a578063587cde1e1161023357806362d1d1dc1161020d57806362d1d1dc146107c857806367a4793e146107dd5780636ebb64a2146108075780636fcfff45146108475761038b565b8063587cde1e1461073357806359d0f713146107735780635c19a95c146107885761038b565b806349bd5a5e1161026457806349bd5a5e146106c95780634a131672146106de578063547c0e77146106f35761038b565b8063395093511461061357806340c10f191461065957806342966c681461069f5761038b565b80631fc53a43116102f757806323b872dd116102d157806323b872dd1461056e5780632aaab8fa146105be578063313ce567146105d3578063323be1c5146105fe5761038b565b80631fc53a431461051a57806320606b701461052f578063216c394d146105445761038b565b80631694505e116103285780631694505e1461049b57806318160ddd146104d9578063189d165e146104ee5761038b565b806306fdde0314610390578063095ea7b31461041a5780630fd8ee17146104745761038b565b3661038b5760408051348152905133917f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874919081900360200190a2005b600080fd5b34801561039c57600080fd5b506103a5610dbf565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103df5781810151838201526020016103c7565b50505050905090810190601f16801561040c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561042657600080fd5b506104606004803603604081101561043d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610e74565b604080519115158252519081900360200190f35b34801561048057600080fd5b50610489610e92565b60408051918252519081900360200190f35b3480156104a757600080fd5b506104b0610e98565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156104e557600080fd5b50610489610eb4565b3480156104fa57600080fd5b506105186004803603602081101561051157600080fd5b5035610eba565b005b34801561052657600080fd5b50610489611001565b34801561053b57600080fd5b506104896110cc565b34801561055057600080fd5b506105186004803603602081101561056757600080fd5b50356110f0565b34801561057a57600080fd5b506104606004803603606081101561059157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611286565b3480156105ca57600080fd5b50610489611518565b3480156105df57600080fd5b506105e861151e565b6040805160ff9092168252519081900360200190f35b34801561060a57600080fd5b50610460611527565b34801561061f57600080fd5b506104606004803603604081101561063657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611549565b34801561066557600080fd5b506105186004803603604081101561067c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356115a9565b3480156106ab57600080fd5b50610518600480360360208110156106c257600080fd5b503561167f565b3480156106d557600080fd5b506104b0611693565b3480156106ea57600080fd5b506105186116af565b3480156106ff57600080fd5b506105186004803603602081101561071657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661194c565b34801561073f57600080fd5b506104b06004803603602081101561075657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611b04565b34801561077f57600080fd5b506104b0611b2f565b34801561079457600080fd5b50610518600480360360208110156107ab57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611b4b565b3480156107d457600080fd5b50610489611b55565b3480156107e957600080fd5b506105186004803603602081101561080057600080fd5b5035611b5b565b34801561081357600080fd5b506105186004803603602081101561082a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ca2565b34801561085357600080fd5b506108876004803603602081101561086a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d7f565b6040805163ffffffff9092168252519081900360200190f35b3480156108ac57600080fd5b50610489600480360360208110156108c357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d97565b3480156108ec57600080fd5b50610518611dbf565b34801561090157600080fd5b506105186004803603602081101561091857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ec9565b34801561094157600080fd5b506104896004803603604081101561095857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561203e565b34801561098757600080fd5b506104b0612308565b34801561099c57600080fd5b50610489600480360360208110156109b357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612324565b3480156109dc57600080fd5b50610518612336565b3480156109f157600080fd5b506104b060048036036040811015610a0857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612420565b348015610a3957600080fd5b506104b061243a565b348015610a4e57600080fd5b506103a561245b565b348015610a6357600080fd5b506104b06124da565b348015610a7857600080fd5b5061046060048036036040811015610a8f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356124f6565b348015610abe57600080fd5b5061046060048036036040811015610ad557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561256b565b348015610b0457600080fd5b5061046061276a565b348015610b1957600080fd5b5061048960048036036020811015610b3057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661278b565b348015610b5957600080fd5b50610489612827565b348015610b6e57600080fd5b5061051861282d565b348015610b8357600080fd5b50610518600480360360c0811015610b9a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060408101359060ff6060820135169060808101359060a00135612b52565b348015610be457600080fd5b5061048960048036036040811015610bfb57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612e91565b348015610c2c57600080fd5b5061051860048036036020811015610c4357600080fd5b50351515612ec9565b348015610c5857600080fd5b5061051860048036036020811015610c6f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612fff565b348015610c9857600080fd5b50610489613164565b348015610cad57600080fd5b5061051860048036036040811015610cc457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613188565b348015610cf557600080fd5b50610d3560048036036040811015610d0c57600080fd5b50803573ffffffffffffffffffffffffffffffffffffffff16906020013563ffffffff16613366565b6040805163ffffffff909316835260208301919091528051918290030190f35b348015610d6157600080fd5b5061051860048036036020811015610d7857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613393565b348015610da157600080fd5b506104b061352d565b348015610db657600080fd5b506104b0613549565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e695780601f10610e3e57610100808354040283529160200191610e69565b820191906000526020600020905b815481529060010190602001808311610e4c57829003601f168201915b505050505090505b90565b6000610e88610e8161361b565b848461361f565b5060015b92915050565b600e5481565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b60025490565b610ec261361b565b73ffffffffffffffffffffffffffffffffffffffff16610ee061352d565b73ffffffffffffffffffffffffffffffffffffffff161480610f3b5750610f0561361b565b73ffffffffffffffffffffffffffffffffffffffff16610f2361243a565b73ffffffffffffffffffffffffffffffffffffffff16145b610fa657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b80610ffc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614a3f6026913960400191505060405180910390fd5b600a55565b60085460009073ffffffffffffffffffffffffffffffffffffffff1661102957506000610e71565b600854604080517f70a0823100000000000000000000000000000000000000000000000000000000815260006004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b15801561109b57600080fd5b505afa1580156110af573d6000803e3d6000fd5b505050506040513d60208110156110c557600080fd5b5051905090565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6110f861361b565b73ffffffffffffffffffffffffffffffffffffffff1661111661352d565b73ffffffffffffffffffffffffffffffffffffffff161480611171575061113b61361b565b73ffffffffffffffffffffffffffffffffffffffff1661115961243a565b73ffffffffffffffffffffffffffffffffffffffff16145b6111dc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d547501000000000000000000000000000000000000000000900460ff1680611204575080155b611259576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260438152602001806149ae6043913960600191505060405180910390fd5b600e55600d80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055565b6000600e5443116112f857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f476f206177617920626f74000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000611305836064613766565b9050600061131e600b548561376690919063ffffffff16565b600d549091506000906113fd9073ffffffffffffffffffffffffffffffffffffffff1661134d57600a546113f6565b600d5473ffffffffffffffffffffffffffffffffffffffff166352ff02a16113758a8a612420565b600a546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b1580156113c957600080fd5b505afa1580156113dd573d6000803e3d6000fd5b505050506040513d60208110156113f357600080fd5b50515b8690613766565b905061140987826137a8565b600c5473ffffffffffffffffffffffffffffffffffffffff16156114bb57600c54604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff898116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156114a257600080fd5b505af11580156114b6573d6000803e3d6000fd5b505050505b6010546114e090889073ffffffffffffffffffffffffffffffffffffffff16856138f2565b506114ec8730846138f2565b5061150d87876115088661150287818c896135d9565b906135d9565b6138f2565b979650505050505050565b600f5481565b60055460ff1690565b600d547501000000000000000000000000000000000000000000900460ff1681565b6000610e8861155661361b565b846115a4856001600061156761361b565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c168152925290205490613565565b61361f565b6115b161361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff90811691161461163f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611649828261398e565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526011602052604081205461167b921683613b02565b5050565b61169061168a61361b565b826137a8565b50565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b60085473ffffffffffffffffffffffffffffffffffffffff161561173457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f506169722068617320616c7265616479206265656e2063726561746564000000604482015290519081900360640190fd5b60095473ffffffffffffffffffffffffffffffffffffffff1615801590611772575060075473ffffffffffffffffffffffffffffffffffffffff1615155b6117c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614b376023913960400191505060405180910390fd5b600954600754604080517fad5c4648000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169363c9c6539693169163ad5c4648916004808301926020929190829003018186803b15801561183c57600080fd5b505afa158015611850573d6000803e3d6000fd5b505050506040513d602081101561186657600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301523060248301525160448083019260209291908290030181600087803b1580156118da57600080fd5b505af11580156118ee573d6000803e3d6000fd5b505050506040513d602081101561190457600080fd5b5051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61195461361b565b73ffffffffffffffffffffffffffffffffffffffff1661197261352d565b73ffffffffffffffffffffffffffffffffffffffff1614806119cd575061199761361b565b73ffffffffffffffffffffffffffffffffffffffff166119b561243a565b73ffffffffffffffffffffffffffffffffffffffff16145b611a3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116301415611abd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f5365636f6e6461727920746f6b656e2063616e6e6f7420626520697473656c66604482015290519081900360640190fd5b600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff9081166000908152601160205260409020541690565b60095473ffffffffffffffffffffffffffffffffffffffff1681565b6116903382613ce8565b600b5481565b611b6361361b565b73ffffffffffffffffffffffffffffffffffffffff16611b8161352d565b73ffffffffffffffffffffffffffffffffffffffff161480611bdc5750611ba661361b565b73ffffffffffffffffffffffffffffffffffffffff16611bc461243a565b73ffffffffffffffffffffffffffffffffffffffff16145b611c4757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b80611c9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061490a602c913960400191505060405180910390fd5b600b55565b611caa61361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff908116911614611d3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60136020526000908152604090205463ffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b611dc761361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff908116911614611e5557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b611ed161361b565b60065473ffffffffffffffffffffffffffffffffffffffff908116911614611f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061495c6026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611fb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180614982602c913960400191505060405180910390fd5b60065460405173ffffffffffffffffffffffffffffffffffffffff8084169216907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000438210612098576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806148406027913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526013602052604090205463ffffffff16806120d3576000915050610e8c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811685529252909120541683106121985773ffffffffffffffffffffffffffffffffffffffff841660009081526012602090815260408083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490940163ffffffff16835292905220600101549050610e8c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832083805290915290205463ffffffff168310156121e0576000915050610e8c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82015b8163ffffffff168163ffffffff1611156122c457600282820363ffffffff160481036122306147e3565b5073ffffffffffffffffffffffffffffffffffffffff8716600090815260126020908152604080832063ffffffff80861685529083529281902081518083019092528054909316808252600190930154918101919091529087141561229f57602001519450610e8c9350505050565b805163ffffffff168711156122b6578193506122bd565b6001820392505b5050612206565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff9094168352929052206001015491505092915050565b60105473ffffffffffffffffffffffffffffffffffffffff1681565b60146020526000908152604090205481565b61233e61361b565b60065473ffffffffffffffffffffffffffffffffffffffff9081169116146123b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061495c6026913960400191505060405180910390fd5b60065460405160009173ffffffffffffffffffffffffffffffffffffffff16907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6908390a3600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6000823b80156124305782612432565b835b949350505050565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1690565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e695780601f10610e3e57610100808354040283529160200191610e69565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b6000610e8861250361361b565b846115a485604051806060016040528060258152602001614ba9602591396001600061252d61361b565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d16815292529020549190613daf565b6000600e5443116125dd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f476f206177617920626f74000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006125ea836064613766565b90506000612603600b548561376690919063ffffffff16565b600d5490915060009061265a9073ffffffffffffffffffffffffffffffffffffffff1661263257600a546113f6565b600d5473ffffffffffffffffffffffffffffffffffffffff166352ff02a1611375338a612420565b905061266633826137a8565b600c5473ffffffffffffffffffffffffffffffffffffffff161561271857600c54604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff898116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156126ff57600080fd5b505af1158015612713573d6000803e3d6000fd5b505050505b60105461273b9073ffffffffffffffffffffffffffffffffffffffff1684613e60565b506127463083613e60565b506127608661275b8561150286818b886135d9565b613e60565b9695505050505050565b600d5474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff811660009081526013602052604081205463ffffffff16806127c3576000612820565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011684529091529020600101545b9392505050565b600a5481565b33803b801561289d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736f7272792068756d616e73206f6e6c79000000000000000000000000000000604482015290519081900360640190fd5b60006128a830611d97565b60085490915073ffffffffffffffffffffffffffffffffffffffff16612919576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614a656025913960400191505060405180910390fd5b60075473ffffffffffffffffffffffffffffffffffffffff16612987576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806148e36027913960400191505060405180910390fd5b670de0b6b3a76400008110156129e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180614bce602e913960400191505060405180910390fd5b674563918244f400006129fa33611d97565b1015612a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180614b5a6029913960400191505060405180910390fd5b600d5460009074010000000000000000000000000000000000000000900460ff1615612a9157612a82826032613766565b9050612a8e82826135d9565b91505b6000612a9e836002613766565b90506000612aac84836135d9565b905047612ab883613e74565b6000612ac447836135d9565b9050612ad08382614073565b604080518481526020810183905281517ff92f4324b27920d4c25c8cf2a2b751ba52ff2f7adc4a500e0cbbda2e1ca4b1fd929181900390910190a18415612b445784612b1b30611d97565b10612b3057612b2a338661256b565b50612b44565b612b4233612b3d30611d97565b61256b565b505b505042600f55505050505050565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866612b7d610dbf565b80519060200120612b8c614328565b60408051602080820195909552808201939093526060830191909152306080808401919091528151808403909101815260a0830182528051908401207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c084015273ffffffffffffffffffffffffffffffffffffffff8b1660e084015261010083018a90526101208084018a905282518085039091018152610140840183528051908501207f19010000000000000000000000000000000000000000000000000000000000006101608501526101628401829052610182808501829052835180860390910181526101a285018085528151918701919091206000918290526101c2860180865281905260ff8b166101e287015261020286018a905261022286018990529351929650909492939092600192610242808401937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301929081900390910190855afa158015612d05573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612d9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614a196026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604090208054600181019091558914612e21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180614b156022913960400191505060405180910390fd5b87421115612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614b836026913960400191505060405180910390fd5b612e84818b613ce8565b505050505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b612ed161361b565b73ffffffffffffffffffffffffffffffffffffffff16612eef61352d565b73ffffffffffffffffffffffffffffffffffffffff161480612f4a5750612f1461361b565b73ffffffffffffffffffffffffffffffffffffffff16612f3261243a565b73ffffffffffffffffffffffffffffffffffffffff16145b612fb557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61300761361b565b73ffffffffffffffffffffffffffffffffffffffff1661302561352d565b73ffffffffffffffffffffffffffffffffffffffff161480613080575061304a61361b565b73ffffffffffffffffffffffffffffffffffffffff1661306861243a565b73ffffffffffffffffffffffffffffffffffffffff16145b6130eb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517f7bde943d0d8a1a1601907e18682e3f76fbab7224d402beee11d35b272f5a07009181900360200190a150565b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b61319061361b565b73ffffffffffffffffffffffffffffffffffffffff166131ae61352d565b73ffffffffffffffffffffffffffffffffffffffff16148061320957506131d361361b565b73ffffffffffffffffffffffffffffffffffffffff166131f161243a565b73ffffffffffffffffffffffffffffffffffffffff16145b61327457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216158015906132ae575073ffffffffffffffffffffffffffffffffffffffff811615155b613303576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614ad06021913960400191505060405180910390fd5b6009805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556007805484841692169190911790556008541661167b5761167b6116af565b60126020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b61339b61361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff90811691161461342957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806148676026913960400191505060405180910390fd5b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b60065473ffffffffffffffffffffffffffffffffffffffff1690565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b60008282018381101561282057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061282083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613daf565b3390565b73ffffffffffffffffffffffffffffffffffffffff831661368b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614af16024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166136f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061488d6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061282083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061432c565b73ffffffffffffffffffffffffffffffffffffffff8216613814576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614a8a6021913960400191505060405180910390fd5b61382082600083613ce3565b61386a8160405180606001604052806022815260200161481e6022913973ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020549190613daf565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205560025461389d90826135d9565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60006138ff8484846143ab565b6139848461390b61361b565b6115a4856040518060600160405280602881526020016149f16028913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081209061395661361b565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190613daf565b5060019392505050565b73ffffffffffffffffffffffffffffffffffffffff8216613a1057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b613a1c60008383613ce3565b6002546902c0bb3dd30c4e20000090613a359083613565565b1115613a5f57600254613a53906902c0bb3dd30c4e200000906135d9565b905080613a5f5761167b565b600254613a6c9082613565565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054613a9f9082613565565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015613b3e5750600081115b15613ce35773ffffffffffffffffffffffffffffffffffffffff831615613c155773ffffffffffffffffffffffffffffffffffffffff831660009081526013602052604081205463ffffffff169081613b98576000613bf5565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87011684529091529020600101545b90506000613c0382856135d9565b9050613c118684848461457b565b5050505b73ffffffffffffffffffffffffffffffffffffffff821615613ce35773ffffffffffffffffffffffffffffffffffffffff821660009081526013602052604081205463ffffffff169081613c6a576000613cc7565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87011684529091529020600101545b90506000613cd58285613565565b9050612e898584848461457b565b505050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526011602052604081205490911690613d1c84611d97565b73ffffffffffffffffffffffffffffffffffffffff85811660008181526011602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4613da9828483613b02565b50505050565b60008184841115613e58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613e1d578181015183820152602001613e05565b50505050905090810190601f168015613e4a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000610e88613e6d61361b565b84846143ab565b60408051600280825260608083018452926020830190803683370190505090503081600081518110613ea257fe5b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152600754604080517fad5c46480000000000000000000000000000000000000000000000000000000081529051919093169263ad5c4648926004808301939192829003018186803b158015613f1c57600080fd5b505afa158015613f30573d6000803e3d6000fd5b505050506040513d6020811015613f4657600080fd5b5051815182906001908110613f5757fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092010152600754613f8a913091168461361f565b6007546040517f791ac947000000000000000000000000000000000000000000000000000000008152600481018481526000602483018190523060648401819052426084850181905260a060448601908152875160a4870152875173ffffffffffffffffffffffffffffffffffffffff9097169663791ac947968a968a9594939092909160c40190602080880191028083838b5b8381101561403657818101518382015260200161401e565b505050509050019650505050505050600060405180830381600087803b15801561405f57600080fd5b505af1158015612e89573d6000803e3d6000fd5b60075461409890309073ffffffffffffffffffffffffffffffffffffffff168461361f565b600754604080517ff305d719000000000000000000000000000000000000000000000000000000008152306004820181905260248201869052600060448301819052606483015260848201524260a4820152905173ffffffffffffffffffffffffffffffffffffffff9092169163f305d71991849160c480830192606092919082900301818588803b15801561412d57600080fd5b505af1158015614141573d6000803e3d6000fd5b50505050506040513d606081101561415857600080fd5b5050600854604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b1580156141cb57600080fd5b505afa1580156141df573d6000803e3d6000fd5b505050506040513d60208110156141f557600080fd5b505190508015613ce357600854604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815260006004820181905260248201859052915173ffffffffffffffffffffffffffffffffffffffff9093169263a9059cbb92604480840193602093929083900390910190829087803b15801561427d57600080fd5b505af1158015614291573d6000803e3d6000fd5b505050506040513d60208110156142a757600080fd5b505060105460405173ffffffffffffffffffffffffffffffffffffffff909116904780156108fc02916000818181858888f193505050501580156142ef573d6000803e3d6000fd5b506040805182815290517f90f0ebc9cbe15b2466dcac46571c49feee27e3385c5ab60c348cc4ebcb91251f9181900360200190a1505050565b4690565b60008183614395576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315613e1d578181015183820152602001613e05565b5060008385816143a157fe5b0495945050505050565b73ffffffffffffffffffffffffffffffffffffffff8316614417576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614aab6025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614483576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806147fb6023913960400191505060405180910390fd5b61448e838383613ce3565b6144d8816040518060600160405280602681526020016149366026913973ffffffffffffffffffffffffffffffffffffffff86166000908152602081905260409020549190613daf565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526020819052604080822093909355908416815220546145149082613565565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600061459f436040518060600160405280603481526020016148af6034913961476b565b905060008463ffffffff16118015614613575073ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8901811685529252909120548282169116145b1561467b5773ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89011684529091529020600101829055614714565b60408051808201825263ffffffff8084168252602080830186815273ffffffffffffffffffffffffffffffffffffffff8a166000818152601284528681208b861682528452868120955186549086167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000918216178755925160019687015590815260139092529390208054928801909116919092161790555b6040805184815260208101849052815173ffffffffffffffffffffffffffffffffffffffff8816927fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724928290030190a25050505050565b60008164010000000084106147db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315613e1d578181015183820152602001613e05565b509192915050565b60408051808201909152600080825260208201529056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365424f4f423a3a6765745072696f72566f7465733a206e6f74207965742064657465726d696e65644f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f2061646472657373424f4f423a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473556e69737761705632526f75746572206e6f742073657420696e20636f6e747261637420796574426f6f3a205f6c697175696469747944697669736f72206d75737420626520626967676572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636541646d696e6973747261626c653a2063616c6c6572206973206e6f74207468652061646d696e41646d696e6973747261626c653a206e65772061646d696e20697320746865207a65726f206164647265737350617573652068617320616c7265616479206265656e2075736564206f6e63652e2049662064697361626c696e672070617573652073657420626c6f636b20746f203045524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365424f4f423a3a64656c656761746542795369673a20696e76616c6964207369676e6174757265426f6f3a206275726e44697669736f72206d75737420626520626967676572207468616e2030556e6973776170563250616972206e6f742073657420696e20636f6e74726163742079657445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f2061646472657373556e6973776170206164647265737365732063616e6e6f7420626520656d70747945524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373424f4f423a3a64656c656761746542795369673a20696e76616c6964206e6f6e6365556e6973776170206164647265737365732068617665206e6f74206265656e20736574596f75206d757374206f776e206174206c656173742035204242726120746f2063616c6c206c6f636b424f4f423a3a64656c656761746542795369673a207369676e6174757265206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f4d696e696d756d206f6620312042425241206265666f72652077652063616e206c6f636b206c6971756964697479a2646970667358221220744779ed20b3324e952eed3ca0630e2716c49fd8329057ee15c1a74e6a2d089a64736f6c634300060c003300000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000028

Deployed Bytecode

0x60806040526004361061034e5760003560e01c806370a08231116101bb578063abf05f5d116100f7578063e19c175d11610095578063f1127ed81161006f578063f1127ed814610ce9578063f2fde38b14610d55578063f851a44014610d95578063faa0a26414610daa5761038b565b8063e19c175d14610c4c578063e7a324dc14610c8c578063ef4a64d414610ca15761038b565b8063bb2f7199116100d1578063bb2f719914610b62578063c3cda52014610b77578063dd62ed3e14610bd8578063e157ee2e14610c205761038b565b8063abf05f5d14610af8578063b4b5ea5714610b0d578063ba52c8b714610b4d5761038b565b80638bad0c0a1161016457806395d89b411161013e57806395d89b4114610a425780639a49f57114610a57578063a457c2d714610a6c578063a9059cbb14610ab25761038b565b80638bad0c0a146109d05780638cf5bf7c146109e55780638da5cb5b14610a2d5761038b565b8063782d6fe111610195578063782d6fe1146109355780637b2798d71461097b5780637ecebe00146109905761038b565b806370a08231146108a0578063715018a6146108e057806375829def146108f55761038b565b8063395093511161028a578063587cde1e1161023357806362d1d1dc1161020d57806362d1d1dc146107c857806367a4793e146107dd5780636ebb64a2146108075780636fcfff45146108475761038b565b8063587cde1e1461073357806359d0f713146107735780635c19a95c146107885761038b565b806349bd5a5e1161026457806349bd5a5e146106c95780634a131672146106de578063547c0e77146106f35761038b565b8063395093511461061357806340c10f191461065957806342966c681461069f5761038b565b80631fc53a43116102f757806323b872dd116102d157806323b872dd1461056e5780632aaab8fa146105be578063313ce567146105d3578063323be1c5146105fe5761038b565b80631fc53a431461051a57806320606b701461052f578063216c394d146105445761038b565b80631694505e116103285780631694505e1461049b57806318160ddd146104d9578063189d165e146104ee5761038b565b806306fdde0314610390578063095ea7b31461041a5780630fd8ee17146104745761038b565b3661038b5760408051348152905133917f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874919081900360200190a2005b600080fd5b34801561039c57600080fd5b506103a5610dbf565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103df5781810151838201526020016103c7565b50505050905090810190601f16801561040c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561042657600080fd5b506104606004803603604081101561043d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610e74565b604080519115158252519081900360200190f35b34801561048057600080fd5b50610489610e92565b60408051918252519081900360200190f35b3480156104a757600080fd5b506104b0610e98565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156104e557600080fd5b50610489610eb4565b3480156104fa57600080fd5b506105186004803603602081101561051157600080fd5b5035610eba565b005b34801561052657600080fd5b50610489611001565b34801561053b57600080fd5b506104896110cc565b34801561055057600080fd5b506105186004803603602081101561056757600080fd5b50356110f0565b34801561057a57600080fd5b506104606004803603606081101561059157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611286565b3480156105ca57600080fd5b50610489611518565b3480156105df57600080fd5b506105e861151e565b6040805160ff9092168252519081900360200190f35b34801561060a57600080fd5b50610460611527565b34801561061f57600080fd5b506104606004803603604081101561063657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611549565b34801561066557600080fd5b506105186004803603604081101561067c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356115a9565b3480156106ab57600080fd5b50610518600480360360208110156106c257600080fd5b503561167f565b3480156106d557600080fd5b506104b0611693565b3480156106ea57600080fd5b506105186116af565b3480156106ff57600080fd5b506105186004803603602081101561071657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661194c565b34801561073f57600080fd5b506104b06004803603602081101561075657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611b04565b34801561077f57600080fd5b506104b0611b2f565b34801561079457600080fd5b50610518600480360360208110156107ab57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611b4b565b3480156107d457600080fd5b50610489611b55565b3480156107e957600080fd5b506105186004803603602081101561080057600080fd5b5035611b5b565b34801561081357600080fd5b506105186004803603602081101561082a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ca2565b34801561085357600080fd5b506108876004803603602081101561086a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d7f565b6040805163ffffffff9092168252519081900360200190f35b3480156108ac57600080fd5b50610489600480360360208110156108c357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d97565b3480156108ec57600080fd5b50610518611dbf565b34801561090157600080fd5b506105186004803603602081101561091857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ec9565b34801561094157600080fd5b506104896004803603604081101561095857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561203e565b34801561098757600080fd5b506104b0612308565b34801561099c57600080fd5b50610489600480360360208110156109b357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612324565b3480156109dc57600080fd5b50610518612336565b3480156109f157600080fd5b506104b060048036036040811015610a0857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612420565b348015610a3957600080fd5b506104b061243a565b348015610a4e57600080fd5b506103a561245b565b348015610a6357600080fd5b506104b06124da565b348015610a7857600080fd5b5061046060048036036040811015610a8f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356124f6565b348015610abe57600080fd5b5061046060048036036040811015610ad557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561256b565b348015610b0457600080fd5b5061046061276a565b348015610b1957600080fd5b5061048960048036036020811015610b3057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661278b565b348015610b5957600080fd5b50610489612827565b348015610b6e57600080fd5b5061051861282d565b348015610b8357600080fd5b50610518600480360360c0811015610b9a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060408101359060ff6060820135169060808101359060a00135612b52565b348015610be457600080fd5b5061048960048036036040811015610bfb57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612e91565b348015610c2c57600080fd5b5061051860048036036020811015610c4357600080fd5b50351515612ec9565b348015610c5857600080fd5b5061051860048036036020811015610c6f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612fff565b348015610c9857600080fd5b50610489613164565b348015610cad57600080fd5b5061051860048036036040811015610cc457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613188565b348015610cf557600080fd5b50610d3560048036036040811015610d0c57600080fd5b50803573ffffffffffffffffffffffffffffffffffffffff16906020013563ffffffff16613366565b6040805163ffffffff909316835260208301919091528051918290030190f35b348015610d6157600080fd5b5061051860048036036020811015610d7857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613393565b348015610da157600080fd5b506104b061352d565b348015610db657600080fd5b506104b0613549565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e695780601f10610e3e57610100808354040283529160200191610e69565b820191906000526020600020905b815481529060010190602001808311610e4c57829003601f168201915b505050505090505b90565b6000610e88610e8161361b565b848461361f565b5060015b92915050565b600e5481565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b60025490565b610ec261361b565b73ffffffffffffffffffffffffffffffffffffffff16610ee061352d565b73ffffffffffffffffffffffffffffffffffffffff161480610f3b5750610f0561361b565b73ffffffffffffffffffffffffffffffffffffffff16610f2361243a565b73ffffffffffffffffffffffffffffffffffffffff16145b610fa657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b80610ffc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614a3f6026913960400191505060405180910390fd5b600a55565b60085460009073ffffffffffffffffffffffffffffffffffffffff1661102957506000610e71565b600854604080517f70a0823100000000000000000000000000000000000000000000000000000000815260006004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b15801561109b57600080fd5b505afa1580156110af573d6000803e3d6000fd5b505050506040513d60208110156110c557600080fd5b5051905090565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6110f861361b565b73ffffffffffffffffffffffffffffffffffffffff1661111661352d565b73ffffffffffffffffffffffffffffffffffffffff161480611171575061113b61361b565b73ffffffffffffffffffffffffffffffffffffffff1661115961243a565b73ffffffffffffffffffffffffffffffffffffffff16145b6111dc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d547501000000000000000000000000000000000000000000900460ff1680611204575080155b611259576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260438152602001806149ae6043913960600191505060405180910390fd5b600e55600d80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055565b6000600e5443116112f857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f476f206177617920626f74000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000611305836064613766565b9050600061131e600b548561376690919063ffffffff16565b600d549091506000906113fd9073ffffffffffffffffffffffffffffffffffffffff1661134d57600a546113f6565b600d5473ffffffffffffffffffffffffffffffffffffffff166352ff02a16113758a8a612420565b600a546040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b1580156113c957600080fd5b505afa1580156113dd573d6000803e3d6000fd5b505050506040513d60208110156113f357600080fd5b50515b8690613766565b905061140987826137a8565b600c5473ffffffffffffffffffffffffffffffffffffffff16156114bb57600c54604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff898116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156114a257600080fd5b505af11580156114b6573d6000803e3d6000fd5b505050505b6010546114e090889073ffffffffffffffffffffffffffffffffffffffff16856138f2565b506114ec8730846138f2565b5061150d87876115088661150287818c896135d9565b906135d9565b6138f2565b979650505050505050565b600f5481565b60055460ff1690565b600d547501000000000000000000000000000000000000000000900460ff1681565b6000610e8861155661361b565b846115a4856001600061156761361b565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c168152925290205490613565565b61361f565b6115b161361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff90811691161461163f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611649828261398e565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526011602052604081205461167b921683613b02565b5050565b61169061168a61361b565b826137a8565b50565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b60085473ffffffffffffffffffffffffffffffffffffffff161561173457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f506169722068617320616c7265616479206265656e2063726561746564000000604482015290519081900360640190fd5b60095473ffffffffffffffffffffffffffffffffffffffff1615801590611772575060075473ffffffffffffffffffffffffffffffffffffffff1615155b6117c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180614b376023913960400191505060405180910390fd5b600954600754604080517fad5c4648000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169363c9c6539693169163ad5c4648916004808301926020929190829003018186803b15801561183c57600080fd5b505afa158015611850573d6000803e3d6000fd5b505050506040513d602081101561186657600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301523060248301525160448083019260209291908290030181600087803b1580156118da57600080fd5b505af11580156118ee573d6000803e3d6000fd5b505050506040513d602081101561190457600080fd5b5051600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61195461361b565b73ffffffffffffffffffffffffffffffffffffffff1661197261352d565b73ffffffffffffffffffffffffffffffffffffffff1614806119cd575061199761361b565b73ffffffffffffffffffffffffffffffffffffffff166119b561243a565b73ffffffffffffffffffffffffffffffffffffffff16145b611a3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116301415611abd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f5365636f6e6461727920746f6b656e2063616e6e6f7420626520697473656c66604482015290519081900360640190fd5b600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff9081166000908152601160205260409020541690565b60095473ffffffffffffffffffffffffffffffffffffffff1681565b6116903382613ce8565b600b5481565b611b6361361b565b73ffffffffffffffffffffffffffffffffffffffff16611b8161352d565b73ffffffffffffffffffffffffffffffffffffffff161480611bdc5750611ba661361b565b73ffffffffffffffffffffffffffffffffffffffff16611bc461243a565b73ffffffffffffffffffffffffffffffffffffffff16145b611c4757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b80611c9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061490a602c913960400191505060405180910390fd5b600b55565b611caa61361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff908116911614611d3857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60136020526000908152604090205463ffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b611dc761361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff908116911614611e5557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600554604051600091610100900473ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b611ed161361b565b60065473ffffffffffffffffffffffffffffffffffffffff908116911614611f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061495c6026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611fb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180614982602c913960400191505060405180910390fd5b60065460405173ffffffffffffffffffffffffffffffffffffffff8084169216907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec690600090a3600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000438210612098576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806148406027913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526013602052604090205463ffffffff16806120d3576000915050610e8c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811685529252909120541683106121985773ffffffffffffffffffffffffffffffffffffffff841660009081526012602090815260408083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490940163ffffffff16835292905220600101549050610e8c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832083805290915290205463ffffffff168310156121e0576000915050610e8c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82015b8163ffffffff168163ffffffff1611156122c457600282820363ffffffff160481036122306147e3565b5073ffffffffffffffffffffffffffffffffffffffff8716600090815260126020908152604080832063ffffffff80861685529083529281902081518083019092528054909316808252600190930154918101919091529087141561229f57602001519450610e8c9350505050565b805163ffffffff168711156122b6578193506122bd565b6001820392505b5050612206565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff9094168352929052206001015491505092915050565b60105473ffffffffffffffffffffffffffffffffffffffff1681565b60146020526000908152604090205481565b61233e61361b565b60065473ffffffffffffffffffffffffffffffffffffffff9081169116146123b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061495c6026913960400191505060405180910390fd5b60065460405160009173ffffffffffffffffffffffffffffffffffffffff16907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6908390a3600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6000823b80156124305782612432565b835b949350505050565b600554610100900473ffffffffffffffffffffffffffffffffffffffff1690565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e695780601f10610e3e57610100808354040283529160200191610e69565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b6000610e8861250361361b565b846115a485604051806060016040528060258152602001614ba9602591396001600061252d61361b565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d16815292529020549190613daf565b6000600e5443116125dd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f476f206177617920626f74000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006125ea836064613766565b90506000612603600b548561376690919063ffffffff16565b600d5490915060009061265a9073ffffffffffffffffffffffffffffffffffffffff1661263257600a546113f6565b600d5473ffffffffffffffffffffffffffffffffffffffff166352ff02a1611375338a612420565b905061266633826137a8565b600c5473ffffffffffffffffffffffffffffffffffffffff161561271857600c54604080517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff898116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156126ff57600080fd5b505af1158015612713573d6000803e3d6000fd5b505050505b60105461273b9073ffffffffffffffffffffffffffffffffffffffff1684613e60565b506127463083613e60565b506127608661275b8561150286818b886135d9565b613e60565b9695505050505050565b600d5474010000000000000000000000000000000000000000900460ff1681565b73ffffffffffffffffffffffffffffffffffffffff811660009081526013602052604081205463ffffffff16806127c3576000612820565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011684529091529020600101545b9392505050565b600a5481565b33803b801561289d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736f7272792068756d616e73206f6e6c79000000000000000000000000000000604482015290519081900360640190fd5b60006128a830611d97565b60085490915073ffffffffffffffffffffffffffffffffffffffff16612919576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614a656025913960400191505060405180910390fd5b60075473ffffffffffffffffffffffffffffffffffffffff16612987576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806148e36027913960400191505060405180910390fd5b670de0b6b3a76400008110156129e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180614bce602e913960400191505060405180910390fd5b674563918244f400006129fa33611d97565b1015612a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180614b5a6029913960400191505060405180910390fd5b600d5460009074010000000000000000000000000000000000000000900460ff1615612a9157612a82826032613766565b9050612a8e82826135d9565b91505b6000612a9e836002613766565b90506000612aac84836135d9565b905047612ab883613e74565b6000612ac447836135d9565b9050612ad08382614073565b604080518481526020810183905281517ff92f4324b27920d4c25c8cf2a2b751ba52ff2f7adc4a500e0cbbda2e1ca4b1fd929181900390910190a18415612b445784612b1b30611d97565b10612b3057612b2a338661256b565b50612b44565b612b4233612b3d30611d97565b61256b565b505b505042600f55505050505050565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866612b7d610dbf565b80519060200120612b8c614328565b60408051602080820195909552808201939093526060830191909152306080808401919091528151808403909101815260a0830182528051908401207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c084015273ffffffffffffffffffffffffffffffffffffffff8b1660e084015261010083018a90526101208084018a905282518085039091018152610140840183528051908501207f19010000000000000000000000000000000000000000000000000000000000006101608501526101628401829052610182808501829052835180860390910181526101a285018085528151918701919091206000918290526101c2860180865281905260ff8b166101e287015261020286018a905261022286018990529351929650909492939092600192610242808401937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301929081900390910190855afa158015612d05573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612d9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614a196026913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526014602052604090208054600181019091558914612e21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180614b156022913960400191505060405180910390fd5b87421115612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614b836026913960400191505060405180910390fd5b612e84818b613ce8565b505050505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b612ed161361b565b73ffffffffffffffffffffffffffffffffffffffff16612eef61352d565b73ffffffffffffffffffffffffffffffffffffffff161480612f4a5750612f1461361b565b73ffffffffffffffffffffffffffffffffffffffff16612f3261243a565b73ffffffffffffffffffffffffffffffffffffffff16145b612fb557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61300761361b565b73ffffffffffffffffffffffffffffffffffffffff1661302561352d565b73ffffffffffffffffffffffffffffffffffffffff161480613080575061304a61361b565b73ffffffffffffffffffffffffffffffffffffffff1661306861243a565b73ffffffffffffffffffffffffffffffffffffffff16145b6130eb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b600d805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517f7bde943d0d8a1a1601907e18682e3f76fbab7224d402beee11d35b272f5a07009181900360200190a150565b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b61319061361b565b73ffffffffffffffffffffffffffffffffffffffff166131ae61352d565b73ffffffffffffffffffffffffffffffffffffffff16148061320957506131d361361b565b73ffffffffffffffffffffffffffffffffffffffff166131f161243a565b73ffffffffffffffffffffffffffffffffffffffff16145b61327457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216158015906132ae575073ffffffffffffffffffffffffffffffffffffffff811615155b613303576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614ad06021913960400191505060405180910390fd5b6009805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556007805484841692169190911790556008541661167b5761167b6116af565b60126020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b61339b61361b565b600554610100900473ffffffffffffffffffffffffffffffffffffffff90811691161461342957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806148676026913960400191505060405180910390fd5b60055460405173ffffffffffffffffffffffffffffffffffffffff80841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36005805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b60065473ffffffffffffffffffffffffffffffffffffffff1690565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b60008282018381101561282057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061282083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613daf565b3390565b73ffffffffffffffffffffffffffffffffffffffff831661368b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614af16024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166136f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061488d6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061282083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061432c565b73ffffffffffffffffffffffffffffffffffffffff8216613814576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614a8a6021913960400191505060405180910390fd5b61382082600083613ce3565b61386a8160405180606001604052806022815260200161481e6022913973ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020549190613daf565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205560025461389d90826135d9565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60006138ff8484846143ab565b6139848461390b61361b565b6115a4856040518060600160405280602881526020016149f16028913973ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081209061395661361b565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190613daf565b5060019392505050565b73ffffffffffffffffffffffffffffffffffffffff8216613a1057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b613a1c60008383613ce3565b6002546902c0bb3dd30c4e20000090613a359083613565565b1115613a5f57600254613a53906902c0bb3dd30c4e200000906135d9565b905080613a5f5761167b565b600254613a6c9082613565565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054613a9f9082613565565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015613b3e5750600081115b15613ce35773ffffffffffffffffffffffffffffffffffffffff831615613c155773ffffffffffffffffffffffffffffffffffffffff831660009081526013602052604081205463ffffffff169081613b98576000613bf5565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87011684529091529020600101545b90506000613c0382856135d9565b9050613c118684848461457b565b5050505b73ffffffffffffffffffffffffffffffffffffffff821615613ce35773ffffffffffffffffffffffffffffffffffffffff821660009081526013602052604081205463ffffffff169081613c6a576000613cc7565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87011684529091529020600101545b90506000613cd58285613565565b9050612e898584848461457b565b505050565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526011602052604081205490911690613d1c84611d97565b73ffffffffffffffffffffffffffffffffffffffff85811660008181526011602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4613da9828483613b02565b50505050565b60008184841115613e58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613e1d578181015183820152602001613e05565b50505050905090810190601f168015613e4a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000610e88613e6d61361b565b84846143ab565b60408051600280825260608083018452926020830190803683370190505090503081600081518110613ea257fe5b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152600754604080517fad5c46480000000000000000000000000000000000000000000000000000000081529051919093169263ad5c4648926004808301939192829003018186803b158015613f1c57600080fd5b505afa158015613f30573d6000803e3d6000fd5b505050506040513d6020811015613f4657600080fd5b5051815182906001908110613f5757fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092010152600754613f8a913091168461361f565b6007546040517f791ac947000000000000000000000000000000000000000000000000000000008152600481018481526000602483018190523060648401819052426084850181905260a060448601908152875160a4870152875173ffffffffffffffffffffffffffffffffffffffff9097169663791ac947968a968a9594939092909160c40190602080880191028083838b5b8381101561403657818101518382015260200161401e565b505050509050019650505050505050600060405180830381600087803b15801561405f57600080fd5b505af1158015612e89573d6000803e3d6000fd5b60075461409890309073ffffffffffffffffffffffffffffffffffffffff168461361f565b600754604080517ff305d719000000000000000000000000000000000000000000000000000000008152306004820181905260248201869052600060448301819052606483015260848201524260a4820152905173ffffffffffffffffffffffffffffffffffffffff9092169163f305d71991849160c480830192606092919082900301818588803b15801561412d57600080fd5b505af1158015614141573d6000803e3d6000fd5b50505050506040513d606081101561415857600080fd5b5050600854604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b1580156141cb57600080fd5b505afa1580156141df573d6000803e3d6000fd5b505050506040513d60208110156141f557600080fd5b505190508015613ce357600854604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815260006004820181905260248201859052915173ffffffffffffffffffffffffffffffffffffffff9093169263a9059cbb92604480840193602093929083900390910190829087803b15801561427d57600080fd5b505af1158015614291573d6000803e3d6000fd5b505050506040513d60208110156142a757600080fd5b505060105460405173ffffffffffffffffffffffffffffffffffffffff909116904780156108fc02916000818181858888f193505050501580156142ef573d6000803e3d6000fd5b506040805182815290517f90f0ebc9cbe15b2466dcac46571c49feee27e3385c5ab60c348cc4ebcb91251f9181900360200190a1505050565b4690565b60008183614395576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315613e1d578181015183820152602001613e05565b5060008385816143a157fe5b0495945050505050565b73ffffffffffffffffffffffffffffffffffffffff8316614417576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614aab6025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614483576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806147fb6023913960400191505060405180910390fd5b61448e838383613ce3565b6144d8816040518060600160405280602681526020016149366026913973ffffffffffffffffffffffffffffffffffffffff86166000908152602081905260409020549190613daf565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526020819052604080822093909355908416815220546145149082613565565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600061459f436040518060600160405280603481526020016148af6034913961476b565b905060008463ffffffff16118015614613575073ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8901811685529252909120548282169116145b1561467b5773ffffffffffffffffffffffffffffffffffffffff8516600090815260126020908152604080832063ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89011684529091529020600101829055614714565b60408051808201825263ffffffff8084168252602080830186815273ffffffffffffffffffffffffffffffffffffffff8a166000818152601284528681208b861682528452868120955186549086167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000918216178755925160019687015590815260139092529390208054928801909116919092161790555b6040805184815260208101849052815173ffffffffffffffffffffffffffffffffffffffff8816927fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724928290030190a25050505050565b60008164010000000084106147db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315613e1d578181015183820152602001613e05565b509192915050565b60408051808201909152600080825260208201529056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365424f4f423a3a6765745072696f72566f7465733a206e6f74207965742064657465726d696e65644f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f2061646472657373424f4f423a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473556e69737761705632526f75746572206e6f742073657420696e20636f6e747261637420796574426f6f3a205f6c697175696469747944697669736f72206d75737420626520626967676572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636541646d696e6973747261626c653a2063616c6c6572206973206e6f74207468652061646d696e41646d696e6973747261626c653a206e65772061646d696e20697320746865207a65726f206164647265737350617573652068617320616c7265616479206265656e2075736564206f6e63652e2049662064697361626c696e672070617573652073657420626c6f636b20746f203045524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365424f4f423a3a64656c656761746542795369673a20696e76616c6964207369676e6174757265426f6f3a206275726e44697669736f72206d75737420626520626967676572207468616e2030556e6973776170563250616972206e6f742073657420696e20636f6e74726163742079657445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f2061646472657373556e6973776170206164647265737365732063616e6e6f7420626520656d70747945524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373424f4f423a3a64656c656761746542795369673a20696e76616c6964206e6f6e6365556e6973776170206164647265737365732068617665206e6f74206265656e20736574596f75206d757374206f776e206174206c656173742035204242726120746f2063616c6c206c6f636b424f4f423a3a64656c656761746542795369673a207369676e6174757265206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f4d696e696d756d206f6620312042425241206265666f72652077652063616e206c6f636b206c6971756964697479a2646970667358221220744779ed20b3324e952eed3ca0630e2716c49fd8329057ee15c1a74e6a2d089a64736f6c634300060c0033

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

00000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000028

-----Decoded View---------------
Arg [0] : _burnDivisor (uint256): 255
Arg [1] : _liquidityDivisor (uint256): 40

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000ff
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000028


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.