ETH Price: $2,514.04 (-0.14%)
Gas: 5.24 Gwei

Token

ERC20 ***
 

Overview

Max Total Supply

96,407.244759983389743642 ERC20 ***

Holders

275

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

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

Contract Source Code Verified (Exact Match)

Contract Name:
Pool

Compiler Version
v0.6.10+commit.00c0fcaf

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-10-16
*/

// File: @openzeppelin/contracts/GSN/Context.sol


pragma solidity ^0.6.0;

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

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


pragma solidity ^0.6.0;

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

// File: @openzeppelin/contracts/math/SafeMath.sol


pragma solidity ^0.6.0;

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

// File: @openzeppelin/contracts/utils/Address.sol


pragma solidity ^0.6.2;

/**
 * @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) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

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

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol


pragma solidity ^0.6.0;





/**
 * @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 ERC20 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.
     *
     * 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);

        _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 is 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 { }
}

// File: contracts/pool/Math64x64.sol

/*
 *  Math 64.64 Smart Contract Library.  Copyright © 2019 by  Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
pragma solidity ^0.6.0;

/**
 * Smart contract library of mathematical functions operating with signed
 * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is
 * basically a simple fraction whose numerator is signed 128-bit integer and
 * denominator is 2^64.  As long as denominator is always the same, there is no
 * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
 * represented by int128 type holding only the numerator.
 */
library Math64x64 {
  /**
   * @dev Minimum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

  /**
   * @dev Maximum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

  /**
   * @dev Convert signed 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromInt (int256 x) internal pure returns (int128) {
    require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * @dev Convert signed 64.64 fixed point number into signed 64-bit integer number
   * rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64-bit integer number
   */
  function toInt (int128 x) internal pure returns (int64) {
    return int64 (x >> 64);
  }

  /**
   * @dev Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromUInt (uint256 x) internal pure returns (int128) {
    require (x <= 0x7FFFFFFFFFFFFFFF);
    return int128 (x << 64);
  }

  /**
   * @dev Convert signed 64.64 fixed point number into unsigned 64-bit integer
   * number rounding down.  Revert on underflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return unsigned 64-bit integer number
   */
  function toUInt (int128 x) internal pure returns (uint64) {
    require (x >= 0);
    return uint64 (x >> 64);
  }

  /**
   * @dev Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
   * number rounding down.  Revert on overflow.
   *
   * @param x signed 128.128-bin fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function from128x128 (int256 x) internal pure returns (int128) {
    int256 result = x >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Convert signed 64.64 fixed point number into signed 128.128 fixed point
   * number.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 128.128 fixed point number
   */
  function to128x128 (int128 x) internal pure returns (int256) {
    return int256 (x) << 64;
  }

  /**
   * @dev Calculate x + y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function add (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) + y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Calculate x - y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sub (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) - y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Calculate x * y rounding down.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function mul (int128 x, int128 y) internal pure returns (int128) {
    int256 result = int256(x) * y >> 64;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
   * number and y is signed 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y signed 256-bit integer number
   * @return signed 256-bit integer number
   */
  function muli (int128 x, int256 y) internal pure returns (int256) {
    if (x == MIN_64x64) {
      require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
        y <= 0x1000000000000000000000000000000000000000000000000);
      return -y << 63;
    } else {
      bool negativeResult = false;
      if (x < 0) {
        x = -x;
        negativeResult = true;
      }
      if (y < 0) {
        y = -y; // We rely on overflow behavior here
        negativeResult = !negativeResult;
      }
      uint256 absoluteResult = mulu (x, uint256 (y));
      if (negativeResult) {
        require (absoluteResult <=
          0x8000000000000000000000000000000000000000000000000000000000000000);
        return -int256 (absoluteResult); // We rely on overflow behavior here
      } else {
        require (absoluteResult <=
          0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
        return int256 (absoluteResult);
      }
    }
  }

  /**
   * @dev Calculate x * y rounding down, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y unsigned 256-bit integer number
   * @return unsigned 256-bit integer number
   */
  function mulu (int128 x, uint256 y) internal pure returns (uint256) {
    if (y == 0) return 0;

    require (x >= 0);

    uint256 lo = (uint256 (x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
    uint256 hi = uint256 (x) * (y >> 128);

    require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    hi <<= 64;

    require (hi <=
      0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
    return hi + lo;
  }

  /**
   * @dev Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function div (int128 x, int128 y) internal pure returns (int128) {
    require (y != 0);
    int256 result = (int256 (x) << 64) / y;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Calculate x / y rounding towards zero, where x and y are signed 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x signed 256-bit integer number
   * @param y signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divi (int256 x, int256 y) internal pure returns (int128) {
    require (y != 0);

    bool negativeResult = false;
    if (x < 0) {
      x = -x; // We rely on overflow behavior here
      negativeResult = true;
    }
    if (y < 0) {
      y = -y; // We rely on overflow behavior here
      negativeResult = !negativeResult;
    }
    uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * @dev Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divu (uint256 x, uint256 y) internal pure returns (int128) {
    require (y != 0);
    uint128 result = divuu (x, y);
    require (result <= uint128 (MAX_64x64));
    return int128 (result);
  }

  /**
   * @dev Calculate -x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function neg (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return -x;
  }

  /**
   * @dev Calculate |x|.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function abs (int128 x) internal pure returns (int128) {
    require (x != MIN_64x64);
    return x < 0 ? -x : x;
  }

  /**
   * @dev Calculate 1 / x rounding towards zero.  Revert on overflow or when x is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function inv (int128 x) internal pure returns (int128) {
    require (x != 0);
    int256 result = int256 (0x100000000000000000000000000000000) / x;
    require (result >= MIN_64x64 && result <= MAX_64x64);
    return int128 (result);
  }

  /**
   * @dev Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function avg (int128 x, int128 y) internal pure returns (int128) {
    return int128 ((int256 (x) + int256 (y)) >> 1);
  }

  /**
   * @dev Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
   * Revert on overflow or in case x * y is negative.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function gavg (int128 x, int128 y) internal pure returns (int128) {
    int256 m = int256 (x) * int256 (y);
    require (m >= 0);
    require (m <
        0x4000000000000000000000000000000000000000000000000000000000000000);
    return int128 (sqrtu (uint256 (m), uint256 (x) + uint256 (y) >> 1));
  }

  /**
   * @dev Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y uint256 value
   * @return signed 64.64-bit fixed point number
   */
  function pow (int128 x, uint256 y) internal pure returns (int128) {
    uint256 absoluteResult;
    bool negativeResult = false;
    if (x >= 0) {
      absoluteResult = powu (uint256 (x) << 63, y);
    } else {
      // We rely on overflow behavior here
      absoluteResult = powu (uint256 (uint128 (-x)) << 63, y);
      negativeResult = y & 1 > 0;
    }

    absoluteResult >>= 63;

    if (negativeResult) {
      require (absoluteResult <= 0x80000000000000000000000000000000);
      return -int128 (absoluteResult); // We rely on overflow behavior here
    } else {
      require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return int128 (absoluteResult); // We rely on overflow behavior here
    }
  }

  /**
   * @dev Calculate sqrt (x) rounding down.  Revert if x < 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sqrt (int128 x) internal pure returns (int128) {
    require (x >= 0);
    return int128 (sqrtu (uint256 (x) << 64, 0x10000000000000000));
  }

  /**
   * @dev Calculate binary logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function log_2 (int128 x) internal pure returns (int128) {
    require (x > 0);

    int256 msb = 0;
    int256 xc = x;
    if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
    if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
    if (xc >= 0x10000) { xc >>= 16; msb += 16; }
    if (xc >= 0x100) { xc >>= 8; msb += 8; }
    if (xc >= 0x10) { xc >>= 4; msb += 4; }
    if (xc >= 0x4) { xc >>= 2; msb += 2; }
    if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

    int256 result = msb - 64 << 64;
    uint256 ux = uint256 (x) << 127 - msb;
    for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
      ux *= ux;
      uint256 b = ux >> 255;
      ux >>= 127 + b;
      result += bit * int256 (b);
    }

    return int128 (result);
  }

  /**
   * @dev Calculate natural logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function ln (int128 x) internal pure returns (int128) {
    require (x > 0);

    return int128 (
        uint256 (log_2 (x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128);
  }

  /**
   * @dev Calculate binary exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp_2 (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    uint256 result = 0x80000000000000000000000000000000;

    if (x & 0x8000000000000000 > 0)
      result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
    if (x & 0x4000000000000000 > 0)
      result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
    if (x & 0x2000000000000000 > 0)
      result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
    if (x & 0x1000000000000000 > 0)
      result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
    if (x & 0x800000000000000 > 0)
      result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
    if (x & 0x400000000000000 > 0)
      result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
    if (x & 0x200000000000000 > 0)
      result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
    if (x & 0x100000000000000 > 0)
      result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
    if (x & 0x80000000000000 > 0)
      result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
    if (x & 0x40000000000000 > 0)
      result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
    if (x & 0x20000000000000 > 0)
      result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
    if (x & 0x10000000000000 > 0)
      result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
    if (x & 0x8000000000000 > 0)
      result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
    if (x & 0x4000000000000 > 0)
      result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
    if (x & 0x2000000000000 > 0)
      result = result * 0x1000162E525EE054754457D5995292026 >> 128;
    if (x & 0x1000000000000 > 0)
      result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
    if (x & 0x800000000000 > 0)
      result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
    if (x & 0x400000000000 > 0)
      result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
    if (x & 0x200000000000 > 0)
      result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
    if (x & 0x100000000000 > 0)
      result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
    if (x & 0x80000000000 > 0)
      result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
    if (x & 0x40000000000 > 0)
      result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
    if (x & 0x20000000000 > 0)
      result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
    if (x & 0x10000000000 > 0)
      result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
    if (x & 0x8000000000 > 0)
      result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
    if (x & 0x4000000000 > 0)
      result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
    if (x & 0x2000000000 > 0)
      result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
    if (x & 0x1000000000 > 0)
      result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
    if (x & 0x800000000 > 0)
      result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
    if (x & 0x400000000 > 0)
      result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
    if (x & 0x200000000 > 0)
      result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
    if (x & 0x100000000 > 0)
      result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
    if (x & 0x80000000 > 0)
      result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
    if (x & 0x40000000 > 0)
      result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
    if (x & 0x20000000 > 0)
      result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
    if (x & 0x10000000 > 0)
      result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
    if (x & 0x8000000 > 0)
      result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
    if (x & 0x4000000 > 0)
      result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
    if (x & 0x2000000 > 0)
      result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
    if (x & 0x1000000 > 0)
      result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
    if (x & 0x800000 > 0)
      result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
    if (x & 0x400000 > 0)
      result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
    if (x & 0x200000 > 0)
      result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
    if (x & 0x100000 > 0)
      result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
    if (x & 0x80000 > 0)
      result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
    if (x & 0x40000 > 0)
      result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
    if (x & 0x20000 > 0)
      result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
    if (x & 0x10000 > 0)
      result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
    if (x & 0x8000 > 0)
      result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
    if (x & 0x4000 > 0)
      result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
    if (x & 0x2000 > 0)
      result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
    if (x & 0x1000 > 0)
      result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
    if (x & 0x800 > 0)
      result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
    if (x & 0x400 > 0)
      result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
    if (x & 0x200 > 0)
      result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
    if (x & 0x100 > 0)
      result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
    if (x & 0x80 > 0)
      result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
    if (x & 0x40 > 0)
      result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
    if (x & 0x20 > 0)
      result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
    if (x & 0x10 > 0)
      result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
    if (x & 0x8 > 0)
      result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
    if (x & 0x4 > 0)
      result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
    if (x & 0x2 > 0)
      result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
    if (x & 0x1 > 0)
      result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

    result >>= 63 - (x >> 64);
    require (result <= uint256 (MAX_64x64));

    return int128 (result);
  }

  /**
   * @dev Calculate natural exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp (int128 x) internal pure returns (int128) {
    require (x < 0x400000000000000000); // Overflow

    if (x < -0x400000000000000000) return 0; // Underflow

    return exp_2 (
        int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
  }

  /**
   * @dev Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return unsigned 64.64-bit fixed point number
   */
  function divuu (uint256 x, uint256 y) private pure returns (uint128) {
    require (y != 0);

    uint256 result;

    if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
      result = (x << 64) / y;
    else {
      uint256 msb = 192;
      uint256 xc = x >> 192;
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
      require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 hi = result * (y >> 128);
      uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

      uint256 xh = x >> 192;
      uint256 xl = x << 64;

      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here
      lo = hi << 128;
      if (xl < lo) xh -= 1;
      xl -= lo; // We rely on overflow behavior here

      assert (xh == hi >> 128);

      result += xl / y;
    }

    require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
    return uint128 (result);
  }

  /**
   * @dev Calculate x^y assuming 0^0 is 1, where x is unsigned 129.127 fixed point
   * number and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x unsigned 129.127-bit fixed point number
   * @param y uint256 value
   * @return unsigned 129.127-bit fixed point number
   */
  function powu (uint256 x, uint256 y) private pure returns (uint256) {
    if (y == 0) return 0x80000000000000000000000000000000;
    else if (x == 0) return 0;
    else {
      int256 msb = 0;
      uint256 xc = x;
      if (xc >= 0x100000000000000000000000000000000) { xc >>= 128; msb += 128; }
      if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      int256 xe = msb - 127;
      if (xe > 0) x >>= xe;
      else x <<= -xe;

      uint256 result = 0x80000000000000000000000000000000;
      int256 re = 0;

      while (y > 0) {
        if (y & 1 > 0) {
          result = result * x;
          y -= 1;
          re += xe;
          if (result >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            result >>= 128;
            re += 1;
          } else result >>= 127;
          if (re < -127) return 0; // Underflow
          require (re < 128); // Overflow
        } else {
          x = x * x;
          y >>= 1;
          xe <<= 1;
          if (x >=
            0x8000000000000000000000000000000000000000000000000000000000000000) {
            x >>= 128;
            xe += 1;
          } else x >>= 127;
          if (xe < -127) return 0; // Underflow
          require (xe < 128); // Overflow
        }
      }

      if (re > 0) result <<= re;
      else if (re < 0) result >>= -re;

      return result;
    }
  }

  /**
   * @dev Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
   * number.
   *
   * @param x unsigned 256-bit integer number
   * @return unsigned 128-bit integer number
   */
  function sqrtu (uint256 x, uint256 r) private pure returns (uint128) {
    if (x == 0) return 0;
    else {
      require (r > 0);
      while (true) {
        uint256 rr = x / r;
        if (r == rr || r + 1 == rr) return uint128 (r);
        else if (r == rr + 1) return uint128 (rr);
        r = r + rr + 1 >> 1;
      }
    }
  }
}

// File: contracts/pool/YieldMath.sol

pragma solidity ^0.6.0;


/**
 * Ethereum smart contract library implementing Yield Math model.
 */
library YieldMath {
  /**
   * Calculate the amount of fyDai a user would get for given amount of Dai.
   *
   * @param daiReserves Dai reserves amount
   * @param fyDaiReserves fyDai reserves amount
   * @param daiAmount Dai amount to be traded
   * @param timeTillMaturity time till maturity in seconds
   * @param k time till maturity coefficient, multiplied by 2^64
   * @param g fee coefficient, multiplied by 2^64
   * @return the amount of fyDai a user would get for given amount of Dai
   */
  function fyDaiOutForDaiIn (
    uint128 daiReserves, uint128 fyDaiReserves, uint128 daiAmount,
    uint128 timeTillMaturity, int128 k, int128 g)
  internal pure returns (uint128) {
    // t = k * timeTillMaturity
    int128 t = Math64x64.mul (k, Math64x64.fromUInt (timeTillMaturity));

    // a = (1 - gt)
    int128 a = Math64x64.sub (0x10000000000000000, Math64x64.mul (g, t));
    require (a > 0, "YieldMath: Too far from maturity");

    // xdx = daiReserves + daiAmount
    uint256 xdx = uint256 (daiReserves) + uint256 (daiAmount);
    require (xdx < 0x100000000000000000000000000000000, "YieldMath: Too much Dai in");

    uint256 sum =
      pow (daiReserves, uint128 (a), 0x10000000000000000) +
      pow (fyDaiReserves, uint128 (a), 0x10000000000000000) -
      pow (uint128(xdx), uint128 (a), 0x10000000000000000);
    require (sum < 0x100000000000000000000000000000000, "YieldMath: Insufficient fyDai reserves");

    uint256 result = fyDaiReserves - pow (uint128 (sum), 0x10000000000000000, uint128 (a));
    require (result < 0x100000000000000000000000000000000, "YieldMath: Rounding induced error");
    result = result > 1e12 ? result - 1e12 : 0; // Substract error guard, flooring the result at zero

    return uint128 (result);
  }

  /**
   * Calculate the amount of Dai a user would get for certain amount of fyDai.
   *
   * @param daiReserves Dai reserves amount
   * @param fyDaiReserves fyDai reserves amount
   * @param fyDaiAmount fyDai amount to be traded
   * @param timeTillMaturity time till maturity in seconds
   * @param k time till maturity coefficient, multiplied by 2^64
   * @param g fee coefficient, multiplied by 2^64
   * @return the amount of Dai a user would get for given amount of fyDai
   */
  function daiOutForFYDaiIn (
    uint128 daiReserves, uint128 fyDaiReserves, uint128 fyDaiAmount,
    uint128 timeTillMaturity, int128 k, int128 g)
  internal pure returns (uint128) {
    // t = k * timeTillMaturity
    int128 t = Math64x64.mul (k, Math64x64.fromUInt (timeTillMaturity));

    // a = (1 - gt)
    int128 a = Math64x64.sub (0x10000000000000000, Math64x64.mul (g, t));
    require (a > 0, "YieldMath: Too far from maturity");

    // ydy = fyDaiReserves + fyDaiAmount;
    uint256 ydy = uint256 (fyDaiReserves) + uint256 (fyDaiAmount);
    require (ydy < 0x100000000000000000000000000000000, "YieldMath: Too much fyDai in");

    uint256 sum =
      pow (uint128 (daiReserves), uint128 (a), 0x10000000000000000) -
      pow (uint128 (ydy), uint128 (a), 0x10000000000000000) +
      pow (fyDaiReserves, uint128 (a), 0x10000000000000000);
    require (sum < 0x100000000000000000000000000000000, "YieldMath: Insufficient Dai reserves");

    uint256 result =
      daiReserves -
      pow (uint128 (sum), 0x10000000000000000, uint128 (a));
    require (result < 0x100000000000000000000000000000000, "YieldMath: Rounding induced error");
    result = result > 1e12 ? result - 1e12 : 0; // Substract error guard, flooring the result at zero

    return uint128 (result);
  }

  /**
   * Calculate the amount of fyDai a user could sell for given amount of Dai.
   *
   * @param daiReserves Dai reserves amount
   * @param fyDaiReserves fyDai reserves amount
   * @param daiAmount Dai amount to be traded
   * @param timeTillMaturity time till maturity in seconds
   * @param k time till maturity coefficient, multiplied by 2^64
   * @param g fee coefficient, multiplied by 2^64
   * @return the amount of fyDai a user could sell for given amount of Dai
   */
  function fyDaiInForDaiOut (
    uint128 daiReserves, uint128 fyDaiReserves, uint128 daiAmount,
    uint128 timeTillMaturity, int128 k, int128 g)
  internal pure returns (uint128) {
    // t = k * timeTillMaturity
    int128 t = Math64x64.mul (k, Math64x64.fromUInt (timeTillMaturity));

    // a = (1 - gt)
    int128 a = Math64x64.sub (0x10000000000000000, Math64x64.mul (g, t));
    require (a > 0, "YieldMath: Too far from maturity");

    // xdx = daiReserves - daiAmount
    uint256 xdx = uint256 (daiReserves) - uint256 (daiAmount);
    require (xdx < 0x100000000000000000000000000000000, "YieldMath: Too much Dai out");

    uint256 sum =
      pow (uint128 (daiReserves), uint128 (a), 0x10000000000000000) +
      pow (fyDaiReserves, uint128 (a), 0x10000000000000000) -
      pow (uint128 (xdx), uint128 (a), 0x10000000000000000);
    require (sum < 0x100000000000000000000000000000000, "YieldMath: Resulting fyDai reserves too high");

    uint256 result = pow (uint128 (sum), 0x10000000000000000, uint128 (a)) - fyDaiReserves;
    require (result < 0x100000000000000000000000000000000, "YieldMath: Rounding induced error");
    result = result < type(uint128).max - 1e12 ? result + 1e12 : type(uint128).max; // Add error guard, ceiling the result at max

    return uint128 (result);
  }

  /**
   * Calculate the amount of Dai a user would have to pay for certain amount of
   * fyDai.
   *
   * @param daiReserves Dai reserves amount
   * @param fyDaiReserves fyDai reserves amount
   * @param fyDaiAmount fyDai amount to be traded
   * @param timeTillMaturity time till maturity in seconds
   * @param k time till maturity coefficient, multiplied by 2^64
   * @param g fee coefficient, multiplied by 2^64
   * @return the amount of Dai a user would have to pay for given amount of
   *         fyDai
   */
  function daiInForFYDaiOut (
    uint128 daiReserves, uint128 fyDaiReserves, uint128 fyDaiAmount,
    uint128 timeTillMaturity, int128 k, int128 g)
  internal pure returns (uint128) {
    // a = (1 - g * k * timeTillMaturity)
    int128 a = Math64x64.sub (0x10000000000000000, Math64x64.mul (g, Math64x64.mul (k, Math64x64.fromUInt (timeTillMaturity))));
    require (a > 0, "YieldMath: Too far from maturity");

    // ydy = fyDaiReserves - fyDaiAmount;
    uint256 ydy = uint256 (fyDaiReserves) - uint256 (fyDaiAmount);
    require (ydy < 0x100000000000000000000000000000000, "YieldMath: Too much fyDai out");

    uint256 sum =
      pow (daiReserves, uint128 (a), 0x10000000000000000) +
      pow (fyDaiReserves, uint128 (a), 0x10000000000000000) -
      pow (uint128 (ydy), uint128 (a), 0x10000000000000000);
    require (sum < 0x100000000000000000000000000000000, "YieldMath: Resulting Dai reserves too high");

    uint256 result =
      pow (uint128 (sum), 0x10000000000000000, uint128 (a)) -
      daiReserves;
    require (result < 0x100000000000000000000000000000000, "YieldMath: Rounding induced error");
    result = result < type(uint128).max - 1e12 ? result + 1e12 : type(uint128).max; // Add error guard, ceiling the result at max
    
    return uint128 (result);
  }

  /**
   * Raise given number x into power specified as a simple fraction y/z and then
   * multiply the result by the normalization factor 2^(128 * (1 - y/z)).
   * Revert if z is zero, or if both x and y are zeros.
   *
   * @param x number to raise into given power y/z
   * @param y numerator of the power to raise x into
   * @param z denominator of the power to raise x into
   * @return x raised into power y/z and then multiplied by 2^(128 * (1 - y/z))
   */
  function pow (uint128 x, uint128 y, uint128 z)
  internal pure returns (uint256) {
    require (z != 0);

    if (x == 0) {
      require (y != 0);
      return 0;
    } else {
      uint256 l =
        uint256 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - log_2 (x)) * y / z;
      if (l > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) return 0;
      else return uint256 (pow_2 (uint128 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - l)));
    }
  }

  /**
   * Calculate base 2 logarithm of an unsigned 128-bit integer number.  Revert
   * in case x is zero.
   *
   * @param x number to calculate base 2 logarithm of
   * @return base 2 logarithm of x, multiplied by 2^121
   */
  function log_2 (uint128 x)
  internal pure returns (uint128) {
    require (x != 0);

    uint b = x;

    uint l = 0xFE000000000000000000000000000000;

    if (b < 0x10000000000000000) {l -= 0x80000000000000000000000000000000; b <<= 64;}
    if (b < 0x1000000000000000000000000) {l -= 0x40000000000000000000000000000000; b <<= 32;}
    if (b < 0x10000000000000000000000000000) {l -= 0x20000000000000000000000000000000; b <<= 16;}
    if (b < 0x1000000000000000000000000000000) {l -= 0x10000000000000000000000000000000; b <<= 8;}
    if (b < 0x10000000000000000000000000000000) {l -= 0x8000000000000000000000000000000; b <<= 4;}
    if (b < 0x40000000000000000000000000000000) {l -= 0x4000000000000000000000000000000; b <<= 2;}
    if (b < 0x80000000000000000000000000000000) {l -= 0x2000000000000000000000000000000; b <<= 1;}

    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000;}
    /* Precision reduced to 64 bits
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2;}
    b = b * b >> 127; if (b >= 0x100000000000000000000000000000000) l |= 0x1;
    */

    return uint128 (l);
  }

  /**
   * Calculate 2 raised into given power.
   *
   * @param x power to raise 2 into, multiplied by 2^121
   * @return 2 raised into given power
   */
  function pow_2 (uint128 x)
  internal pure returns (uint128) {
    uint r = 0x80000000000000000000000000000000;
    if (x & 0x1000000000000000000000000000000 > 0) r = r * 0xb504f333f9de6484597d89b3754abe9f >> 127;
    if (x & 0x800000000000000000000000000000 > 0) r = r * 0x9837f0518db8a96f46ad23182e42f6f6 >> 127;
    if (x & 0x400000000000000000000000000000 > 0) r = r * 0x8b95c1e3ea8bd6e6fbe4628758a53c90 >> 127;
    if (x & 0x200000000000000000000000000000 > 0) r = r * 0x85aac367cc487b14c5c95b8c2154c1b2 >> 127;
    if (x & 0x100000000000000000000000000000 > 0) r = r * 0x82cd8698ac2ba1d73e2a475b46520bff >> 127;
    if (x & 0x80000000000000000000000000000 > 0) r = r * 0x8164d1f3bc0307737be56527bd14def4 >> 127;
    if (x & 0x40000000000000000000000000000 > 0) r = r * 0x80b1ed4fd999ab6c25335719b6e6fd20 >> 127;
    if (x & 0x20000000000000000000000000000 > 0) r = r * 0x8058d7d2d5e5f6b094d589f608ee4aa2 >> 127;
    if (x & 0x10000000000000000000000000000 > 0) r = r * 0x802c6436d0e04f50ff8ce94a6797b3ce >> 127;
    if (x & 0x8000000000000000000000000000 > 0) r = r * 0x8016302f174676283690dfe44d11d008 >> 127;
    if (x & 0x4000000000000000000000000000 > 0) r = r * 0x800b179c82028fd0945e54e2ae18f2f0 >> 127;
    if (x & 0x2000000000000000000000000000 > 0) r = r * 0x80058baf7fee3b5d1c718b38e549cb93 >> 127;
    if (x & 0x1000000000000000000000000000 > 0) r = r * 0x8002c5d00fdcfcb6b6566a58c048be1f >> 127;
    if (x & 0x800000000000000000000000000 > 0) r = r * 0x800162e61bed4a48e84c2e1a463473d9 >> 127;
    if (x & 0x400000000000000000000000000 > 0) r = r * 0x8000b17292f702a3aa22beacca949013 >> 127;
    if (x & 0x200000000000000000000000000 > 0) r = r * 0x800058b92abbae02030c5fa5256f41fe >> 127;
    if (x & 0x100000000000000000000000000 > 0) r = r * 0x80002c5c8dade4d71776c0f4dbea67d6 >> 127;
    if (x & 0x80000000000000000000000000 > 0) r = r * 0x8000162e44eaf636526be456600bdbe4 >> 127;
    if (x & 0x40000000000000000000000000 > 0) r = r * 0x80000b1721fa7c188307016c1cd4e8b6 >> 127;
    if (x & 0x20000000000000000000000000 > 0) r = r * 0x8000058b90de7e4cecfc487503488bb1 >> 127;
    if (x & 0x10000000000000000000000000 > 0) r = r * 0x800002c5c8678f36cbfce50a6de60b14 >> 127;
    if (x & 0x8000000000000000000000000 > 0) r = r * 0x80000162e431db9f80b2347b5d62e516 >> 127;
    if (x & 0x4000000000000000000000000 > 0) r = r * 0x800000b1721872d0c7b08cf1e0114152 >> 127;
    if (x & 0x2000000000000000000000000 > 0) r = r * 0x80000058b90c1aa8a5c3736cb77e8dff >> 127;
    if (x & 0x1000000000000000000000000 > 0) r = r * 0x8000002c5c8605a4635f2efc2362d978 >> 127;
    if (x & 0x800000000000000000000000 > 0) r = r * 0x800000162e4300e635cf4a109e3939bd >> 127;
    if (x & 0x400000000000000000000000 > 0) r = r * 0x8000000b17217ff81bef9c551590cf83 >> 127;
    if (x & 0x200000000000000000000000 > 0) r = r * 0x800000058b90bfdd4e39cd52c0cfa27c >> 127;
    if (x & 0x100000000000000000000000 > 0) r = r * 0x80000002c5c85fe6f72d669e0e76e411 >> 127;
    if (x & 0x80000000000000000000000 > 0) r = r * 0x8000000162e42ff18f9ad35186d0df28 >> 127;
    if (x & 0x40000000000000000000000 > 0) r = r * 0x80000000b17217f84cce71aa0dcfffe7 >> 127;
    if (x & 0x20000000000000000000000 > 0) r = r * 0x8000000058b90bfc07a77ad56ed22aaa >> 127;
    if (x & 0x10000000000000000000000 > 0) r = r * 0x800000002c5c85fdfc23cdead40da8d6 >> 127;
    if (x & 0x8000000000000000000000 > 0) r = r * 0x80000000162e42fefc25eb1571853a66 >> 127;
    if (x & 0x4000000000000000000000 > 0) r = r * 0x800000000b17217f7d97f692baacded5 >> 127;
    if (x & 0x2000000000000000000000 > 0) r = r * 0x80000000058b90bfbead3b8b5dd254d7 >> 127;
    if (x & 0x1000000000000000000000 > 0) r = r * 0x8000000002c5c85fdf4eedd62f084e67 >> 127;
    if (x & 0x800000000000000000000 > 0) r = r * 0x800000000162e42fefa58aef378bf586 >> 127;
    if (x & 0x400000000000000000000 > 0) r = r * 0x8000000000b17217f7d24a78a3c7ef02 >> 127;
    if (x & 0x200000000000000000000 > 0) r = r * 0x800000000058b90bfbe9067c93e474a6 >> 127;
    if (x & 0x100000000000000000000 > 0) r = r * 0x80000000002c5c85fdf47b8e5a72599f >> 127;
    if (x & 0x80000000000000000000 > 0) r = r * 0x8000000000162e42fefa3bdb315934a2 >> 127;
    if (x & 0x40000000000000000000 > 0) r = r * 0x80000000000b17217f7d1d7299b49c46 >> 127;
    if (x & 0x20000000000000000000 > 0) r = r * 0x8000000000058b90bfbe8e9a8d1c4ea0 >> 127;
    if (x & 0x10000000000000000000 > 0) r = r * 0x800000000002c5c85fdf4745969ea76f >> 127;
    if (x & 0x8000000000000000000 > 0) r = r * 0x80000000000162e42fefa3a0df5373bf >> 127;
    if (x & 0x4000000000000000000 > 0) r = r * 0x800000000000b17217f7d1cff4aac1e1 >> 127;
    if (x & 0x2000000000000000000 > 0) r = r * 0x80000000000058b90bfbe8e7db95a2f1 >> 127;
    if (x & 0x1000000000000000000 > 0) r = r * 0x8000000000002c5c85fdf473e61ae1f8 >> 127;
    if (x & 0x800000000000000000 > 0) r = r * 0x800000000000162e42fefa39f121751c >> 127;
    if (x & 0x400000000000000000 > 0) r = r * 0x8000000000000b17217f7d1cf815bb96 >> 127;
    if (x & 0x200000000000000000 > 0) r = r * 0x800000000000058b90bfbe8e7bec1e0d >> 127;
    if (x & 0x100000000000000000 > 0) r = r * 0x80000000000002c5c85fdf473dee5f17 >> 127;
    if (x & 0x80000000000000000 > 0) r = r * 0x8000000000000162e42fefa39ef5438f >> 127;
    if (x & 0x40000000000000000 > 0) r = r * 0x80000000000000b17217f7d1cf7a26c8 >> 127;
    if (x & 0x20000000000000000 > 0) r = r * 0x8000000000000058b90bfbe8e7bcf4a4 >> 127;
    if (x & 0x10000000000000000 > 0) r = r * 0x800000000000002c5c85fdf473de72a2 >> 127;
    /* Precision reduced to 64 bits
    if (x & 0x8000000000000000 > 0) r = r * 0x80000000000000162e42fefa39ef3765 >> 127;
    if (x & 0x4000000000000000 > 0) r = r * 0x800000000000000b17217f7d1cf79b37 >> 127;
    if (x & 0x2000000000000000 > 0) r = r * 0x80000000000000058b90bfbe8e7bcd7d >> 127;
    if (x & 0x1000000000000000 > 0) r = r * 0x8000000000000002c5c85fdf473de6b6 >> 127;
    if (x & 0x800000000000000 > 0) r = r * 0x800000000000000162e42fefa39ef359 >> 127;
    if (x & 0x400000000000000 > 0) r = r * 0x8000000000000000b17217f7d1cf79ac >> 127;
    if (x & 0x200000000000000 > 0) r = r * 0x800000000000000058b90bfbe8e7bcd6 >> 127;
    if (x & 0x100000000000000 > 0) r = r * 0x80000000000000002c5c85fdf473de6a >> 127;
    if (x & 0x80000000000000 > 0) r = r * 0x8000000000000000162e42fefa39ef35 >> 127;
    if (x & 0x40000000000000 > 0) r = r * 0x80000000000000000b17217f7d1cf79a >> 127;
    if (x & 0x20000000000000 > 0) r = r * 0x8000000000000000058b90bfbe8e7bcd >> 127;
    if (x & 0x10000000000000 > 0) r = r * 0x800000000000000002c5c85fdf473de6 >> 127;
    if (x & 0x8000000000000 > 0) r = r * 0x80000000000000000162e42fefa39ef3 >> 127;
    if (x & 0x4000000000000 > 0) r = r * 0x800000000000000000b17217f7d1cf79 >> 127;
    if (x & 0x2000000000000 > 0) r = r * 0x80000000000000000058b90bfbe8e7bc >> 127;
    if (x & 0x1000000000000 > 0) r = r * 0x8000000000000000002c5c85fdf473de >> 127;
    if (x & 0x800000000000 > 0) r = r * 0x800000000000000000162e42fefa39ef >> 127;
    if (x & 0x400000000000 > 0) r = r * 0x8000000000000000000b17217f7d1cf7 >> 127;
    if (x & 0x200000000000 > 0) r = r * 0x800000000000000000058b90bfbe8e7b >> 127;
    if (x & 0x100000000000 > 0) r = r * 0x80000000000000000002c5c85fdf473d >> 127;
    if (x & 0x80000000000 > 0) r = r * 0x8000000000000000000162e42fefa39e >> 127;
    if (x & 0x40000000000 > 0) r = r * 0x80000000000000000000b17217f7d1cf >> 127;
    if (x & 0x20000000000 > 0) r = r * 0x8000000000000000000058b90bfbe8e7 >> 127;
    if (x & 0x10000000000 > 0) r = r * 0x800000000000000000002c5c85fdf473 >> 127;
    if (x & 0x8000000000 > 0) r = r * 0x80000000000000000000162e42fefa39 >> 127;
    if (x & 0x4000000000 > 0) r = r * 0x800000000000000000000b17217f7d1c >> 127;
    if (x & 0x2000000000 > 0) r = r * 0x80000000000000000000058b90bfbe8e >> 127;
    if (x & 0x1000000000 > 0) r = r * 0x8000000000000000000002c5c85fdf47 >> 127;
    if (x & 0x800000000 > 0) r = r * 0x800000000000000000000162e42fefa3 >> 127;
    if (x & 0x400000000 > 0) r = r * 0x8000000000000000000000b17217f7d1 >> 127;
    if (x & 0x200000000 > 0) r = r * 0x800000000000000000000058b90bfbe8 >> 127;
    if (x & 0x100000000 > 0) r = r * 0x80000000000000000000002c5c85fdf4 >> 127;
    if (x & 0x80000000 > 0) r = r * 0x8000000000000000000000162e42fefa >> 127;
    if (x & 0x40000000 > 0) r = r * 0x80000000000000000000000b17217f7d >> 127;
    if (x & 0x20000000 > 0) r = r * 0x8000000000000000000000058b90bfbe >> 127;
    if (x & 0x10000000 > 0) r = r * 0x800000000000000000000002c5c85fdf >> 127;
    if (x & 0x8000000 > 0) r = r * 0x80000000000000000000000162e42fef >> 127;
    if (x & 0x4000000 > 0) r = r * 0x800000000000000000000000b17217f7 >> 127;
    if (x & 0x2000000 > 0) r = r * 0x80000000000000000000000058b90bfb >> 127;
    if (x & 0x1000000 > 0) r = r * 0x8000000000000000000000002c5c85fd >> 127;
    if (x & 0x800000 > 0) r = r * 0x800000000000000000000000162e42fe >> 127;
    if (x & 0x400000 > 0) r = r * 0x8000000000000000000000000b17217f >> 127;
    if (x & 0x200000 > 0) r = r * 0x800000000000000000000000058b90bf >> 127;
    if (x & 0x100000 > 0) r = r * 0x80000000000000000000000002c5c85f >> 127;
    if (x & 0x80000 > 0) r = r * 0x8000000000000000000000000162e42f >> 127;
    if (x & 0x40000 > 0) r = r * 0x80000000000000000000000000b17217 >> 127;
    if (x & 0x20000 > 0) r = r * 0x8000000000000000000000000058b90b >> 127;
    if (x & 0x10000 > 0) r = r * 0x800000000000000000000000002c5c85 >> 127;
    if (x & 0x8000 > 0) r = r * 0x80000000000000000000000000162e42 >> 127;
    if (x & 0x4000 > 0) r = r * 0x800000000000000000000000000b1721 >> 127;
    if (x & 0x2000 > 0) r = r * 0x80000000000000000000000000058b90 >> 127;
    if (x & 0x1000 > 0) r = r * 0x8000000000000000000000000002c5c8 >> 127;
    if (x & 0x800 > 0) r = r * 0x800000000000000000000000000162e4 >> 127;
    if (x & 0x400 > 0) r = r * 0x8000000000000000000000000000b172 >> 127;
    if (x & 0x200 > 0) r = r * 0x800000000000000000000000000058b9 >> 127;
    if (x & 0x100 > 0) r = r * 0x80000000000000000000000000002c5c >> 127;
    if (x & 0x80 > 0) r = r * 0x8000000000000000000000000000162e >> 127;
    if (x & 0x40 > 0) r = r * 0x80000000000000000000000000000b17 >> 127;
    if (x & 0x20 > 0) r = r * 0x8000000000000000000000000000058b >> 127;
    if (x & 0x10 > 0) r = r * 0x800000000000000000000000000002c5 >> 127;
    if (x & 0x8 > 0) r = r * 0x80000000000000000000000000000162 >> 127;
    if (x & 0x4 > 0) r = r * 0x800000000000000000000000000000b1 >> 127;
    if (x & 0x2 > 0) r = r * 0x80000000000000000000000000000058 >> 127;
    if (x & 0x1 > 0) r = r * 0x8000000000000000000000000000002c >> 127;
    */

    r >>= 127 - (x >> 121);

    return uint128 (r);
  }
}

// File: contracts/interfaces/IDelegable.sol

pragma solidity ^0.6.10;


interface IDelegable {
    function addDelegate(address) external;
    function addDelegateBySignature(address, address, uint, uint8, bytes32, bytes32) external;
}

// File: contracts/helpers/Delegable.sol

pragma solidity ^0.6.10;



/// @dev Delegable enables users to delegate their account management to other users.
/// Delegable implements addDelegateBySignature, to add delegates using a signature instead of a separate transaction.
contract Delegable is IDelegable {
    event Delegate(address indexed user, address indexed delegate, bool enabled);

    // keccak256("Signature(address user,address delegate,uint256 nonce,uint256 deadline)");
    bytes32 public immutable SIGNATURE_TYPEHASH = 0x0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb7;
    bytes32 public immutable DELEGABLE_DOMAIN;
    mapping(address => uint) public signatureCount;

    mapping(address => mapping(address => bool)) public delegated;

    constructor () public {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        DELEGABLE_DOMAIN = keccak256(
            abi.encode(
                keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                keccak256(bytes('Yield')),
                keccak256(bytes('1')),
                chainId,
                address(this)
            )
        );
    }

    /// @dev Require that msg.sender is the account holder or a delegate
    modifier onlyHolderOrDelegate(address holder, string memory errorMessage) {
        require(
            msg.sender == holder || delegated[holder][msg.sender],
            errorMessage
        );
        _;
    }

    /// @dev Enable a delegate to act on the behalf of caller
    function addDelegate(address delegate) public override {
        _addDelegate(msg.sender, delegate);
    }

    /// @dev Stop a delegate from acting on the behalf of caller
    function revokeDelegate(address delegate) public {
        _revokeDelegate(msg.sender, delegate);
    }

    /// @dev Add a delegate through an encoded signature
    function addDelegateBySignature(address user, address delegate, uint deadline, uint8 v, bytes32 r, bytes32 s) public override {
        require(deadline >= block.timestamp, 'Delegable: Signature expired');

        bytes32 hashStruct = keccak256(
            abi.encode(
                SIGNATURE_TYPEHASH,
                user,
                delegate,
                signatureCount[user]++,
                deadline
            )
        );

        bytes32 digest = keccak256(
            abi.encodePacked(
                '\x19\x01',
                DELEGABLE_DOMAIN,
                hashStruct
            )
        );
        address signer = ecrecover(digest, v, r, s);
        require(
            signer != address(0) && signer == user,
            'Delegable: Invalid signature'
        );

        _addDelegate(user, delegate);
    }

    /// @dev Enable a delegate to act on the behalf of an user
    function _addDelegate(address user, address delegate) internal {
        require(!delegated[user][delegate], "Delegable: Already delegated");
        delegated[user][delegate] = true;
        emit Delegate(user, delegate, true);
    }

    /// @dev Stop a delegate from acting on the behalf of an user
    function _revokeDelegate(address user, address delegate) internal {
        require(delegated[user][delegate], "Delegable: Already undelegated");
        delegated[user][delegate] = false;
        emit Delegate(user, delegate, false);
    }
}

// File: contracts/interfaces/IERC2612.sol

// Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/
pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC2612 standard as defined in the EIP.
 *
 * Adds the {permit} method, which can be used to change one's
 * {IERC20-allowance} without having to send a transaction, by signing a
 * message. This allows users to spend tokens without having to hold Ether.
 *
 * See https://eips.ethereum.org/EIPS/eip-2612.
 */
interface IERC2612 {
    /**
     * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens,
     * given `owner`'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;

    /**
     * @dev Returns the current ERC2612 nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);
}

// File: contracts/helpers/ERC20Permit.sol

// Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/53516bc555a454862470e7860a9b5254db4d00f5/contracts/token/ERC20/ERC20Permit.sol
pragma solidity ^0.6.0;



/**
 * @dev Extension of {ERC20} that allows token holders to use their tokens
 * without sending any transactions by setting {IERC20-allowance} with a
 * signature using the {permit} method, and then spend them via
 * {IERC20-transferFrom}.
 *
 * The {permit} signature mechanism conforms to the {IERC2612} interface.
 */
abstract contract ERC20Permit is ERC20, IERC2612 {
    mapping (address => uint256) public override nonces;

    bytes32 public immutable PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public immutable DOMAIN_SEPARATOR;

    constructor(string memory name_, string memory symbol_) internal ERC20(name_, symbol_) {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name_)),
                keccak256(bytes("1")),
                chainId,
                address(this)
            )
        );
    }

    /**
     * @dev See {IERC2612-permit}.
     *
     * In cases where the free option is not a concern, deadline can simply be
     * set to uint(-1), so it should be seen as an optional parameter
     */
    function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
        require(deadline >= block.timestamp, "ERC20Permit: expired deadline");

        bytes32 hashStruct = keccak256(
            abi.encode(
                PERMIT_TYPEHASH,
                owner,
                spender,
                amount,
                nonces[owner]++,
                deadline
            )
        );

        bytes32 hash = keccak256(
            abi.encodePacked(
                '\x19\x01',
                DOMAIN_SEPARATOR,
                hashStruct
            )
        );

        address signer = ecrecover(hash, v, r, s);
        require(
            signer != address(0) && signer == owner,
            "ERC20Permit: invalid signature"
        );

        _approve(owner, spender, amount);
    }
}

// File: contracts/interfaces/IPot.sol

pragma solidity ^0.6.10;


/// @dev interface for the pot contract from MakerDao
/// Taken from https://github.com/makerdao/developerguides/blob/master/dai/dsr-integration-guide/dsr.sol
interface IPot {
    function chi() external view returns (uint256);
    function pie(address) external view returns (uint256); // Not a function, but a public variable.
    function rho() external returns (uint256);
    function drip() external returns (uint256);
    function join(uint256) external;
    function exit(uint256) external;
}

// File: contracts/interfaces/IFYDai.sol

pragma solidity ^0.6.10;



interface IFYDai is IERC20, IERC2612 {
    function isMature() external view returns(bool);
    function maturity() external view returns(uint);
    function chi0() external view returns(uint);
    function rate0() external view returns(uint);
    function chiGrowth() external view returns(uint);
    function rateGrowth() external view returns(uint);
    function mature() external;
    function unlocked() external view returns (uint);
    function mint(address, uint) external;
    function burn(address, uint) external;
    function flashMint(uint, bytes calldata) external;
    function redeem(address, address, uint256) external returns (uint256);
    // function transfer(address, uint) external returns (bool);
    // function transferFrom(address, address, uint) external returns (bool);
    // function approve(address, uint) external returns (bool);
}

// File: contracts/interfaces/IPool.sol

pragma solidity ^0.6.10;





interface IPool is IDelegable, IERC20, IERC2612 {
    function dai() external view returns(IERC20);
    function fyDai() external view returns(IFYDai);
    function getDaiReserves() external view returns(uint128);
    function getFYDaiReserves() external view returns(uint128);
    function sellDai(address from, address to, uint128 daiIn) external returns(uint128);
    function buyDai(address from, address to, uint128 daiOut) external returns(uint128);
    function sellFYDai(address from, address to, uint128 fyDaiIn) external returns(uint128);
    function buyFYDai(address from, address to, uint128 fyDaiOut) external returns(uint128);
    function sellDaiPreview(uint128 daiIn) external view returns(uint128);
    function buyDaiPreview(uint128 daiOut) external view returns(uint128);
    function sellFYDaiPreview(uint128 fyDaiIn) external view returns(uint128);
    function buyFYDaiPreview(uint128 fyDaiOut) external view returns(uint128);
    function mint(address from, address to, uint256 daiOffered) external returns (uint256);
    function burn(address from, address to, uint256 tokensBurned) external returns (uint256, uint256);
}

// File: contracts/pool/Pool.sol

pragma solidity ^0.6.10;










/// @dev The Pool contract exchanges Dai for fyDai at a price defined by a specific formula.
contract Pool is IPool, Delegable(), ERC20Permit {

    event Trade(uint256 maturity, address indexed from, address indexed to, int256 daiTokens, int256 fyDaiTokens);
    event Liquidity(uint256 maturity, address indexed from, address indexed to, int256 daiTokens, int256 fyDaiTokens, int256 poolTokens);

    int128 constant public k = int128(uint256((1 << 64)) / 126144000); // 1 / Seconds in 4 years, in 64.64
    int128 constant public g1 = int128(uint256((950 << 64)) / 1000); // To be used when selling Dai to the pool. All constants are `ufixed`, to divide them they must be converted to uint256
    int128 constant public g2 = int128(uint256((1000 << 64)) / 950); // To be used when selling fyDai to the pool. All constants are `ufixed`, to divide them they must be converted to uint256
    uint128 immutable public maturity;

    IERC20 public override dai;
    IFYDai public override fyDai;

    constructor(address dai_, address fyDai_, string memory name_, string memory symbol_)
        public
        ERC20Permit(name_, symbol_)
    {
        dai = IERC20(dai_);
        fyDai = IFYDai(fyDai_);

        maturity = toUint128(fyDai.maturity());
    }

    /// @dev Trading can only be done before maturity
    modifier beforeMaturity() {
        require(
            now < maturity,
            "Pool: Too late"
        );
        _;
    }

    /// @dev Overflow-protected addition, from OpenZeppelin
    function add(uint128 a, uint128 b)
        internal pure returns (uint128)
    {
        uint128 c = a + b;
        require(c >= a, "Pool: Dai reserves too high");

        return c;
    }

    /// @dev Overflow-protected substraction, from OpenZeppelin
    function sub(uint128 a, uint128 b) internal pure returns (uint128) {
        require(b <= a, "Pool: fyDai reserves too low");
        uint128 c = a - b;

        return c;
    }

    /// @dev Safe casting from uint256 to uint128
    function toUint128(uint256 x) internal pure returns(uint128) {
        require(
            x <= type(uint128).max,
            "Pool: Cast overflow"
        );
        return uint128(x);
    }

    /// @dev Safe casting from uint256 to int256
    function toInt256(uint256 x) internal pure returns(int256) {
        require(
            x <= uint256(type(int256).max),
            "Pool: Cast overflow"
        );
        return int256(x);
    }

    /// @dev Mint initial liquidity tokens.
    /// The liquidity provider needs to have called `dai.approve`
    /// @param daiIn The initial Dai liquidity to provide.
    function init(uint256 daiIn)
        internal
        beforeMaturity
        returns (uint256)
    {
        require(
            totalSupply() == 0,
            "Pool: Already initialized"
        );
        // no fyDai transferred, because initial fyDai deposit is entirely virtual
        dai.transferFrom(msg.sender, address(this), daiIn);
        _mint(msg.sender, daiIn);
        emit Liquidity(maturity, msg.sender, msg.sender, -toInt256(daiIn), 0, toInt256(daiIn));

        return daiIn;
    }

    /// @dev Mint liquidity tokens in exchange for adding dai and fyDai
    /// The liquidity provider needs to have called `dai.approve` and `fyDai.approve`.
    /// @param from Wallet providing the dai and fyDai. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the minted liquidity tokens.
    /// @param daiOffered Amount of `dai` being invested, an appropriate amount of `fyDai` to be invested alongside will be calculated and taken by this function from the caller.
    /// @return The amount of liquidity tokens minted.
    function mint(address from, address to, uint256 daiOffered)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns (uint256)
    {
        uint256 supply = totalSupply();
        if (supply == 0) return init(daiOffered);

        uint256 daiReserves = dai.balanceOf(address(this));
        // use the actual reserves rather than the virtual reserves
        uint256 fyDaiReserves = fyDai.balanceOf(address(this));
        uint256 tokensMinted = supply.mul(daiOffered).div(daiReserves);
        uint256 fyDaiRequired = fyDaiReserves.mul(tokensMinted).div(supply);

        require(daiReserves.add(daiOffered) <= type(uint128).max); // fyDaiReserves can't go over type(uint128).max
        require(supply.add(fyDaiReserves.add(fyDaiRequired)) <= type(uint128).max); // fyDaiReserves can't go over type(uint128).max

        require(dai.transferFrom(from, address(this), daiOffered));
        require(fyDai.transferFrom(from, address(this), fyDaiRequired));
        _mint(to, tokensMinted);
        emit Liquidity(maturity, from, to, -toInt256(daiOffered), -toInt256(fyDaiRequired), toInt256(tokensMinted));

        return tokensMinted;
    }

    /// @dev Burn liquidity tokens in exchange for dai and fyDai.
    /// The liquidity provider needs to have called `pool.approve`.
    /// @param from Wallet providing the liquidity tokens. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the dai and fyDai.
    /// @param tokensBurned Amount of liquidity tokens being burned.
    /// @return The amount of reserve tokens returned (daiTokens, fyDaiTokens).
    function burn(address from, address to, uint256 tokensBurned)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns (uint256, uint256)
    {
        uint256 supply = totalSupply();
        uint256 daiReserves = dai.balanceOf(address(this));
        // use the actual reserves rather than the virtual reserves
        uint256 daiReturned;
        uint256 fyDaiReturned;
        { // avoiding stack too deep
            uint256 fyDaiReserves = fyDai.balanceOf(address(this));
            daiReturned = tokensBurned.mul(daiReserves).div(supply);
            fyDaiReturned = tokensBurned.mul(fyDaiReserves).div(supply);
        }

        _burn(from, tokensBurned);
        dai.transfer(to, daiReturned);
        fyDai.transfer(to, fyDaiReturned);
        emit Liquidity(maturity, from, to, toInt256(daiReturned), toInt256(fyDaiReturned), -toInt256(tokensBurned));

        return (daiReturned, fyDaiReturned);
    }

    /// @dev Sell Dai for fyDai
    /// The trader needs to have called `dai.approve`
    /// @param from Wallet providing the dai being sold. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the fyDai being bought
    /// @param daiIn Amount of dai being sold that will be taken from the user's wallet
    /// @return Amount of fyDai that will be deposited on `to` wallet
    function sellDai(address from, address to, uint128 daiIn)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns(uint128)
    {
        uint128 fyDaiOut = sellDaiPreview(daiIn);

        dai.transferFrom(from, address(this), daiIn);
        fyDai.transfer(to, fyDaiOut);
        emit Trade(maturity, from, to, -toInt256(daiIn), toInt256(fyDaiOut));

        return fyDaiOut;
    }

    /// @dev Returns how much fyDai would be obtained by selling `daiIn` dai
    /// @param daiIn Amount of dai hypothetically sold.
    /// @return Amount of fyDai hypothetically bought.
    function sellDaiPreview(uint128 daiIn)
        public view override
        beforeMaturity
        returns(uint128)
    {
        uint128 daiReserves = getDaiReserves();
        uint128 fyDaiReserves = getFYDaiReserves();

        uint128 fyDaiOut = YieldMath.fyDaiOutForDaiIn(
            daiReserves,
            fyDaiReserves,
            daiIn,
            toUint128(maturity - now), // This can't be called after maturity
            k,
            g1
        );

        require(
            sub(fyDaiReserves, fyDaiOut) >= add(daiReserves, daiIn),
            "Pool: fyDai reserves too low"
        );

        return fyDaiOut;
    }

    /// @dev Buy Dai for fyDai
    /// The trader needs to have called `fyDai.approve`
    /// @param from Wallet providing the fyDai being sold. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the dai being bought
    /// @param daiOut Amount of dai being bought that will be deposited in `to` wallet
    /// @return Amount of fyDai that will be taken from `from` wallet
    function buyDai(address from, address to, uint128 daiOut)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns(uint128)
    {
        uint128 fyDaiIn = buyDaiPreview(daiOut);

        fyDai.transferFrom(from, address(this), fyDaiIn);
        dai.transfer(to, daiOut);
        emit Trade(maturity, from, to, toInt256(daiOut), -toInt256(fyDaiIn));

        return fyDaiIn;
    }

    /// @dev Returns how much fyDai would be required to buy `daiOut` dai.
    /// @param daiOut Amount of dai hypothetically desired.
    /// @return Amount of fyDai hypothetically required.
    function buyDaiPreview(uint128 daiOut)
        public view override
        beforeMaturity
        returns(uint128)
    {
        return YieldMath.fyDaiInForDaiOut(
            getDaiReserves(),
            getFYDaiReserves(),
            daiOut,
            toUint128(maturity - now), // This can't be called after maturity
            k,
            g2
        );
    }

    /// @dev Sell fyDai for Dai
    /// The trader needs to have called `fyDai.approve`
    /// @param from Wallet providing the fyDai being sold. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the dai being bought
    /// @param fyDaiIn Amount of fyDai being sold that will be taken from the user's wallet
    /// @return Amount of dai that will be deposited on `to` wallet
    function sellFYDai(address from, address to, uint128 fyDaiIn)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns(uint128)
    {
        uint128 daiOut = sellFYDaiPreview(fyDaiIn);

        fyDai.transferFrom(from, address(this), fyDaiIn);
        dai.transfer(to, daiOut);
        emit Trade(maturity, from, to, toInt256(daiOut), -toInt256(fyDaiIn));

        return daiOut;
    }

    /// @dev Returns how much dai would be obtained by selling `fyDaiIn` fyDai.
    /// @param fyDaiIn Amount of fyDai hypothetically sold.
    /// @return Amount of Dai hypothetically bought.
    function sellFYDaiPreview(uint128 fyDaiIn)
        public view override
        beforeMaturity
        returns(uint128)
    {
        return YieldMath.daiOutForFYDaiIn(
            getDaiReserves(),
            getFYDaiReserves(),
            fyDaiIn,
            toUint128(maturity - now), // This can't be called after maturity
            k,
            g2
        );
    }

    /// @dev Buy fyDai for dai
    /// The trader needs to have called `dai.approve`
    /// @param from Wallet providing the dai being sold. Must have approved the operator with `pool.addDelegate(operator)`.
    /// @param to Wallet receiving the fyDai being bought
    /// @param fyDaiOut Amount of fyDai being bought that will be deposited in `to` wallet
    /// @return Amount of dai that will be taken from `from` wallet
    function buyFYDai(address from, address to, uint128 fyDaiOut)
        external override
        onlyHolderOrDelegate(from, "Pool: Only Holder Or Delegate")
        returns(uint128)
    {
        uint128 daiIn = buyFYDaiPreview(fyDaiOut);

        dai.transferFrom(from, address(this), daiIn);
        fyDai.transfer(to, fyDaiOut);
        emit Trade(maturity, from, to, -toInt256(daiIn), toInt256(fyDaiOut));

        return daiIn;
    }


    /// @dev Returns how much dai would be required to buy `fyDaiOut` fyDai.
    /// @param fyDaiOut Amount of fyDai hypothetically desired.
    /// @return Amount of Dai hypothetically required.
    function buyFYDaiPreview(uint128 fyDaiOut)
        public view override
        beforeMaturity
        returns(uint128)
    {
        uint128 daiReserves = getDaiReserves();
        uint128 fyDaiReserves = getFYDaiReserves();

        uint128 daiIn = YieldMath.daiInForFYDaiOut(
            daiReserves,
            fyDaiReserves,
            fyDaiOut,
            toUint128(maturity - now), // This can't be called after maturity
            k,
            g1
        );

        require(
            sub(fyDaiReserves, fyDaiOut) >= add(daiReserves, daiIn),
            "Pool: fyDai reserves too low"
        );

        return daiIn;
    }

    /// @dev Returns the "virtual" fyDai reserves
    function getFYDaiReserves()
        public view override
        returns(uint128)
    {
        return toUint128(fyDai.balanceOf(address(this)).add(totalSupply()));
    }

    /// @dev Returns the Dai reserves
    function getDaiReserves()
        public view override
        returns(uint128)
    {
        return toUint128(dai.balanceOf(address(this)));
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"dai_","type":"address"},{"internalType":"address","name":"fyDai_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"Delegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"int256","name":"daiTokens","type":"int256"},{"indexed":false,"internalType":"int256","name":"fyDaiTokens","type":"int256"},{"indexed":false,"internalType":"int256","name":"poolTokens","type":"int256"}],"name":"Liquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"int256","name":"daiTokens","type":"int256"},{"indexed":false,"internalType":"int256","name":"fyDaiTokens","type":"int256"}],"name":"Trade","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":"DELEGABLE_DOMAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"addDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"addDelegateBySignature","outputs":[],"stateMutability":"nonpayable","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":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokensBurned","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"daiOut","type":"uint128"}],"name":"buyDai","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"daiOut","type":"uint128"}],"name":"buyDaiPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"fyDaiOut","type":"uint128"}],"name":"buyFYDai","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"fyDaiOut","type":"uint128"}],"name":"buyFYDaiPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dai","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"delegated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fyDai","outputs":[{"internalType":"contract IFYDai","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"g1","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"g2","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDaiReserves","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFYDaiReserves","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"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":"k","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturity","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"daiOffered","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"revokeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"daiIn","type":"uint128"}],"name":"sellDai","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"daiIn","type":"uint128"}],"name":"sellDaiPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"fyDaiIn","type":"uint128"}],"name":"sellFYDai","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"fyDaiIn","type":"uint128"}],"name":"sellFYDaiPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signatureCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

61012060408190527f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb76080528060526200549e823960405190819003605201902060c052503480156200005157600080fd5b506040516200554238038062005542833981810160405260808110156200007757600080fd5b81516020830151604080850180519151939592948301929184640100000000821115620000a357600080fd5b908301906020820185811115620000b957600080fd5b8251640100000000811182820188101715620000d457600080fd5b82525081516020918201929091019080838360005b8381101562000103578181015183820152602001620000e9565b50505050905090810190601f168015620001315780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200015557600080fd5b9083019060208201858111156200016b57600080fd5b82516401000000008111828201881017156200018657600080fd5b82525081516020918201929091019080838360005b83811015620001b55781810151838201526020016200019b565b50505050905090810190601f168015620001e35780820380516001836020036101000a031916815260200191505b50604052505050818181818160039080519060200190620002069291906200049d565b5080516200021c9060049060208401906200049d565b50506005805460ff19166012179055506040514690806052620054f08239604080516052928190038301812081830183526005825264165a595b1960da1b6020928301528251808401845260018152603160f81b908301528251808301919091527f0dc8618f4925c4319195a39ada16304f511bf885ff9f3d63bc6b0f3979e46fb6818401526000805160206200547e833981519152606082015260808101959095523060a08087019190915282518087038201815260c09096019283905285519590910194909420909352469291508190620054f08239604080519182900360520182208651602097880120838301835260018452603160f81b93880193909352815180880191909152808201929092526000805160206200547e833981519152606083015260808201939093523060a0808301919091528351808303909101815260c0820180855281519187019190912060e052600980546001600160a01b038c81166001600160a01b031992831617909255600a80548c84169216919091179081905563204f83f960e01b90925293516200041e9691909416945063204f83f99360c480840194509192909190829003018186803b158015620003e157600080fd5b505afa158015620003f6573d6000803e3d6000fd5b505050506040513d60208110156200040d57600080fd5b50516001600160e01b036200043a16565b60801b6001600160801b03191661010052506200053792505050565b60006001600160801b0382111562000499576040805162461bcd60e51b815260206004820152601360248201527f506f6f6c3a2043617374206f766572666c6f7700000000000000000000000000604482015290519081900360640190fd5b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004e057805160ff191683800117855562000510565b8280016001018555821562000510579182015b8281111562000510578251825591602001919060010190620004f3565b506200049992620005349250905b808211156200049957600081556001016200051e565b90565b60805160a05160c05160e0516101005160801c614ea0620005de60003980610b695280610cf55280610d7b5280611096528061133b528061144b52806114dd5280611607528061169952806116fe52806117845280611a475280611eaa5280612125528061270c52806134985280613614525080610c575280612254525080610c2a52806121e7525080610a285280610ccf5250806109c35280611ac35250614ea06000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806385561a341161013b578063c0bd65d7116100b8578063e71bdf411161007c578063e71bdf41146107b9578063f4b9fa75146107df578063f6b911bc146107e7578063f6bcbd3114610836578063fa352c001461086457610248565b8063c0bd65d7146106bc578063c6c3bbe6146106c4578063cc5783d3146106fa578063d505accf1461073a578063dd62ed3e1461078b57610248565b8063a9059cbb116100ff578063a9059cbb1461061a578063b26be92214610646578063b4f40c6114610686578063b5d832fe1461068e578063bdd8a366146106b457610248565b806385561a341461057457806395d89b411461059a57806398ba4aec146105a25780639ac95875146105c8578063a457c2d7146105ee57610248565b806339509351116101c95780636970a9241161018d5780636970a924146104bf57806370a08231146104e05780637543e39c1461050657806377d739f3146105465780637ecebe001461054e57610248565b8063395093511461041d578063459e414f146104495780634e20e952146104515780635f4d07dc1461047757806360561e051461047f57610248565b806323b872dd1161021057806323b872dd14610395578063284f4444146103cb57806330adf81f146103ef578063313ce567146103f75780633644e5151461041557610248565b806306fdde031461024d578063095ea7b3146102ca57806318160ddd1461030a5780631a28ff0514610324578063204f83f914610371575b600080fd5b61025561088a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561028f578181015183820152602001610277565b50505050905090810190601f1680156102bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102f6600480360360408110156102e057600080fd5b506001600160a01b038135169060200135610920565b604080519115158252519081900360200190f35b61031261093e565b60408051918252519081900360200190f35b61036f600480360360c081101561033a57600080fd5b506001600160a01b03813581169160208101359091169060408101359060ff6060820135169060808101359060a00135610944565b005b610379610b67565b604080516001600160801b039092168252519081900360200190f35b6102f6600480360360608110156103ab57600080fd5b506001600160a01b03813581169160208101359091169060400135610b8b565b6103d3610c19565b604080516001600160a01b039092168252519081900360200190f35b610312610c28565b6103ff610c4c565b6040805160ff9092168252519081900360200190f35b610312610c55565b6102f66004803603604081101561043357600080fd5b506001600160a01b038135169060200135610c79565b610312610ccd565b6103796004803603602081101561046757600080fd5b50356001600160801b0316610cf1565b610379610dbe565b6103796004803603606081101561049557600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316610e5b565b6104c761110f565b60408051600f92830b90920b8252519081900360200190f35b610312600480360360208110156104f657600080fd5b50356001600160a01b0316611122565b6103796004803603606081101561051c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b031661113d565b6103796113b2565b6103126004803603602081101561056457600080fd5b50356001600160a01b0316611435565b6103796004803603602081101561058a57600080fd5b50356001600160801b0316611447565b6102556115a2565b610379600480360360208110156105b857600080fd5b50356001600160801b0316611603565b610379600480360360208110156105de57600080fd5b50356001600160801b03166116fa565b6102f66004803603604081101561060457600080fd5b506001600160a01b0381351690602001356117c7565b6102f66004803603604081101561063057600080fd5b506001600160a01b038135169060200135611835565b6103796004803603606081101561065c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611849565b6104c7611a8d565b610312600480360360208110156106a457600080fd5b50356001600160a01b0316611a9c565b6104c7611aae565b610312611ac1565b610312600480360360608110156106da57600080fd5b506001600160a01b03813581169160208101359091169060400135611ae5565b6103796004803603606081101561071057600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611f27565b61036f600480360360e081101561075057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612168565b610312600480360360408110156107a157600080fd5b506001600160a01b0381358116916020013516612396565b61036f600480360360208110156107cf57600080fd5b50356001600160a01b03166123c1565b6103d36123ce565b61081d600480360360608110156107fd57600080fd5b506001600160a01b038135811691602081013590911690604001356123dd565b6040805192835260208301919091528051918290030190f35b6102f66004803603604081101561084c57600080fd5b506001600160a01b0381358116916020013516612788565b61036f6004803603602081101561087a57600080fd5b50356001600160a01b03166127a8565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b5050505050905090565b600061093461092d6127b2565b84846127b6565b5060015b92915050565b60025490565b42841015610999576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b6001600160a01b0380871660008181526006602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c08501825280519083012061190160f01b60e08601527f000000000000000000000000000000000000000000000000000000000000000060e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c2808401939192601f1981019281900390910190855afa158015610acb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610b015750886001600160a01b0316816001600160a01b0316145b610b52576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b610b5c89896128a2565b505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610b98848484612989565b610c0e84610ba46127b2565b610c0985604051806060016040528060288152602001614d50602891396001600160a01b038a16600090815260016020526040812090610be26127b2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff612af016565b6127b6565b5060015b9392505050565b600a546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610934610c866127b2565b84610c098560016000610c976127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612b4a16565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210610d61576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b610938610d6c6113b2565b610d74610dbe565b84610da9427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7268010d79435e50d79435612bfc565b6000610e56610e51610dce61093e565b600a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6020811015610e4357600080fd5b50519063ffffffff612b4a16565b612ba4565b905090565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480610ec557506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190610f4f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610f14578181015183820152602001610efc565b50505050905090810190601f168015610f415780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000610f5b856116fa565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b158015610fc157600080fd5b505af1158015610fd5573d6000803e3d6000fd5b505050506040513d6020811015610feb57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561104b57600080fd5b505af115801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f00000000000000000000000000000000000000000000000000000000000000006110c76001600160801b038616612df6565b6110d98a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925260000382820152519081900360600190a392505b50509392505050565b6103b66903e800000000000000005b0481565b6001600160a01b031660009081526020819052604090205490565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806111a757506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906111f45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061120085611603565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506040513d602081101561129057600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156112f057600080fd5b505af1158015611304573d6000803e3d6000fd5b505050506040513d602081101561131a57600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f000000000000000000000000000000000000000000000000000000000000000061136c6001600160801b038616612df6565b6000036113818a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925282820152519081900360600190a39695505050505050565b600954604080516370a0823160e01b81523060048201529051600092610e56926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561140457600080fd5b505afa158015611418573d6000803e3d6000fd5b505050506040513d602081101561142e57600080fd5b5051612ba4565b60086020526000908152604090205481565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b031642106114b7576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b60006114c16113b2565b905060006114cd610dbe565b9050600061151f83838761150b427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7267f333333333333333612e4a565b905061152b8386613027565b6001600160801b031661153e838361308d565b6001600160801b0316101561159a576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b949350505050565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210611673576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b600061167d6113b2565b90506000611689610dbe565b905060006116db8383876116c7427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7267f3333333333333336130fc565b90506116e78382613027565b6001600160801b031661153e838761308d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b0316421061176a576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b6109386117756113b2565b61177d610dbe565b846117b2427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7268010d79435e50d794356132e1565b60006109346117d46127b2565b84610c0985604051806060016040528060258152602001614e4660259139600160006117fe6127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff612af016565b60006109346118426127b2565b8484612989565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806118b357506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906119005760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061190c85611447565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561197257600080fd5b505af1158015611986573d6000803e3d6000fd5b505050506040513d602081101561199c57600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b505050506040513d6020811015611a2657600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000000000000611a786001600160801b038a16612df6565b600003611381866001600160801b0316612df6565b630784ce00600160401b61111e565b60066020526000908152604090205481565b6103e86903b6000000000000000061111e565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611b4f57506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611b9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611ba761093e565b905080611bbf57611bb785613494565b935050611106565b600954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c0a57600080fd5b505afa158015611c1e573d6000803e3d6000fd5b505050506040513d6020811015611c3457600080fd5b5051600a54604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611c8757600080fd5b505afa158015611c9b573d6000803e3d6000fd5b505050506040513d6020811015611cb157600080fd5b505190506000611cd783611ccb868b63ffffffff61367d16565b9063ffffffff6136d616565b90506000611cef85611ccb858563ffffffff61367d16565b90506001600160801b03611d09858b63ffffffff612b4a16565b1115611d1457600080fd5b6001600160801b03611d3c611d2f858463ffffffff612b4a16565b879063ffffffff612b4a16565b1115611d4757600080fd5b600954604080516323b872dd60e01b81526001600160a01b038e81166004830152306024830152604482018d9052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611da357600080fd5b505af1158015611db7573d6000803e3d6000fd5b505050506040513d6020811015611dcd57600080fd5b5051611dd857600080fd5b600a54604080516323b872dd60e01b81526001600160a01b038e8116600483015230602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611e3457600080fd5b505af1158015611e48573d6000803e3d6000fd5b505050506040513d6020811015611e5e57600080fd5b5051611e6957600080fd5b611e738a83613718565b896001600160a01b03168b6001600160a01b03167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000000000000611ed28d612df6565b600003611ede86612df6565b600003611eea88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a3509998505050505050505050565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611f9157506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611fde5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611fea85610cf1565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050506040513d602081101561207a57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156120da57600080fd5b505af11580156120ee573d6000803e3d6000fd5b505050506040513d602081101561210457600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f00000000000000000000000000000000000000000000000000000000000000006121566001600160801b038a16612df6565b6110d9866001600160801b0316612df6565b428410156121bd576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b6001600160a01b0380881660008181526008602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e08501825280519083012061190160f01b6101008601527f000000000000000000000000000000000000000000000000000000000000000061010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e2808401939192601f1981019281900390910190855afa1580156122f8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232e5750896001600160a01b0316816001600160a01b0316145b61237f576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b61238a8a8a8a6127b6565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6123cb33826128a2565b50565b6009546001600160a01b031681565b600080846040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b0316148061244857506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906124955760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b5060006124a061093e565b600954604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156124f157600080fd5b505afa158015612505573d6000803e3d6000fd5b505050506040513d602081101561251b57600080fd5b5051600a54604080516370a0823160e01b81523060048201529051929350600092839283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561257257600080fd5b505afa158015612586573d6000803e3d6000fd5b505050506040513d602081101561259c57600080fd5b505190506125b485611ccb8c8763ffffffff61367d16565b92506125ca85611ccb8c8463ffffffff61367d16565b9150506125d78b8a613814565b6009546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561262d57600080fd5b505af1158015612641573d6000803e3d6000fd5b505050506040513d602081101561265757600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505050506040513d60208110156126d957600080fd5b50506001600160a01b03808b16908c167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f000000000000000000000000000000000000000000000000000000000000000061273486612df6565b61273d86612df6565b6127468f612df6565b604080516001600160801b0390951685526020850193909352838301919091526000036060830152519081900360800190a3909a909950975050505050505050565b600760209081526000928352604080842090915290825290205460ff1681565b6123cb338261391c565b3390565b6001600160a01b0383166127fb5760405162461bcd60e51b8152600401808060200182810382526024815260200180614dde6024913960400191505060405180910390fd5b6001600160a01b0382166128405760405162461bcd60e51b8152600401808060200182810382526022815260200180614c7c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff161561291d576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b6001600160a01b03808316600081815260076020908152604080832094861680845294825291829020805460ff19166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b6001600160a01b0383166129ce5760405162461bcd60e51b8152600401808060200182810382526025815260200180614db96025913960400191505060405180910390fd5b6001600160a01b038216612a135760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0b6023913960400191505060405180910390fd5b612a1e8383836139fa565b612a6181604051806060016040528060268152602001614c9e602691396001600160a01b038616600090815260208190526040902054919063ffffffff612af016565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a96908263ffffffff612b4a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612b425760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b505050900390565b600082820183811015610c12576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160801b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b5090565b600080612c1a84612c15876001600160801b03166139ff565b613a1d565b90506000612c35600160401b612c308685613a1d565b613a54565b9050600081600f0b13612c7d576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b03808816908a1603600160801b8110612ce4576040805162461bcd60e51b815260206004820152601b60248201527f5969656c644d6174683a20546f6f206d75636820446169206f75740000000000604482015290519081900360640190fd5b6000612cf58284600160401b613a87565b612d048b85600160401b613a87565b612d138d86600160401b613a87565b01039050600160801b8110612d595760405162461bcd60e51b815260040180806020018281038252602c815260200180614c2e602c913960400191505060405180910390fd5b60008a6001600160801b0316612d7483600160401b87613a87565b039050600160801b8110612db95760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff8110612ddd576001600160801b03612de6565b8064e8d4a51000015b9c9b505050505050505050505050565b60006001600160ff1b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b600080612e6384612c15876001600160801b03166139ff565b90506000612e79600160401b612c308685613a1d565b9050600081600f0b13612ec1576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0389811690881601600160801b8110612f28576040805162461bcd60e51b815260206004820152601a60248201527f5969656c644d6174683a20546f6f206d7563682044616920696e000000000000604482015290519081900360640190fd5b6000612f398284600160401b613a87565b612f488b85600160401b613a87565b612f578d86600160401b613a87565b01039050600160801b8110612f9d5760405162461bcd60e51b8152600401808060200182810382526026815260200180614be56026913960400191505060405180910390fd5b6000612fae82600160401b86613a87565b8b6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b64e8d4a510008111613010576000612de6565b64e8d4a50fff19019b9a5050505050505050505050565b60008282016001600160801b038085169082161015610c12576040805162461bcd60e51b815260206004820152601b60248201527f506f6f6c3a2044616920726573657276657320746f6f20686967680000000000604482015290519081900360640190fd5b6000826001600160801b0316826001600160801b031611156130f6576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b50900390565b600080613121600160401b612c3085612c1588612c158b6001600160801b03166139ff565b9050600081600f0b13613169576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0380871690881603600160801b81106131d0576040805162461bcd60e51b815260206004820152601d60248201527f5969656c644d6174683a20546f6f206d756368206679446169206f7574000000604482015290519081900360640190fd5b60006131e18284600160401b613a87565b6131f08a85600160401b613a87565b6131ff8c86600160401b613a87565b01039050600160801b81106132455760405162461bcd60e51b815260040180806020018281038252602a815260200180614d05602a913960400191505060405180910390fd5b60008a6001600160801b031661326083600160401b87613a87565b039050600160801b81106132a55760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff81106132c9576001600160801b036132d2565b8064e8d4a51000015b9b9a5050505050505050505050565b6000806132fa84612c15876001600160801b03166139ff565b90506000613310600160401b612c308685613a1d565b9050600081600f0b13613358576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0388811690881601600160801b81106133bf576040805162461bcd60e51b815260206004820152601c60248201527f5969656c644d6174683a20546f6f206d75636820667944616920696e00000000604482015290519081900360640190fd5b60006133d08a84600160401b613a87565b6133df8385600160401b613a87565b6133ee8d86600160401b613a87565b03019050600160801b81106134345760405162461bcd60e51b8152600401808060200182810382526024815260200180614e226024913960400191505060405180910390fd5b600061344582600160401b86613a87565b8c6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210613504576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b61350c61093e565b1561355e576040805162461bcd60e51b815260206004820152601960248201527f506f6f6c3a20416c726561647920696e697469616c697a656400000000000000604482015290519081900360640190fd5b600954604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135b857600080fd5b505af11580156135cc573d6000803e3d6000fd5b505050506040513d60208110156135e257600080fd5b506135ef90503383613718565b33807fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f000000000000000000000000000000000000000000000000000000000000000061363c86612df6565b600003600061364a88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a35090565b60008261368c57506000610938565b8282028284828161369957fe5b0414610c125760405162461bcd60e51b8152600401808060200182810382526021815260200180614d2f6021913960400191505060405180910390fd5b6000610c1283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613b3d565b6001600160a01b038216613773576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61377f600083836139fa565b600254613792908263ffffffff612b4a16565b6002556001600160a01b0382166000908152602081905260409020546137be908263ffffffff612b4a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166138595760405162461bcd60e51b8152600401808060200182810382526021815260200180614d786021913960400191505060405180910390fd5b613865826000836139fa565b6138a881604051806060016040528060228152602001614c5a602291396001600160a01b038516600090815260208190526040902054919063ffffffff612af016565b6001600160a01b0383166000908152602081905260409020556002546138d4908263ffffffff613ba216565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff16613996576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b6001600160a01b038083166000818152600760209081526040808320948616808452948252808320805460ff191690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b505050565b6000677fffffffffffffff821115613a1657600080fd5b5060401b90565b6000600f83810b9083900b0260401d60016001607f1b03198112801590613a4b575060016001607f1b038113155b610c1257600080fd5b6000600f82810b9084900b0360016001607f1b03198112801590613a4b575060016001607f1b03811315610c1257600080fd5b60006001600160801b038216613a9c57600080fd5b6001600160801b038416613ac5576001600160801b038316613abd57600080fd5b506000610c12565b6000826001600160801b0316846001600160801b0316613ae487613be4565b6001600160801b03036001600160801b03160281613afe57fe5b0490506001600160801b03811115613b1a576000915050610c12565b613b2c816001600160801b030361442f565b6001600160801b0316915050610c12565b60008183613b8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000838581613b9857fe5b0495945050505050565b6000610c1283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612af0565b60006001600160801b038216613bf957600080fd5b6001600160801b038216607f60791b600160401b821015613c265760409190911b9060016001607f1b0319015b600160601b821015613c4d5760209190911b906f3fffffffffffffffffffffffffffffff19015b600160701b821015613c745760109190911b906f1fffffffffffffffffffffffffffffff19015b600160781b821015613c9b5760089190911b906f0fffffffffffffffffffffffffffffff19015b6001607c1b821015613cc25760049190911b906f07ffffffffffffffffffffffffffffff19015b6001607e1b821015613ce95760029190911b906f03ffffffffffffffffffffffffffffff19015b6001607f1b821015613d105760019190911b906f01ffffffffffffffffffffffffffffff19015b908002607f1c90600160801b8210613d305760019190911c90600160781b175b908002607f1c90600160801b8210613d505760019190911c90600160771b175b908002607f1c90600160801b8210613d705760019190911c90600160761b175b908002607f1c90600160801b8210613d905760019190911c90600160751b175b908002607f1c90600160801b8210613db05760019190911c90600160741b175b908002607f1c90600160801b8210613dd05760019190911c90600160731b175b908002607f1c90600160801b8210613df05760019190911c90600160721b175b908002607f1c90600160801b8210613e105760019190911c90600160711b175b908002607f1c90600160801b8210613e305760019190911c90600160701b175b908002607f1c90600160801b8210613e505760019190911c906001606f1b175b908002607f1c90600160801b8210613e705760019190911c906001606e1b175b908002607f1c90600160801b8210613e905760019190911c906001606d1b175b908002607f1c90600160801b8210613eb05760019190911c906001606c1b175b908002607f1c90600160801b8210613ed05760019190911c906001606b1b175b908002607f1c90600160801b8210613ef05760019190911c906001606a1b175b908002607f1c90600160801b8210613f105760019190911c90600160691b175b908002607f1c90600160801b8210613f305760019190911c90600160681b175b908002607f1c90600160801b8210613f505760019190911c90600160671b175b908002607f1c90600160801b8210613f705760019190911c90600160661b175b908002607f1c90600160801b8210613f905760019190911c90600160651b175b908002607f1c90600160801b8210613fb05760019190911c90600160641b175b908002607f1c90600160801b8210613fd05760019190911c90600160631b175b908002607f1c90600160801b8210613ff05760019190911c90600160621b175b908002607f1c90600160801b82106140105760019190911c90600160611b175b908002607f1c90600160801b82106140305760019190911c90600160601b175b908002607f1c90600160801b82106140505760019190911c906001605f1b175b908002607f1c90600160801b82106140705760019190911c906001605e1b175b908002607f1c90600160801b82106140905760019190911c906001605d1b175b908002607f1c90600160801b82106140b05760019190911c906001605c1b175b908002607f1c90600160801b82106140d05760019190911c906001605b1b175b908002607f1c90600160801b82106140f05760019190911c906001605a1b175b908002607f1c90600160801b82106141105760019190911c90600160591b175b908002607f1c90600160801b82106141305760019190911c90600160581b175b908002607f1c90600160801b82106141505760019190911c90600160571b175b908002607f1c90600160801b82106141705760019190911c90600160561b175b908002607f1c90600160801b82106141905760019190911c90600160551b175b908002607f1c90600160801b82106141b05760019190911c90600160541b175b908002607f1c90600160801b82106141d05760019190911c90600160531b175b908002607f1c90600160801b82106141f05760019190911c90600160521b175b908002607f1c90600160801b82106142105760019190911c90600160511b175b908002607f1c90600160801b82106142305760019190911c90600160501b175b908002607f1c90600160801b82106142505760019190911c906001604f1b175b908002607f1c90600160801b82106142705760019190911c906001604e1b175b908002607f1c90600160801b82106142905760019190911c906001604d1b175b908002607f1c90600160801b82106142b05760019190911c906001604c1b175b908002607f1c90600160801b82106142d05760019190911c906001604b1b175b908002607f1c90600160801b82106142f05760019190911c906001604a1b175b908002607f1c90600160801b82106143105760019190911c90600160491b175b908002607f1c90600160801b82106143305760019190911c90600160481b175b908002607f1c90600160801b82106143505760019190911c90600160471b175b908002607f1c90600160801b82106143705760019190911c90600160461b175b908002607f1c90600160801b82106143905760019190911c90600160451b175b908002607f1c90600160801b82106143b05760019190911c90600160441b175b908002607f1c90600160801b82106143d05760019190911c90600160431b175b908002607f1c90600160801b82106143f05760019190911c90600160421b175b908002607f1c90600160801b82106144105760019190911c90600160411b175b908002607f1c90600160801b8210610c1257600160401b179392505050565b60006001607f1b600160781b831615614458576fb504f333f9de6484597d89b3754abe9f02607f1c5b600160771b83161561447a576f9837f0518db8a96f46ad23182e42f6f602607f1c5b600160761b83161561449c576f8b95c1e3ea8bd6e6fbe4628758a53c9002607f1c5b600160751b8316156144be576f85aac367cc487b14c5c95b8c2154c1b202607f1c5b600160741b8316156144e0576f82cd8698ac2ba1d73e2a475b46520bff02607f1c5b600160731b831615614502576f8164d1f3bc0307737be56527bd14def402607f1c5b600160721b831615614524576f80b1ed4fd999ab6c25335719b6e6fd2002607f1c5b600160711b831615614546576f8058d7d2d5e5f6b094d589f608ee4aa202607f1c5b600160701b831615614568576f802c6436d0e04f50ff8ce94a6797b3ce02607f1c5b6001606f1b83161561458a576f8016302f174676283690dfe44d11d00802607f1c5b6001606e1b8316156145ac576f800b179c82028fd0945e54e2ae18f2f002607f1c5b6001606d1b8316156145ce576f80058baf7fee3b5d1c718b38e549cb9302607f1c5b6001606c1b8316156145f0576f8002c5d00fdcfcb6b6566a58c048be1f02607f1c5b6001606b1b831615614612576f800162e61bed4a48e84c2e1a463473d902607f1c5b6001606a1b831615614634576f8000b17292f702a3aa22beacca94901302607f1c5b600160691b831615614656576f800058b92abbae02030c5fa5256f41fe02607f1c5b600160681b831615614678576f80002c5c8dade4d71776c0f4dbea67d602607f1c5b600160671b83161561469a576f8000162e44eaf636526be456600bdbe402607f1c5b600160661b8316156146bc576f80000b1721fa7c188307016c1cd4e8b602607f1c5b600160651b8316156146de576f8000058b90de7e4cecfc487503488bb102607f1c5b600160641b831615614700576f800002c5c8678f36cbfce50a6de60b1402607f1c5b600160631b831615614722576f80000162e431db9f80b2347b5d62e51602607f1c5b600160621b831615614744576f800000b1721872d0c7b08cf1e011415202607f1c5b600160611b831615614766576f80000058b90c1aa8a5c3736cb77e8dff02607f1c5b600160601b831615614788576f8000002c5c8605a4635f2efc2362d97802607f1c5b6001605f1b8316156147aa576f800000162e4300e635cf4a109e3939bd02607f1c5b6001605e1b8316156147cc576f8000000b17217ff81bef9c551590cf8302607f1c5b6001605d1b8316156147ee576f800000058b90bfdd4e39cd52c0cfa27c02607f1c5b6001605c1b831615614810576f80000002c5c85fe6f72d669e0e76e41102607f1c5b6001605b1b831615614832576f8000000162e42ff18f9ad35186d0df2802607f1c5b6001605a1b831615614854576f80000000b17217f84cce71aa0dcfffe702607f1c5b600160591b831615614876576f8000000058b90bfc07a77ad56ed22aaa02607f1c5b600160581b831615614898576f800000002c5c85fdfc23cdead40da8d602607f1c5b600160571b8316156148ba576f80000000162e42fefc25eb1571853a6602607f1c5b600160561b8316156148dc576f800000000b17217f7d97f692baacded502607f1c5b600160551b8316156148fe576f80000000058b90bfbead3b8b5dd254d702607f1c5b600160541b831615614920576f8000000002c5c85fdf4eedd62f084e6702607f1c5b600160531b831615614942576f800000000162e42fefa58aef378bf58602607f1c5b600160521b831615614964576f8000000000b17217f7d24a78a3c7ef0202607f1c5b600160511b831615614986576f800000000058b90bfbe9067c93e474a602607f1c5b600160501b8316156149a8576f80000000002c5c85fdf47b8e5a72599f02607f1c5b6001604f1b8316156149ca576f8000000000162e42fefa3bdb315934a202607f1c5b6001604e1b8316156149ec576f80000000000b17217f7d1d7299b49c4602607f1c5b6001604d1b831615614a0e576f8000000000058b90bfbe8e9a8d1c4ea002607f1c5b6001604c1b831615614a30576f800000000002c5c85fdf4745969ea76f02607f1c5b6001604b1b831615614a52576f80000000000162e42fefa3a0df5373bf02607f1c5b6001604a1b831615614a74576f800000000000b17217f7d1cff4aac1e102607f1c5b600160491b831615614a96576f80000000000058b90bfbe8e7db95a2f102607f1c5b600160481b831615614ab8576f8000000000002c5c85fdf473e61ae1f802607f1c5b600160471b831615614ada576f800000000000162e42fefa39f121751c02607f1c5b600160461b831615614afc576f8000000000000b17217f7d1cf815bb9602607f1c5b600160451b831615614b1e576f800000000000058b90bfbe8e7bec1e0d02607f1c5b600160441b831615614b40576f80000000000002c5c85fdf473dee5f1702607f1c5b600160431b831615614b62576f8000000000000162e42fefa39ef5438f02607f1c5b600160421b831615614b84576f80000000000000b17217f7d1cf7a26c802607f1c5b600160411b831615614ba6576f8000000000000058b90bfbe8e7bcf4a402607f1c5b600160401b831615614bc8576f800000000000002c5c85fdf473de72a202607f1c5b607f607984901c811690036001600160801b03161c905091905056fe5969656c644d6174683a20496e73756666696369656e7420667944616920726573657276657345524332303a207472616e7366657220746f20746865207a65726f20616464726573735969656c644d6174683a20526573756c74696e6720667944616920726573657276657320746f6f206869676845524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63653f207773c457c66e004ab34e2ce7ae1fcafc7b4c3286f63997c87428014219155969656c644d6174683a20526f756e64696e6720696e6475636564206572726f725969656c644d6174683a20526573756c74696e672044616920726573657276657320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f2061646472657373506f6f6c3a204f6e6c7920486f6c646572204f722044656c656761746500000045524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735969656c644d6174683a20546f6f206661722066726f6d206d617475726974795969656c644d6174683a20496e73756666696369656e742044616920726573657276657345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220dfcf38324d56249e8a26c32edabb5f6f86fc1ce3ab9e6844ae333018550aedef64736f6c634300060a0033c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc65065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374290000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000269a30e0fd5231438017dc0438f818a80dc4464b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001b5969656c6420446169202d20323032312d30392d33302d506f6f6c0000000000000000000000000000000000000000000000000000000000000000000000000c66794461694c5032315365700000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c806385561a341161013b578063c0bd65d7116100b8578063e71bdf411161007c578063e71bdf41146107b9578063f4b9fa75146107df578063f6b911bc146107e7578063f6bcbd3114610836578063fa352c001461086457610248565b8063c0bd65d7146106bc578063c6c3bbe6146106c4578063cc5783d3146106fa578063d505accf1461073a578063dd62ed3e1461078b57610248565b8063a9059cbb116100ff578063a9059cbb1461061a578063b26be92214610646578063b4f40c6114610686578063b5d832fe1461068e578063bdd8a366146106b457610248565b806385561a341461057457806395d89b411461059a57806398ba4aec146105a25780639ac95875146105c8578063a457c2d7146105ee57610248565b806339509351116101c95780636970a9241161018d5780636970a924146104bf57806370a08231146104e05780637543e39c1461050657806377d739f3146105465780637ecebe001461054e57610248565b8063395093511461041d578063459e414f146104495780634e20e952146104515780635f4d07dc1461047757806360561e051461047f57610248565b806323b872dd1161021057806323b872dd14610395578063284f4444146103cb57806330adf81f146103ef578063313ce567146103f75780633644e5151461041557610248565b806306fdde031461024d578063095ea7b3146102ca57806318160ddd1461030a5780631a28ff0514610324578063204f83f914610371575b600080fd5b61025561088a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561028f578181015183820152602001610277565b50505050905090810190601f1680156102bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102f6600480360360408110156102e057600080fd5b506001600160a01b038135169060200135610920565b604080519115158252519081900360200190f35b61031261093e565b60408051918252519081900360200190f35b61036f600480360360c081101561033a57600080fd5b506001600160a01b03813581169160208101359091169060408101359060ff6060820135169060808101359060a00135610944565b005b610379610b67565b604080516001600160801b039092168252519081900360200190f35b6102f6600480360360608110156103ab57600080fd5b506001600160a01b03813581169160208101359091169060400135610b8b565b6103d3610c19565b604080516001600160a01b039092168252519081900360200190f35b610312610c28565b6103ff610c4c565b6040805160ff9092168252519081900360200190f35b610312610c55565b6102f66004803603604081101561043357600080fd5b506001600160a01b038135169060200135610c79565b610312610ccd565b6103796004803603602081101561046757600080fd5b50356001600160801b0316610cf1565b610379610dbe565b6103796004803603606081101561049557600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316610e5b565b6104c761110f565b60408051600f92830b90920b8252519081900360200190f35b610312600480360360208110156104f657600080fd5b50356001600160a01b0316611122565b6103796004803603606081101561051c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b031661113d565b6103796113b2565b6103126004803603602081101561056457600080fd5b50356001600160a01b0316611435565b6103796004803603602081101561058a57600080fd5b50356001600160801b0316611447565b6102556115a2565b610379600480360360208110156105b857600080fd5b50356001600160801b0316611603565b610379600480360360208110156105de57600080fd5b50356001600160801b03166116fa565b6102f66004803603604081101561060457600080fd5b506001600160a01b0381351690602001356117c7565b6102f66004803603604081101561063057600080fd5b506001600160a01b038135169060200135611835565b6103796004803603606081101561065c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611849565b6104c7611a8d565b610312600480360360208110156106a457600080fd5b50356001600160a01b0316611a9c565b6104c7611aae565b610312611ac1565b610312600480360360608110156106da57600080fd5b506001600160a01b03813581169160208101359091169060400135611ae5565b6103796004803603606081101561071057600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611f27565b61036f600480360360e081101561075057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612168565b610312600480360360408110156107a157600080fd5b506001600160a01b0381358116916020013516612396565b61036f600480360360208110156107cf57600080fd5b50356001600160a01b03166123c1565b6103d36123ce565b61081d600480360360608110156107fd57600080fd5b506001600160a01b038135811691602081013590911690604001356123dd565b6040805192835260208301919091528051918290030190f35b6102f66004803603604081101561084c57600080fd5b506001600160a01b0381358116916020013516612788565b61036f6004803603602081101561087a57600080fd5b50356001600160a01b03166127a8565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b5050505050905090565b600061093461092d6127b2565b84846127b6565b5060015b92915050565b60025490565b42841015610999576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b6001600160a01b0380871660008181526006602090815260408083208054600180820190925582517f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb78186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c08501825280519083012061190160f01b60e08601527fe2b92f8b92efffa336aff8f05121940c9f5a9c97ff9f331f87c151cbefc2e92660e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c2808401939192601f1981019281900390910190855afa158015610acb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610b015750886001600160a01b0316816001600160a01b0316145b610b52576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b610b5c89896128a2565b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000061564f7f81565b6000610b98848484612989565b610c0e84610ba46127b2565b610c0985604051806060016040528060288152602001614d50602891396001600160a01b038a16600090815260016020526040812090610be26127b2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff612af016565b6127b6565b5060015b9392505050565b600a546001600160a01b031681565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b7f9b1884898dba8a5776254bad93c6f899dd152886df4c28934639198013222d7781565b6000610934610c866127b2565b84610c098560016000610c976127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612b4a16565b7fe2b92f8b92efffa336aff8f05121940c9f5a9c97ff9f331f87c151cbefc2e92681565b60007f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b03164210610d61576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b610938610d6c6113b2565b610d74610dbe565b84610da9427f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b031603612ba4565b64220c523d7268010d79435e50d79435612bfc565b6000610e56610e51610dce61093e565b600a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6020811015610e4357600080fd5b50519063ffffffff612b4a16565b612ba4565b905090565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480610ec557506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190610f4f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610f14578181015183820152602001610efc565b50505050905090810190601f168015610f415780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000610f5b856116fa565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b158015610fc157600080fd5b505af1158015610fd5573d6000803e3d6000fd5b505050506040513d6020811015610feb57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561104b57600080fd5b505af115801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061564f7f6110c76001600160801b038616612df6565b6110d98a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925260000382820152519081900360600190a392505b50509392505050565b6103b66903e800000000000000005b0481565b6001600160a01b031660009081526020819052604090205490565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806111a757506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906111f45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061120085611603565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506040513d602081101561129057600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156112f057600080fd5b505af1158015611304573d6000803e3d6000fd5b505050506040513d602081101561131a57600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061564f7f61136c6001600160801b038616612df6565b6000036113818a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925282820152519081900360600190a39695505050505050565b600954604080516370a0823160e01b81523060048201529051600092610e56926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561140457600080fd5b505afa158015611418573d6000803e3d6000fd5b505050506040513d602081101561142e57600080fd5b5051612ba4565b60086020526000908152604090205481565b60007f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b031642106114b7576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b60006114c16113b2565b905060006114cd610dbe565b9050600061151f83838761150b427f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b031603612ba4565b64220c523d7267f333333333333333612e4a565b905061152b8386613027565b6001600160801b031661153e838361308d565b6001600160801b0316101561159a576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b949350505050565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b60007f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b03164210611673576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b600061167d6113b2565b90506000611689610dbe565b905060006116db8383876116c7427f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b031603612ba4565b64220c523d7267f3333333333333336130fc565b90506116e78382613027565b6001600160801b031661153e838761308d565b60007f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b0316421061176a576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b6109386117756113b2565b61177d610dbe565b846117b2427f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b031603612ba4565b64220c523d7268010d79435e50d794356132e1565b60006109346117d46127b2565b84610c0985604051806060016040528060258152602001614e4660259139600160006117fe6127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff612af016565b60006109346118426127b2565b8484612989565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806118b357506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906119005760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061190c85611447565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561197257600080fd5b505af1158015611986573d6000803e3d6000fd5b505050506040513d602081101561199c57600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b505050506040513d6020811015611a2657600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061564f7f611a786001600160801b038a16612df6565b600003611381866001600160801b0316612df6565b630784ce00600160401b61111e565b60066020526000908152604090205481565b6103e86903b6000000000000000061111e565b7f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb781565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611b4f57506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611b9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611ba761093e565b905080611bbf57611bb785613494565b935050611106565b600954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c0a57600080fd5b505afa158015611c1e573d6000803e3d6000fd5b505050506040513d6020811015611c3457600080fd5b5051600a54604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611c8757600080fd5b505afa158015611c9b573d6000803e3d6000fd5b505050506040513d6020811015611cb157600080fd5b505190506000611cd783611ccb868b63ffffffff61367d16565b9063ffffffff6136d616565b90506000611cef85611ccb858563ffffffff61367d16565b90506001600160801b03611d09858b63ffffffff612b4a16565b1115611d1457600080fd5b6001600160801b03611d3c611d2f858463ffffffff612b4a16565b879063ffffffff612b4a16565b1115611d4757600080fd5b600954604080516323b872dd60e01b81526001600160a01b038e81166004830152306024830152604482018d9052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611da357600080fd5b505af1158015611db7573d6000803e3d6000fd5b505050506040513d6020811015611dcd57600080fd5b5051611dd857600080fd5b600a54604080516323b872dd60e01b81526001600160a01b038e8116600483015230602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611e3457600080fd5b505af1158015611e48573d6000803e3d6000fd5b505050506040513d6020811015611e5e57600080fd5b5051611e6957600080fd5b611e738a83613718565b896001600160a01b03168b6001600160a01b03167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061564f7f611ed28d612df6565b600003611ede86612df6565b600003611eea88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a3509998505050505050505050565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611f9157506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611fde5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611fea85610cf1565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050506040513d602081101561207a57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156120da57600080fd5b505af11580156120ee573d6000803e3d6000fd5b505050506040513d602081101561210457600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061564f7f6121566001600160801b038a16612df6565b6110d9866001600160801b0316612df6565b428410156121bd576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b6001600160a01b0380881660008181526008602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e08501825280519083012061190160f01b6101008601527f9b1884898dba8a5776254bad93c6f899dd152886df4c28934639198013222d7761010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e2808401939192601f1981019281900390910190855afa1580156122f8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232e5750896001600160a01b0316816001600160a01b0316145b61237f576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b61238a8a8a8a6127b6565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6123cb33826128a2565b50565b6009546001600160a01b031681565b600080846040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b0316148061244857506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906124955760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b5060006124a061093e565b600954604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156124f157600080fd5b505afa158015612505573d6000803e3d6000fd5b505050506040513d602081101561251b57600080fd5b5051600a54604080516370a0823160e01b81523060048201529051929350600092839283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561257257600080fd5b505afa158015612586573d6000803e3d6000fd5b505050506040513d602081101561259c57600080fd5b505190506125b485611ccb8c8763ffffffff61367d16565b92506125ca85611ccb8c8463ffffffff61367d16565b9150506125d78b8a613814565b6009546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561262d57600080fd5b505af1158015612641573d6000803e3d6000fd5b505050506040513d602081101561265757600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505050506040513d60208110156126d957600080fd5b50506001600160a01b03808b16908c167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061564f7f61273486612df6565b61273d86612df6565b6127468f612df6565b604080516001600160801b0390951685526020850193909352838301919091526000036060830152519081900360800190a3909a909950975050505050505050565b600760209081526000928352604080842090915290825290205460ff1681565b6123cb338261391c565b3390565b6001600160a01b0383166127fb5760405162461bcd60e51b8152600401808060200182810382526024815260200180614dde6024913960400191505060405180910390fd5b6001600160a01b0382166128405760405162461bcd60e51b8152600401808060200182810382526022815260200180614c7c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff161561291d576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b6001600160a01b03808316600081815260076020908152604080832094861680845294825291829020805460ff19166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b6001600160a01b0383166129ce5760405162461bcd60e51b8152600401808060200182810382526025815260200180614db96025913960400191505060405180910390fd5b6001600160a01b038216612a135760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0b6023913960400191505060405180910390fd5b612a1e8383836139fa565b612a6181604051806060016040528060268152602001614c9e602691396001600160a01b038616600090815260208190526040902054919063ffffffff612af016565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a96908263ffffffff612b4a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612b425760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b505050900390565b600082820183811015610c12576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160801b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b5090565b600080612c1a84612c15876001600160801b03166139ff565b613a1d565b90506000612c35600160401b612c308685613a1d565b613a54565b9050600081600f0b13612c7d576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b03808816908a1603600160801b8110612ce4576040805162461bcd60e51b815260206004820152601b60248201527f5969656c644d6174683a20546f6f206d75636820446169206f75740000000000604482015290519081900360640190fd5b6000612cf58284600160401b613a87565b612d048b85600160401b613a87565b612d138d86600160401b613a87565b01039050600160801b8110612d595760405162461bcd60e51b815260040180806020018281038252602c815260200180614c2e602c913960400191505060405180910390fd5b60008a6001600160801b0316612d7483600160401b87613a87565b039050600160801b8110612db95760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff8110612ddd576001600160801b03612de6565b8064e8d4a51000015b9c9b505050505050505050505050565b60006001600160ff1b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b600080612e6384612c15876001600160801b03166139ff565b90506000612e79600160401b612c308685613a1d565b9050600081600f0b13612ec1576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0389811690881601600160801b8110612f28576040805162461bcd60e51b815260206004820152601a60248201527f5969656c644d6174683a20546f6f206d7563682044616920696e000000000000604482015290519081900360640190fd5b6000612f398284600160401b613a87565b612f488b85600160401b613a87565b612f578d86600160401b613a87565b01039050600160801b8110612f9d5760405162461bcd60e51b8152600401808060200182810382526026815260200180614be56026913960400191505060405180910390fd5b6000612fae82600160401b86613a87565b8b6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b64e8d4a510008111613010576000612de6565b64e8d4a50fff19019b9a5050505050505050505050565b60008282016001600160801b038085169082161015610c12576040805162461bcd60e51b815260206004820152601b60248201527f506f6f6c3a2044616920726573657276657320746f6f20686967680000000000604482015290519081900360640190fd5b6000826001600160801b0316826001600160801b031611156130f6576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b50900390565b600080613121600160401b612c3085612c1588612c158b6001600160801b03166139ff565b9050600081600f0b13613169576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0380871690881603600160801b81106131d0576040805162461bcd60e51b815260206004820152601d60248201527f5969656c644d6174683a20546f6f206d756368206679446169206f7574000000604482015290519081900360640190fd5b60006131e18284600160401b613a87565b6131f08a85600160401b613a87565b6131ff8c86600160401b613a87565b01039050600160801b81106132455760405162461bcd60e51b815260040180806020018281038252602a815260200180614d05602a913960400191505060405180910390fd5b60008a6001600160801b031661326083600160401b87613a87565b039050600160801b81106132a55760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff81106132c9576001600160801b036132d2565b8064e8d4a51000015b9b9a5050505050505050505050565b6000806132fa84612c15876001600160801b03166139ff565b90506000613310600160401b612c308685613a1d565b9050600081600f0b13613358576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0388811690881601600160801b81106133bf576040805162461bcd60e51b815260206004820152601c60248201527f5969656c644d6174683a20546f6f206d75636820667944616920696e00000000604482015290519081900360640190fd5b60006133d08a84600160401b613a87565b6133df8385600160401b613a87565b6133ee8d86600160401b613a87565b03019050600160801b81106134345760405162461bcd60e51b8152600401808060200182810382526024815260200180614e226024913960400191505060405180910390fd5b600061344582600160401b86613a87565b8c6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000061564f7f6001600160801b03164210613504576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b61350c61093e565b1561355e576040805162461bcd60e51b815260206004820152601960248201527f506f6f6c3a20416c726561647920696e697469616c697a656400000000000000604482015290519081900360640190fd5b600954604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135b857600080fd5b505af11580156135cc573d6000803e3d6000fd5b505050506040513d60208110156135e257600080fd5b506135ef90503383613718565b33807fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061564f7f61363c86612df6565b600003600061364a88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a35090565b60008261368c57506000610938565b8282028284828161369957fe5b0414610c125760405162461bcd60e51b8152600401808060200182810382526021815260200180614d2f6021913960400191505060405180910390fd5b6000610c1283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613b3d565b6001600160a01b038216613773576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61377f600083836139fa565b600254613792908263ffffffff612b4a16565b6002556001600160a01b0382166000908152602081905260409020546137be908263ffffffff612b4a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166138595760405162461bcd60e51b8152600401808060200182810382526021815260200180614d786021913960400191505060405180910390fd5b613865826000836139fa565b6138a881604051806060016040528060228152602001614c5a602291396001600160a01b038516600090815260208190526040902054919063ffffffff612af016565b6001600160a01b0383166000908152602081905260409020556002546138d4908263ffffffff613ba216565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff16613996576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b6001600160a01b038083166000818152600760209081526040808320948616808452948252808320805460ff191690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b505050565b6000677fffffffffffffff821115613a1657600080fd5b5060401b90565b6000600f83810b9083900b0260401d60016001607f1b03198112801590613a4b575060016001607f1b038113155b610c1257600080fd5b6000600f82810b9084900b0360016001607f1b03198112801590613a4b575060016001607f1b03811315610c1257600080fd5b60006001600160801b038216613a9c57600080fd5b6001600160801b038416613ac5576001600160801b038316613abd57600080fd5b506000610c12565b6000826001600160801b0316846001600160801b0316613ae487613be4565b6001600160801b03036001600160801b03160281613afe57fe5b0490506001600160801b03811115613b1a576000915050610c12565b613b2c816001600160801b030361442f565b6001600160801b0316915050610c12565b60008183613b8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000838581613b9857fe5b0495945050505050565b6000610c1283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612af0565b60006001600160801b038216613bf957600080fd5b6001600160801b038216607f60791b600160401b821015613c265760409190911b9060016001607f1b0319015b600160601b821015613c4d5760209190911b906f3fffffffffffffffffffffffffffffff19015b600160701b821015613c745760109190911b906f1fffffffffffffffffffffffffffffff19015b600160781b821015613c9b5760089190911b906f0fffffffffffffffffffffffffffffff19015b6001607c1b821015613cc25760049190911b906f07ffffffffffffffffffffffffffffff19015b6001607e1b821015613ce95760029190911b906f03ffffffffffffffffffffffffffffff19015b6001607f1b821015613d105760019190911b906f01ffffffffffffffffffffffffffffff19015b908002607f1c90600160801b8210613d305760019190911c90600160781b175b908002607f1c90600160801b8210613d505760019190911c90600160771b175b908002607f1c90600160801b8210613d705760019190911c90600160761b175b908002607f1c90600160801b8210613d905760019190911c90600160751b175b908002607f1c90600160801b8210613db05760019190911c90600160741b175b908002607f1c90600160801b8210613dd05760019190911c90600160731b175b908002607f1c90600160801b8210613df05760019190911c90600160721b175b908002607f1c90600160801b8210613e105760019190911c90600160711b175b908002607f1c90600160801b8210613e305760019190911c90600160701b175b908002607f1c90600160801b8210613e505760019190911c906001606f1b175b908002607f1c90600160801b8210613e705760019190911c906001606e1b175b908002607f1c90600160801b8210613e905760019190911c906001606d1b175b908002607f1c90600160801b8210613eb05760019190911c906001606c1b175b908002607f1c90600160801b8210613ed05760019190911c906001606b1b175b908002607f1c90600160801b8210613ef05760019190911c906001606a1b175b908002607f1c90600160801b8210613f105760019190911c90600160691b175b908002607f1c90600160801b8210613f305760019190911c90600160681b175b908002607f1c90600160801b8210613f505760019190911c90600160671b175b908002607f1c90600160801b8210613f705760019190911c90600160661b175b908002607f1c90600160801b8210613f905760019190911c90600160651b175b908002607f1c90600160801b8210613fb05760019190911c90600160641b175b908002607f1c90600160801b8210613fd05760019190911c90600160631b175b908002607f1c90600160801b8210613ff05760019190911c90600160621b175b908002607f1c90600160801b82106140105760019190911c90600160611b175b908002607f1c90600160801b82106140305760019190911c90600160601b175b908002607f1c90600160801b82106140505760019190911c906001605f1b175b908002607f1c90600160801b82106140705760019190911c906001605e1b175b908002607f1c90600160801b82106140905760019190911c906001605d1b175b908002607f1c90600160801b82106140b05760019190911c906001605c1b175b908002607f1c90600160801b82106140d05760019190911c906001605b1b175b908002607f1c90600160801b82106140f05760019190911c906001605a1b175b908002607f1c90600160801b82106141105760019190911c90600160591b175b908002607f1c90600160801b82106141305760019190911c90600160581b175b908002607f1c90600160801b82106141505760019190911c90600160571b175b908002607f1c90600160801b82106141705760019190911c90600160561b175b908002607f1c90600160801b82106141905760019190911c90600160551b175b908002607f1c90600160801b82106141b05760019190911c90600160541b175b908002607f1c90600160801b82106141d05760019190911c90600160531b175b908002607f1c90600160801b82106141f05760019190911c90600160521b175b908002607f1c90600160801b82106142105760019190911c90600160511b175b908002607f1c90600160801b82106142305760019190911c90600160501b175b908002607f1c90600160801b82106142505760019190911c906001604f1b175b908002607f1c90600160801b82106142705760019190911c906001604e1b175b908002607f1c90600160801b82106142905760019190911c906001604d1b175b908002607f1c90600160801b82106142b05760019190911c906001604c1b175b908002607f1c90600160801b82106142d05760019190911c906001604b1b175b908002607f1c90600160801b82106142f05760019190911c906001604a1b175b908002607f1c90600160801b82106143105760019190911c90600160491b175b908002607f1c90600160801b82106143305760019190911c90600160481b175b908002607f1c90600160801b82106143505760019190911c90600160471b175b908002607f1c90600160801b82106143705760019190911c90600160461b175b908002607f1c90600160801b82106143905760019190911c90600160451b175b908002607f1c90600160801b82106143b05760019190911c90600160441b175b908002607f1c90600160801b82106143d05760019190911c90600160431b175b908002607f1c90600160801b82106143f05760019190911c90600160421b175b908002607f1c90600160801b82106144105760019190911c90600160411b175b908002607f1c90600160801b8210610c1257600160401b179392505050565b60006001607f1b600160781b831615614458576fb504f333f9de6484597d89b3754abe9f02607f1c5b600160771b83161561447a576f9837f0518db8a96f46ad23182e42f6f602607f1c5b600160761b83161561449c576f8b95c1e3ea8bd6e6fbe4628758a53c9002607f1c5b600160751b8316156144be576f85aac367cc487b14c5c95b8c2154c1b202607f1c5b600160741b8316156144e0576f82cd8698ac2ba1d73e2a475b46520bff02607f1c5b600160731b831615614502576f8164d1f3bc0307737be56527bd14def402607f1c5b600160721b831615614524576f80b1ed4fd999ab6c25335719b6e6fd2002607f1c5b600160711b831615614546576f8058d7d2d5e5f6b094d589f608ee4aa202607f1c5b600160701b831615614568576f802c6436d0e04f50ff8ce94a6797b3ce02607f1c5b6001606f1b83161561458a576f8016302f174676283690dfe44d11d00802607f1c5b6001606e1b8316156145ac576f800b179c82028fd0945e54e2ae18f2f002607f1c5b6001606d1b8316156145ce576f80058baf7fee3b5d1c718b38e549cb9302607f1c5b6001606c1b8316156145f0576f8002c5d00fdcfcb6b6566a58c048be1f02607f1c5b6001606b1b831615614612576f800162e61bed4a48e84c2e1a463473d902607f1c5b6001606a1b831615614634576f8000b17292f702a3aa22beacca94901302607f1c5b600160691b831615614656576f800058b92abbae02030c5fa5256f41fe02607f1c5b600160681b831615614678576f80002c5c8dade4d71776c0f4dbea67d602607f1c5b600160671b83161561469a576f8000162e44eaf636526be456600bdbe402607f1c5b600160661b8316156146bc576f80000b1721fa7c188307016c1cd4e8b602607f1c5b600160651b8316156146de576f8000058b90de7e4cecfc487503488bb102607f1c5b600160641b831615614700576f800002c5c8678f36cbfce50a6de60b1402607f1c5b600160631b831615614722576f80000162e431db9f80b2347b5d62e51602607f1c5b600160621b831615614744576f800000b1721872d0c7b08cf1e011415202607f1c5b600160611b831615614766576f80000058b90c1aa8a5c3736cb77e8dff02607f1c5b600160601b831615614788576f8000002c5c8605a4635f2efc2362d97802607f1c5b6001605f1b8316156147aa576f800000162e4300e635cf4a109e3939bd02607f1c5b6001605e1b8316156147cc576f8000000b17217ff81bef9c551590cf8302607f1c5b6001605d1b8316156147ee576f800000058b90bfdd4e39cd52c0cfa27c02607f1c5b6001605c1b831615614810576f80000002c5c85fe6f72d669e0e76e41102607f1c5b6001605b1b831615614832576f8000000162e42ff18f9ad35186d0df2802607f1c5b6001605a1b831615614854576f80000000b17217f84cce71aa0dcfffe702607f1c5b600160591b831615614876576f8000000058b90bfc07a77ad56ed22aaa02607f1c5b600160581b831615614898576f800000002c5c85fdfc23cdead40da8d602607f1c5b600160571b8316156148ba576f80000000162e42fefc25eb1571853a6602607f1c5b600160561b8316156148dc576f800000000b17217f7d97f692baacded502607f1c5b600160551b8316156148fe576f80000000058b90bfbead3b8b5dd254d702607f1c5b600160541b831615614920576f8000000002c5c85fdf4eedd62f084e6702607f1c5b600160531b831615614942576f800000000162e42fefa58aef378bf58602607f1c5b600160521b831615614964576f8000000000b17217f7d24a78a3c7ef0202607f1c5b600160511b831615614986576f800000000058b90bfbe9067c93e474a602607f1c5b600160501b8316156149a8576f80000000002c5c85fdf47b8e5a72599f02607f1c5b6001604f1b8316156149ca576f8000000000162e42fefa3bdb315934a202607f1c5b6001604e1b8316156149ec576f80000000000b17217f7d1d7299b49c4602607f1c5b6001604d1b831615614a0e576f8000000000058b90bfbe8e9a8d1c4ea002607f1c5b6001604c1b831615614a30576f800000000002c5c85fdf4745969ea76f02607f1c5b6001604b1b831615614a52576f80000000000162e42fefa3a0df5373bf02607f1c5b6001604a1b831615614a74576f800000000000b17217f7d1cff4aac1e102607f1c5b600160491b831615614a96576f80000000000058b90bfbe8e7db95a2f102607f1c5b600160481b831615614ab8576f8000000000002c5c85fdf473e61ae1f802607f1c5b600160471b831615614ada576f800000000000162e42fefa39f121751c02607f1c5b600160461b831615614afc576f8000000000000b17217f7d1cf815bb9602607f1c5b600160451b831615614b1e576f800000000000058b90bfbe8e7bec1e0d02607f1c5b600160441b831615614b40576f80000000000002c5c85fdf473dee5f1702607f1c5b600160431b831615614b62576f8000000000000162e42fefa39ef5438f02607f1c5b600160421b831615614b84576f80000000000000b17217f7d1cf7a26c802607f1c5b600160411b831615614ba6576f8000000000000058b90bfbe8e7bcf4a402607f1c5b600160401b831615614bc8576f800000000000002c5c85fdf473de72a202607f1c5b607f607984901c811690036001600160801b03161c905091905056fe5969656c644d6174683a20496e73756666696369656e7420667944616920726573657276657345524332303a207472616e7366657220746f20746865207a65726f20616464726573735969656c644d6174683a20526573756c74696e6720667944616920726573657276657320746f6f206869676845524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63653f207773c457c66e004ab34e2ce7ae1fcafc7b4c3286f63997c87428014219155969656c644d6174683a20526f756e64696e6720696e6475636564206572726f725969656c644d6174683a20526573756c74696e672044616920726573657276657320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f2061646472657373506f6f6c3a204f6e6c7920486f6c646572204f722044656c656761746500000045524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735969656c644d6174683a20546f6f206661722066726f6d206d617475726974795969656c644d6174683a20496e73756666696369656e742044616920726573657276657345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220dfcf38324d56249e8a26c32edabb5f6f86fc1ce3ab9e6844ae333018550aedef64736f6c634300060a0033

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

0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000269a30e0fd5231438017dc0438f818a80dc4464b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001b5969656c6420446169202d20323032312d30392d33302d506f6f6c0000000000000000000000000000000000000000000000000000000000000000000000000c66794461694c5032315365700000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : dai_ (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [1] : fyDai_ (address): 0x269A30E0fD5231438017dC0438f818A80dC4464B
Arg [2] : name_ (string): Yield Dai - 2021-09-30-Pool
Arg [3] : symbol_ (string): fyDaiLP21Sep

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [1] : 000000000000000000000000269a30e0fd5231438017dc0438f818a80dc4464b
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000001b
Arg [5] : 5969656c6420446169202d20323032312d30392d33302d506f6f6c0000000000
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [7] : 66794461694c5032315365700000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

95763:13304:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17592:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19698:169;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;19698:169:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;18667:100;;;:::i;:::-;;;;;;;;;;;;;;;;86841:873;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;86841:873:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;96570:33;;;:::i;:::-;;;;-1:-1:-1;;;;;96570:33:0;;;;;;;;;;;;;;20341:321;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;20341:321:0;;;;;;;;;;;;;;;;;:::i;96645:28::-;;;:::i;:::-;;;;-1:-1:-1;;;;;96645:28:0;;;;;;;;;;;;;;90940:138;;;:::i;18519:83::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;91085:41;;;:::i;21071:218::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;21071:218:0;;;;;;;;:::i;85475:41::-;;;:::i;104997:384::-;;;;;;;;;;;;;;;;-1:-1:-1;104997:384:0;-1:-1:-1;;;;;104997:384:0;;:::i;108690:175::-;;;:::i;105825:451::-;;;;;;;;;;;;;;;;-1:-1:-1;105825:451:0;;-1:-1:-1;;;;;105825:451:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;105825:451:0;;:::i;96377:63::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;18830:119;;;;;;;;;;;;;;;;-1:-1:-1;18830:119:0;-1:-1:-1;;;;;18830:119:0;;:::i;107309:449::-;;;;;;;;;;;;;;;;-1:-1:-1;107309:449:0;;-1:-1:-1;;;;;107309:449:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;107309:449:0;;:::i;108912:152::-;;;:::i;90880:51::-;;;;;;;;;;;;;;;;-1:-1:-1;90880:51:0;-1:-1:-1;;;;;90880:51:0;;:::i;103246:663::-;;;;;;;;;;;;;;;;-1:-1:-1;103246:663:0;-1:-1:-1;;;;;103246:663:0;;:::i;17794:87::-;;;:::i;107967:664::-;;;;;;;;;;;;;;;;-1:-1:-1;107967:664:0;-1:-1:-1;;;;;107967:664:0;;:::i;106480:389::-;;;;;;;;;;;;;;;;-1:-1:-1;106480:389:0;-1:-1:-1;;;;;106480:389:0;;:::i;21792:269::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;21792:269:0;;;;;;;;:::i;19162:175::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;19162:175:0;;;;;;;;:::i;102600:447::-;;;;;;;;;;;;;;;;-1:-1:-1;102600:447:0;;-1:-1:-1;;;;;102600:447:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;102600:447:0;;:::i;96078:65::-;;;:::i;85523:46::-;;;;;;;;;;;;;;;;-1:-1:-1;85523:46:0;-1:-1:-1;;;;;85523:46:0;;:::i;96186:63::-;;;:::i;85356:112::-;;;:::i;99475:1218::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;99475:1218:0;;;;;;;;;;;;;;;;;:::i;104349:445::-;;;;;;;;;;;;;;;;-1:-1:-1;104349:445:0;;-1:-1:-1;;;;;104349:445:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;104349:445:0;;:::i;91888:905::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;91888:905:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;19400:151::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;19400:151:0;;;;;;;;;;:::i;86488:108::-;;;;;;;;;;;;;;;;-1:-1:-1;86488:108:0;-1:-1:-1;;;;;86488:108:0;;:::i;96612:26::-;;;:::i;101170:990::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;101170:990:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;85578:61;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;85578:61:0;;;;;;;;;;:::i;86670:105::-;;;;;;;;;;;;;;;;-1:-1:-1;86670:105:0;-1:-1:-1;;;;;86670:105:0;;:::i;17592:83::-;17662:5;17655:12;;;;;;;;-1:-1:-1;;17655:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17629:13;;17655:12;;17662:5;;17655:12;;17662:5;17655:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17592:83;:::o;19698:169::-;19781:4;19798:39;19807:12;:10;:12::i;:::-;19821:7;19830:6;19798:8;:39::i;:::-;-1:-1:-1;19855:4:0;19698:169;;;;;:::o;18667:100::-;18747:12;;18667:100;:::o;86841:873::-;86998:15;86986:8;:27;;86978:68;;;;;-1:-1:-1;;;86978:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87220:20:0;;;87059:18;87220:20;;;:14;:20;;;;;;;;:22;;;;;;;;;87104:180;;87133:18;87104:180;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87080:215;;;;;;-1:-1:-1;;;87349:124:0;;;;87413:16;87349:124;;;;;;;;;;;;;;;;;;;;;;;;;;;87325:159;;;;;;;;;87512:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87080:215;;87325:159;;87220:22;;87512:26;;;;;87220:20;;-1:-1:-1;;87512:26:0;;;;;;;;;;87220:22;87512:26;;;;;;;;;;;;;;;-1:-1:-1;;87512:26:0;;-1:-1:-1;;87512:26:0;;;-1:-1:-1;;;;;;;87571:20:0;;;;;;:38;;;87605:4;-1:-1:-1;;;;;87595:14:0;:6;-1:-1:-1;;;;;87595:14:0;;87571:38;87549:116;;;;;-1:-1:-1;;;87549:116:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87678:28;87691:4;87697:8;87678:12;:28::i;:::-;86841:873;;;;;;;;;:::o;96570:33::-;;;:::o;20341:321::-;20447:4;20464:36;20474:6;20482:9;20493:6;20464:9;:36::i;:::-;20511:121;20520:6;20528:12;:10;:12::i;:::-;20542:89;20580:6;20542:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20542:19:0;;;;;;:11;:19;;;;;;20562:12;:10;:12::i;:::-;-1:-1:-1;;;;;20542:33:0;;;;;;;;;;;;-1:-1:-1;20542:33:0;;;:89;;:37;:89;:::i;:::-;20511:8;:121::i;:::-;-1:-1:-1;20650:4:0;20341:321;;;;;;:::o;96645:28::-;;;-1:-1:-1;;;;;96645:28:0;;:::o;90940:138::-;;;:::o;18519:83::-;18585:9;;;;18519:83;:::o;91085:41::-;;;:::o;21071:218::-;21159:4;21176:83;21185:12;:10;:12::i;:::-;21199:7;21208:50;21247:10;21208:11;:25;21220:12;:10;:12::i;:::-;-1:-1:-1;;;;;21208:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;21208:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;85475:41::-;;;:::o;104997:384::-;105107:7;97075:8;-1:-1:-1;;;;;97069:14:0;:3;:14;97047:78;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;;;;105139:234:::1;105180:16;:14;:16::i;:::-;105211:18;:16;:18::i;:::-;105244:6;105265:25;105286:3;105275:8;-1:-1:-1::0;;;;;105275:14:0::1;;105265:9;:25::i;:::-;96112:30:::0;96412:27;105139:26:::1;:234::i;108690:175::-:0;108765:7;108797:60;108807:49;108842:13;:11;:13::i;:::-;108807:5;;:30;;;-1:-1:-1;;;108807:30:0;;108831:4;108807:30;;;;;;-1:-1:-1;;;;;108807:5:0;;;;:15;;:30;;;;;;;;;;;;;;;:5;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;108807:30:0;;:49;:34;:49;:::i;:::-;108797:9;:60::i;:::-;108790:67;;108690:175;:::o;105825:451::-;106000:7;105944:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106025:14:::1;106042:25;106059:7;106042:16;:25::i;:::-;106080:5;::::0;:48:::1;::::0;;-1:-1:-1;;;106080:48:0;;-1:-1:-1;;;;;106080:48:0;;::::1;;::::0;::::1;::::0;106113:4:::1;106080:48:::0;;;;-1:-1:-1;;;;;106080:48:0;::::1;::::0;;;;;;106025:42;;-1:-1:-1;106080:5:0;::::1;::::0;:18:::1;::::0;:48;;;;;::::1;::::0;;;;;;;;;:5:::1;::::0;:48;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;106139:3:0::1;::::0;:24:::1;::::0;;-1:-1:-1;;;106139:24:0;;-1:-1:-1;;;;;106139:24:0;;::::1;;::::0;::::1;::::0;-1:-1:-1;;;;;106139:24:0;::::1;::::0;;;;;;:3;;;::::1;::::0;:12:::1;::::0;:24;;;;;106080:48:::1;::::0;106139:24;;;;;;;:3:::1;::::0;:24;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;;;;;;106179:63:0;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;;;;;;106185:8:0::1;106205:16;-1:-1:-1::0;;;;;106205:16:0;::::1;:8;:16::i;:::-;106224:17;106233:7;-1:-1:-1::0;;;;;106224:17:0::1;:8;:17::i;:::-;106179:63;::::0;;-1:-1:-1;;;;;106179:63:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;106223:18:::1;;106179:63:::0;;;;;;;;;;;;::::1;106262:6:::0;-1:-1:-1;86408:1:0::1;105825:451:::0;;;;;;;:::o;96377:63::-;96436:3;96421:10;96412:27;;96377:63;:::o;18830:119::-;-1:-1:-1;;;;;18923:18:0;18896:7;18923:18;;;;;;;;;;;;18830:119::o;107309:449::-;107484:7;107428:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107509:13:::1;107525:25;107541:8;107525:15;:25::i;:::-;107563:3;::::0;:44:::1;::::0;;-1:-1:-1;;;107563:44:0;;-1:-1:-1;;;;;107563:44:0;;::::1;;::::0;::::1;::::0;107594:4:::1;107563:44:::0;;;;-1:-1:-1;;;;;107563:44:0;::::1;::::0;;;;;;107509:41;;-1:-1:-1;107563:3:0;::::1;::::0;:16:::1;::::0;:44;;;;;::::1;::::0;;;;;;;;;:3:::1;::::0;:44;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;107618:5:0::1;::::0;:28:::1;::::0;;-1:-1:-1;;;107618:28:0;;-1:-1:-1;;;;;107618:28:0;;::::1;;::::0;::::1;::::0;-1:-1:-1;;;;;107618:28:0;::::1;::::0;;;;;;:5;;;::::1;::::0;:14:::1;::::0;:28;;;;;107563:44:::1;::::0;107618:28;;;;;;;:5:::1;::::0;:28;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;;;;;;107662:63:0;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;;;;;;107668:8:0::1;107689:15;-1:-1:-1::0;;;;;107689:15:0;::::1;:8;:15::i;:::-;107688:16;;107706:18;107715:8;-1:-1:-1::0;;;;;107706:18:0::1;:8;:18::i;:::-;107662:63;::::0;;-1:-1:-1;;;;;107662:63:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;::::1;107745:5:::0;107309:449;-1:-1:-1;;;;;;107309:449:0:o;108912:152::-;109027:3;;:28;;;-1:-1:-1;;;109027:28:0;;109049:4;109027:28;;;;;;108985:7;;109017:39;;-1:-1:-1;;;;;109027:3:0;;;;:13;;:28;;;;;;;;;;;;;;;:3;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;109027:28:0;109017:9;:39::i;90880:51::-;;;;;;;;;;;;;:::o;103246:663::-;103356:7;97075:8;-1:-1:-1;;;;;97069:14:0;:3;:14;97047:78;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;;;;103381:19:::1;103403:16;:14;:16::i;:::-;103381:38;;103430:21;103454:18;:16;:18::i;:::-;103430:42;;103485:16;103504:223;103545:11;103571:13;103599:5;103619:25;103640:3;103629:8;-1:-1:-1::0;;;;;103629:14:0::1;;103619:9;:25::i;:::-;96112:30:::0;96221:27;103504:26:::1;:223::i;:::-;103485:242;;103794:23;103798:11;103811:5;103794:3;:23::i;:::-;-1:-1:-1::0;;;;;103762:55:0::1;:28;103766:13;103781:8;103762:3;:28::i;:::-;-1:-1:-1::0;;;;;103762:55:0::1;;;103740:133;;;::::0;;-1:-1:-1;;;103740:133:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;103893:8:::0;103246:663;-1:-1:-1;;;;103246:663:0:o;17794:87::-;17866:7;17859:14;;;;;;;;-1:-1:-1;;17859:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17833:13;;17859:14;;17866:7;;17859:14;;17866:7;17859:14;;;;;;;;;;;;;;;;;;;;;;;;107967:664;108081:7;97075:8;-1:-1:-1;;;;;97069:14:0;:3;:14;97047:78;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;;;;108106:19:::1;108128:16;:14;:16::i;:::-;108106:38;;108155:21;108179:18;:16;:18::i;:::-;108155:42;;108210:13;108226:226;108267:11;108293:13;108321:8;108344:25;108365:3;108354:8;-1:-1:-1::0;;;;;108354:14:0::1;;108344:9;:25::i;:::-;96112:30:::0;96221:27;108226:26:::1;:226::i;:::-;108210:242;;108519:23;108523:11;108536:5;108519:3;:23::i;:::-;-1:-1:-1::0;;;;;108487:55:0::1;:28;108491:13;108506:8;108487:3;:28::i;106480:389::-:0;106594:7;97075:8;-1:-1:-1;;;;;97069:14:0;:3;:14;97047:78;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;;;;106626:235:::1;106667:16;:14;:16::i;:::-;106698:18;:16;:18::i;:::-;106731:7;106753:25;106774:3;106763:8;-1:-1:-1::0;;;;;106763:14:0::1;;106753:9;:25::i;:::-;96112:30:::0;96412:27;106626:26:::1;:235::i;21792:269::-:0;21885:4;21902:129;21911:12;:10;:12::i;:::-;21925:7;21934:96;21973:15;21934:96;;;;;;;;;;;;;;;;;:11;:25;21946:12;:10;:12::i;:::-;-1:-1:-1;;;;;21934:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;21934:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;19162:175::-;19248:4;19265:42;19275:12;:10;:12::i;:::-;19289:9;19300:6;19265:9;:42::i;102600:447::-;102771:7;102715:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102796:16:::1;102815:21;102830:5;102815:14;:21::i;:::-;102849:3;::::0;:44:::1;::::0;;-1:-1:-1;;;102849:44:0;;-1:-1:-1;;;;;102849:44:0;;::::1;;::::0;::::1;::::0;102880:4:::1;102849:44:::0;;;;-1:-1:-1;;;;;102849:44:0;::::1;::::0;;;;;;102796:40;;-1:-1:-1;102849:3:0;::::1;::::0;:16:::1;::::0;:44;;;;;::::1;::::0;;;;;;;;;:3:::1;::::0;:44;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;102904:5:0::1;::::0;:28:::1;::::0;;-1:-1:-1;;;102904:28:0;;-1:-1:-1;;;;;102904:28:0;;::::1;;::::0;::::1;::::0;-1:-1:-1;;;;;102904:28:0;::::1;::::0;;;;;;:5;;;::::1;::::0;:14:::1;::::0;:28;;;;;102849:44:::1;::::0;102904:28;;;;;;;:5:::1;::::0;:28;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;;;;;;102948:63:0;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;;;;;;102954:8:0::1;102975:15;-1:-1:-1::0;;;;;102975:15:0;::::1;:8;:15::i;:::-;102974:16;;102992:18;103001:8;-1:-1:-1::0;;;;;102992:18:0::1;:8;:18::i;96078:65::-:0;96133:9;-1:-1:-1;;;96112:30:0;;85523:46;;;;;;;;;;;;;:::o;96186:63::-;96244:4;96230:9;96221:27;;85356:112;;;:::o;99475:1218::-;99649:7;99592:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99674:14:::1;99691:13;:11;:13::i;:::-;99674:30:::0;-1:-1:-1;99719:11:0;99715:40:::1;;99739:16;99744:10;99739:4;:16::i;:::-;99732:23;;;;;99715:40;99790:3;::::0;:28:::1;::::0;;-1:-1:-1;;;99790:28:0;;99812:4:::1;99790:28;::::0;::::1;::::0;;;99768:19:::1;::::0;-1:-1:-1;;;;;99790:3:0::1;::::0;:13:::1;::::0;:28;;;;;::::1;::::0;;;;;;;;:3;:28;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;99790:28:0;99922:5:::1;::::0;:30:::1;::::0;;-1:-1:-1;;;99922:30:0;;99946:4:::1;99922:30;::::0;::::1;::::0;;;99790:28;;-1:-1:-1;99898:21:0::1;::::0;-1:-1:-1;;;;;99922:5:0;;::::1;::::0;:15:::1;::::0;:30;;;;;99790:28:::1;::::0;99922:30;;;;;;;;:5;:30;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;99922:30:0;;-1:-1:-1;99963:20:0::1;99986:39;100013:11:::0;99986:22:::1;:6:::0;99997:10;99986:22:::1;:10;:22;:::i;:::-;:26:::0;:39:::1;:26;:39;:::i;:::-;99963:62:::0;-1:-1:-1;100036:21:0::1;100060:43;100096:6:::0;100060:31:::1;:13:::0;99963:62;100060:31:::1;:17;:31;:::i;:43::-;100036:67:::0;-1:-1:-1;;;;;;100124:27:0::1;:11:::0;100140:10;100124:27:::1;:15;:27;:::i;:::-;:48;;100116:57;;;::::0;::::1;;-1:-1:-1::0;;;;;100241:44:0::1;100252:32;:13:::0;100270;100252:32:::1;:17;:32;:::i;:::-;100241:6:::0;;:44:::1;:10;:44;:::i;:::-;:65;;100233:74;;;::::0;::::1;;100377:3;::::0;:49:::1;::::0;;-1:-1:-1;;;100377:49:0;;-1:-1:-1;;;;;100377:49:0;;::::1;;::::0;::::1;::::0;100408:4:::1;100377:49:::0;;;;;;;;;;;;:3;;;::::1;::::0;:16:::1;::::0;:49;;;;;::::1;::::0;;;;;;;;:3:::1;::::0;:49;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;100377:49:0;100369:58:::1;;;::::0;::::1;;100446:5;::::0;:54:::1;::::0;;-1:-1:-1;;;100446:54:0;;-1:-1:-1;;;;;100446:54:0;;::::1;;::::0;::::1;::::0;100479:4:::1;100446:54:::0;;;;;;;;;;;;:5;;;::::1;::::0;:18:::1;::::0;:54;;;;;::::1;::::0;;;;;;;;:5:::1;::::0;:54;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;100446:54:0;100438:63:::1;;;::::0;::::1;;100512:23;100518:2;100522:12;100512:5;:23::i;:::-;100577:2;-1:-1:-1::0;;;;;100551:102:0::1;100571:4;-1:-1:-1::0;;;;;100551:102:0::1;;100561:8;100582:20;100591:10;100582:8;:20::i;:::-;100581:21;;100605:23;100614:13;100605:8;:23::i;:::-;100604:24;;100630:22;100639:12;100630:8;:22::i;:::-;100551:102;::::0;;-1:-1:-1;;;;;100551:102:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;::::1;-1:-1:-1::0;100673:12:0;99475:1218;-1:-1:-1;;;;;;;;;99475:1218:0:o;104349:445::-;104520:7;104464:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104545:15:::1;104563:21;104577:6;104563:13;:21::i;:::-;104597:5;::::0;:48:::1;::::0;;-1:-1:-1;;;104597:48:0;;-1:-1:-1;;;;;104597:48:0;;::::1;;::::0;::::1;::::0;104630:4:::1;104597:48:::0;;;;-1:-1:-1;;;;;104597:48:0;::::1;::::0;;;;;;104545:39;;-1:-1:-1;104597:5:0;::::1;::::0;:18:::1;::::0;:48;;;;;::::1;::::0;;;;;;;;;:5:::1;::::0;:48;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;104656:3:0::1;::::0;:24:::1;::::0;;-1:-1:-1;;;104656:24:0;;-1:-1:-1;;;;;104656:24:0;;::::1;;::::0;::::1;::::0;-1:-1:-1;;;;;104656:24:0;::::1;::::0;;;;;;:3;;;::::1;::::0;:12:::1;::::0;:24;;;;;104597:48:::1;::::0;104656:24;;;;;;;:3:::1;::::0;:24;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;;;;;;104696:63:0;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;;;;;;104702:8:0::1;104722:16;-1:-1:-1::0;;;;;104722:16:0;::::1;:8;:16::i;:::-;104741:17;104750:7;-1:-1:-1::0;;;;;104741:17:0::1;:8;:17::i;91888:905::-:0;92056:15;92044:8;:27;;92036:69;;;;;-1:-1:-1;;;92036:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;92301:13:0;;;92118:18;92301:13;;;:6;:13;;;;;;;;:15;;;;;;;;;92163:195;;92192:15;92163:195;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92139:230;;;;;;-1:-1:-1;;;92421:124:0;;;;92485:16;92421:124;;;;;;;;;;;;;;;;;;;;;;;;;;;92397:159;;;;;;;;;92586:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92139:230;;92397:159;;92301:15;;92586:24;;;;;92301:13;;-1:-1:-1;;92586:24:0;;;;;;;;;;92301:15;92586:24;;;;;;;;;;;;;;;-1:-1:-1;;92586:24:0;;-1:-1:-1;;92586:24:0;;;-1:-1:-1;;;;;;;92643:20:0;;;;;;:39;;;92677:5;-1:-1:-1;;;;;92667:15:0;:6;-1:-1:-1;;;;;92667:15:0;;92643:39;92621:119;;;;;-1:-1:-1;;;92621:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;92753:32;92762:5;92769:7;92778:6;92753:8;:32::i;:::-;91888:905;;;;;;;;;;:::o;19400:151::-;-1:-1:-1;;;;;19516:18:0;;;19489:7;19516:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;19400:151::o;86488:108::-;86554:34;86567:10;86579:8;86554:12;:34::i;:::-;86488:108;:::o;96612:26::-;;;-1:-1:-1;;;;;96612:26:0;;:::o;101170:990::-;101346:7;101355;101289:4;86199:218;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;86199:218:0;;;86320:6;-1:-1:-1;;;;;86306:20:0;:10;-1:-1:-1;;;;;86306:20:0;;:53;;;-1:-1:-1;;;;;;86330:17:0;;;;;;:9;:17;;;;;;;;86348:10;86330:29;;;;;;;;;;86306:53;86374:12;86284:113;;;;;-1:-1:-1;;;86284:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101380:14:::1;101397:13;:11;:13::i;:::-;101443:3;::::0;:28:::1;::::0;;-1:-1:-1;;;101443:28:0;;101465:4:::1;101443:28;::::0;::::1;::::0;;;101380:30;;-1:-1:-1;101421:19:0::1;::::0;-1:-1:-1;;;;;101443:3:0;;::::1;::::0;:13:::1;::::0;:28;;;;;::::1;::::0;;;;;;;;;:3;:28;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;101443:28:0;101679:5:::1;::::0;:30:::1;::::0;;-1:-1:-1;;;101679:30:0;;101703:4:::1;101679:30;::::0;::::1;::::0;;;101443:28;;-1:-1:-1;101551:19:0::1;::::0;;;;;-1:-1:-1;;;;;101679:5:0;;::::1;::::0;:15:::1;::::0;:30;;;;;101443:28:::1;::::0;101679:30;;;;;;;;:5;:30;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;101679:30:0;;-1:-1:-1;101738:41:0::1;101772:6:::0;101738:29:::1;:12:::0;101755:11;101738:29:::1;:16;:29;:::i;:41::-;101724:55:::0;-1:-1:-1;101810:43:0::1;101846:6:::0;101810:31:::1;:12:::0;101827:13;101810:31:::1;:16;:31;:::i;:43::-;101794:59;;86408:1;101877:25;101883:4;101889:12;101877:5;:25::i;:::-;101913:3;::::0;:29:::1;::::0;;-1:-1:-1;;;101913:29:0;;-1:-1:-1;;;;;101913:29:0;;::::1;;::::0;::::1;::::0;;;;;;;;;:3;;;::::1;::::0;:12:::1;::::0;:29;;;;;::::1;::::0;;;;;;;;:3:::1;::::0;:29;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;101953:5:0::1;::::0;:33:::1;::::0;;-1:-1:-1;;;101953:33:0;;-1:-1:-1;;;;;101953:33:0;;::::1;;::::0;::::1;::::0;;;;;;;;;:5;;;::::1;::::0;:14:::1;::::0;:33;;;;;101913:29:::1;::::0;101953:33;;;;;;;:5:::1;::::0;:33;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;;;;;;;102002:102:0;;::::1;::::0;;::::1;;102012:8;102032:21;102041:11:::0;102032:8:::1;:21::i;:::-;102055:23;102064:13;102055:8;:23::i;:::-;102081:22;102090:12;102081:8;:22::i;:::-;102002:102;::::0;;-1:-1:-1;;;;;102002:102:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;102080:23:::1;;102002:102:::0;;;;;;;;;;;;::::1;102125:11:::0;;;;-1:-1:-1;101170:990:0;-1:-1:-1;;;;;;;;101170:990:0:o;85578:61::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;86670:105::-;86730:37;86746:10;86758:8;86730:15;:37::i;624:106::-;712:10;624:106;:::o;24939:346::-;-1:-1:-1;;;;;25041:19:0;;25033:68;;;;-1:-1:-1;;;25033:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;25120:21:0;;25112:68;;;;-1:-1:-1;;;25112:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;25193:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;25245:32;;;;;;;;;;;;;;;;;24939:346;;;:::o;87786:238::-;-1:-1:-1;;;;;87869:15:0;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;87868:26;87860:67;;;;;-1:-1:-1;;;87860:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87938:15:0;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;;:32;;-1:-1:-1;;87938:32:0;87966:4;87938:32;;;;;;87986:30;;;;;;;;;;;;;;;;;87786:238;;:::o;22551:539::-;-1:-1:-1;;;;;22657:20:0;;22649:70;;;;-1:-1:-1;;;22649:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22738:23:0;;22730:71;;;;-1:-1:-1;;;22730:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22814:47;22835:6;22843:9;22854:6;22814:20;:47::i;:::-;22894:71;22916:6;22894:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22894:17:0;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;-1:-1:-1;;;;;22874:17:0;;;:9;:17;;;;;;;;;;;:91;;;;22999:20;;;;;;;:32;;23024:6;22999:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;22976:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;23047:35;;;;;;;22976:20;;23047:35;;;;;;;;;;;;;22551:539;;;:::o;5605:192::-;5691:7;5727:12;5719:6;;;;5711:29;;;;-1:-1:-1;;;5711:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5763:5:0;;;5605:192::o;4702:181::-;4760:7;4792:5;;;4816:6;;;;4808:46;;;;;-1:-1:-1;;;4808:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;97723:199;97775:7;-1:-1:-1;;;;;97817:22:0;;;97795:91;;;;;-1:-1:-1;;;97795:91:0;;;;;;;;;;;;-1:-1:-1;;;97795:91:0;;;;;;;;;;;;;;;-1:-1:-1;97912:1:0;97723:199::o;55707:1323::-;55880:7;55929:8;55940:56;55955:1;55958:37;55978:16;-1:-1:-1;;;;;55958:37:0;:18;:37::i;:::-;55940:13;:56::i;:::-;55929:67;;56026:8;56037:57;-1:-1:-1;;;56073:20:0;56088:1;56091;56073:13;:20::i;:::-;56037:13;:57::i;:::-;56026:68;;56114:1;56110;:5;;;56101:51;;;;;-1:-1:-1;;;56101:51:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56101:51:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;56237:19:0;;;56213:21;;;:43;-1:-1:-1;;;56272:41:0;;56263:82;;;;;-1:-1:-1;;;56263:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56354:11;56509:53;56523:3;56538:1;-1:-1:-1;;;56509:3:0;:53::i;:::-;56446;56451:13;56475:1;-1:-1:-1;;;56446:3:0;:53::i;:::-;56375:61;56389:11;56412:1;-1:-1:-1;;;56375:3:0;:61::i;:::-;:124;:187;56354:208;;-1:-1:-1;;;56578:3:0;:41;56569:99;;;;-1:-1:-1;;;56569:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56677:14;56750:13;-1:-1:-1;;;;;56694:69:0;:53;56708:3;-1:-1:-1;;;56744:1:0;56694:3;:53::i;:::-;:69;56677:86;;-1:-1:-1;;;56779:6:0;:44;56770:91;;;;-1:-1:-1;;;56770:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56886:24;56877:33;;:69;;-1:-1:-1;;;;;56877:69:0;;;56913:6;56922:4;56913:13;56877:69;56868:78;55707:1323;-1:-1:-1;;;;;;;;;;;;55707:1323:0:o;97980:204::-;98031:6;-1:-1:-1;;;;;98072:1:0;:30;;98050:99;;;;;-1:-1:-1;;;98050:99:0;;;;;;;;;;;;-1:-1:-1;;;98050:99:0;;;;;;;;;;;;;;52117:1277;52290:7;52339:8;52350:56;52365:1;52368:37;52388:16;-1:-1:-1;;;;;52368:37:0;:18;:37::i;52350:56::-;52339:67;;52436:8;52447:57;-1:-1:-1;;;52483:20:0;52498:1;52501;52483:13;:20::i;52447:57::-;52436:68;;52524:1;52520;:5;;;52511:51;;;;;-1:-1:-1;;;52511:51:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;52511:51:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;52623:21:0;;;52647:19;;;52623:43;-1:-1:-1;;;52682:41:0;;52673:81;;;;;-1:-1:-1;;;52673:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52763:11;52908:52;52921:3;52936:1;-1:-1:-1;;;52908:3:0;:52::i;:::-;52845:53;52850:13;52874:1;-1:-1:-1;;;52845:3:0;:53::i;:::-;52784:51;52789:11;52811:1;-1:-1:-1;;;52784:3:0;:51::i;:::-;:114;:176;52763:197;;-1:-1:-1;;;52976:3:0;:41;52967:93;;;;-1:-1:-1;;;52967:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53069:14;53102:53;53116:3;-1:-1:-1;;;53152:1:0;53102:3;:53::i;:::-;53086:13;-1:-1:-1;;;;;53086:69:0;;53069:86;;-1:-1:-1;;;53171:6:0;:44;53162:91;;;;-1:-1:-1;;;53162:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53278:4;53269:6;:13;:33;;53301:1;53269:33;;;-1:-1:-1;;53285:13:0;;52117:1277;-1:-1:-1;;;;;;;;;;;52117:1277:0:o;97214:195::-;97281:7;97318:5;;;-1:-1:-1;;;;;97342:6:0;;;;;;;;97334:46;;;;;-1:-1:-1;;;97334:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;97482:182;97540:7;97573:1;-1:-1:-1;;;;;97568:6:0;:1;-1:-1:-1;;;;;97568:6:0;;;97560:47;;;;;-1:-1:-1;;;97560:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;97630:5:0;;;97482:182::o;57569:1308::-;57744:7;57803:8;57814:112;-1:-1:-1;;;57850:75:0;57865:1;57868:56;57883:1;57886:37;57906:16;-1:-1:-1;;;;;57886:37:0;:18;:37::i;57814:112::-;57803:123;;57946:1;57942;:5;;;57933:51;;;;;-1:-1:-1;;;57933:51:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;57933:51:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;58076:21:0;;;58050:23;;;:47;-1:-1:-1;;;58113:41:0;;58104:84;;;;;-1:-1:-1;;;58104:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;58197:11;58342:53;58356:3;58371:1;-1:-1:-1;;;58342:3:0;:53::i;:::-;58279;58284:13;58308:1;-1:-1:-1;;;58279:3:0;:53::i;:::-;58218:51;58223:11;58245:1;-1:-1:-1;;;58218:3:0;:51::i;:::-;:114;:177;58197:198;;-1:-1:-1;;;58411:3:0;:41;58402:97;;;;-1:-1:-1;;;58402:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58508:14;58595:11;-1:-1:-1;;;;;58532:74:0;:53;58546:3;-1:-1:-1;;;58582:1:0;58532:3;:53::i;:::-;:74;58508:98;;-1:-1:-1;;;58622:6:0;:44;58613:91;;;;-1:-1:-1;;;58613:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58729:24;58720:33;;:69;;-1:-1:-1;;;;;58720:69:0;;;58756:6;58765:4;58756:13;58720:69;58711:78;57569:1308;-1:-1:-1;;;;;;;;;;;57569:1308:0:o;53897:1311::-;54072:7;54121:8;54132:56;54147:1;54150:37;54170:16;-1:-1:-1;;;;;54150:37:0;:18;:37::i;54132:56::-;54121:67;;54218:8;54229:57;-1:-1:-1;;;54265:20:0;54280:1;54283;54265:13;:20::i;54229:57::-;54218:68;;54306:1;54302;:5;;;54293:51;;;;;-1:-1:-1;;;54293:51:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;54293:51:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;54410:23:0;;;54436:21;;;54410:47;-1:-1:-1;;;54473:41:0;;54464:83;;;;;-1:-1:-1;;;54464:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;54556:11;54711:53;54716:13;54740:1;-1:-1:-1;;;54711:3:0;:53::i;:::-;54648;54662:3;54677:1;-1:-1:-1;;;54648:3:0;:53::i;:::-;54577:61;54591:11;54614:1;-1:-1:-1;;;54577:3:0;:61::i;:::-;:124;:187;54556:208;;-1:-1:-1;;;54780:3:0;:41;54771:91;;;;-1:-1:-1;;;54771:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54871:14;54916:53;54930:3;-1:-1:-1;;;54966:1:0;54916:3;:53::i;:::-;54895:11;-1:-1:-1;;;;;54895:74:0;;54871:98;;-1:-1:-1;;;54985:6:0;:44;54976:91;;;;-1:-1:-1;;;54976:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98364:517;98453:7;97075:8;-1:-1:-1;;;;;97069:14:0;:3;:14;97047:78;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;-1:-1:-1;;;97047:78:0;;;;;;;;;;;;;;;98500:13:::1;:11;:13::i;:::-;:18:::0;98478:93:::1;;;::::0;;-1:-1:-1;;;98478:93:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;98666:3;::::0;:50:::1;::::0;;-1:-1:-1;;;98666:50:0;;98683:10:::1;98666:50;::::0;::::1;::::0;98703:4:::1;98666:50:::0;;;;;;;;;;;;-1:-1:-1;;;;;98666:3:0;;::::1;::::0;:16:::1;::::0;:50;;;;;::::1;::::0;;;;;;;;;:3:::1;::::0;:50;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;98727:24:0::1;::::0;-1:-1:-1;98733:10:0::1;98745:5:::0;98727::::1;:24::i;:::-;98799:10;::::0;98767:81:::1;98777:8;98812:15;98821:5:::0;98812:8:::1;:15::i;:::-;98811:16;;98829:1;98832:15;98841:5;98832:8;:15::i;:::-;98767:81;::::0;;-1:-1:-1;;;;;98767:81:0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;::::1;-1:-1:-1::0;98868:5:0;98364:517::o;6056:471::-;6114:7;6359:6;6355:47;;-1:-1:-1;6389:1:0;6382:8;;6355:47;6426:5;;;6430:1;6426;:5;:1;6450:5;;;;;:10;6442:56;;;;-1:-1:-1;;;6442:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7003:132;7061:7;7088:39;7092:1;7095;7088:39;;;;;;;;;;;;;;;;;:3;:39::i;23371:378::-;-1:-1:-1;;;;;23455:21:0;;23447:65;;;;;-1:-1:-1;;;23447:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;23525:49;23554:1;23558:7;23567:6;23525:20;:49::i;:::-;23602:12;;:24;;23619:6;23602:24;:16;:24;:::i;:::-;23587:12;:39;-1:-1:-1;;;;;23658:18:0;;:9;:18;;;;;;;;;;;:30;;23681:6;23658:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;23637:18:0;;:9;:18;;;;;;;;;;;:51;;;;23704:37;;;;;;;23637:18;;:9;;23704:37;;;;;;;;;;23371:378;;:::o;24081:418::-;-1:-1:-1;;;;;24165:21:0;;24157:67;;;;-1:-1:-1;;;24157:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24237:49;24258:7;24275:1;24279:6;24237:20;:49::i;:::-;24320:68;24343:6;24320:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;24320:18:0;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;-1:-1:-1;;;;;24299:18:0;;:9;:18;;;;;;;;;;:89;24414:12;;:24;;24431:6;24414:24;:16;:24;:::i;:::-;24399:12;:39;24454:37;;;;;;;;24480:1;;-1:-1:-1;;;;;24454:37:0;;;;;;;;;;;;24081:418;;:::o;88099:244::-;-1:-1:-1;;;;;88184:15:0;;;;;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;88176:68;;;;;-1:-1:-1;;;88176:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;88255:15:0;;;88283:5;88255:15;;;:9;:15;;;;;;;;:25;;;;;;;;;;;;:33;;-1:-1:-1;;88255:33:0;;;88304:31;;;;;;;;;;;;;;;;88099:244;;:::o;26310:92::-;;;;:::o;28387:137::-;28440:6;28469:18;28464:1;:23;;28455:33;;;;;;-1:-1:-1;28515:2:0;28510:7;;28387:137::o;30749:201::-;30806:6;30837:13;:9;;;:13;;;;;30854:2;30837:19;-1:-1:-1;;;;;;30872:19:0;;;;;:42;;-1:-1:-1;;;;;;30895:19:0;;;30872:42;30863:52;;;;;30313:195;30370:6;30401:13;;;;:9;;;;:13;-1:-1:-1;;;;;;30430:19:0;;;;;:42;;-1:-1:-1;;;;;;30453:19:0;;;30421:52;;;;;59360:437;59433:7;-1:-1:-1;;;;;59458:6:0;;59449:16;;;;;;-1:-1:-1;;;;;59478:6:0;;59474:318;;-1:-1:-1;;;;;59504:6:0;;59495:16;;;;;;-1:-1:-1;59527:1:0;59520:8;;59474:318;59551:9;59635:1;-1:-1:-1;;;;;59572:64:0;59631:1;-1:-1:-1;;;;;59572:60:0;59618:9;59625:1;59618:5;:9::i;:::-;-1:-1:-1;;;;;59581:46:0;-1:-1:-1;;;;;59572:56:0;:60;:64;;;;;;59551:85;;-1:-1:-1;;;;;59649:1:0;:38;59645:139;;;59696:1;59689:8;;;;;59645:139;59727:56;59780:1;-1:-1:-1;;;;;59743:38:0;59727:5;:56::i;:::-;-1:-1:-1;;;;;59718:66:0;59711:73;;;;;7631:278;7717:7;7752:12;7745:5;7737:28;;;;-1:-1:-1;;;7737:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7776:9;7792:1;7788;:5;;;;;;;7631:278;-1:-1:-1;;;;;7631:278:0:o;5166:136::-;5224:7;5251:43;5255:1;5258;5251:43;;;;;;;;;;;;;;;;;:3;:43::i;60040:13568::-;60093:7;-1:-1:-1;;;;;60118:6:0;;60109:16;;;;;;-1:-1:-1;;;;;60134:10:0;;-1:-1:-1;;;;;;60209:23:0;;60205:81;;;60282:2;60276:8;;;;;-1:-1:-1;;;;;;60235:39:0;60205:81;-1:-1:-1;;;60296:1:0;:31;60292:89;;;60377:2;60371:8;;;;;-1:-1:-1;;60330:39:0;60292:89;-1:-1:-1;;;60391:1:0;:35;60387:93;;;60476:2;60470:8;;;;;-1:-1:-1;;60429:39:0;60387:93;-1:-1:-1;;;60490:1:0;:37;60486:94;;;60577:1;60571:7;;;;;-1:-1:-1;;60530:39:0;60486:94;-1:-1:-1;;;60590:1:0;:38;60586:94;;;60677:1;60671:7;;;;;-1:-1:-1;;60631:38:0;60586:94;-1:-1:-1;;;60690:1:0;:38;60686:94;;;60777:1;60771:7;;;;;-1:-1:-1;;60731:38:0;60686:94;-1:-1:-1;;;60790:1:0;:38;60786:94;;;60877:1;60871:7;;;;;-1:-1:-1;;60831:38:0;60786:94;60892:5;;;60901:3;60892:12;;-1:-1:-1;;;60910:40:0;;60906:96;;60959:1;60953:7;;;;;-1:-1:-1;;;60962:38:0;60906:96;61012:5;;;61021:3;61012:12;;-1:-1:-1;;;61030:40:0;;61026:95;;61079:1;61073:7;;;;;-1:-1:-1;;;61082:37:0;61026:95;61131:5;;;61140:3;61131:12;;-1:-1:-1;;;61149:40:0;;61145:95;;61198:1;61192:7;;;;;-1:-1:-1;;;61201:37:0;61145:95;61250:5;;;61259:3;61250:12;;-1:-1:-1;;;61268:40:0;;61264:95;;61317:1;61311:7;;;;;-1:-1:-1;;;61320:37:0;61264:95;61369:5;;;61378:3;61369:12;;-1:-1:-1;;;61387:40:0;;61383:95;;61436:1;61430:7;;;;;-1:-1:-1;;;61439:37:0;61383:95;61488:5;;;61497:3;61488:12;;-1:-1:-1;;;61506:40:0;;61502:94;;61555:1;61549:7;;;;;-1:-1:-1;;;61558:36:0;61502:94;61606:5;;;61615:3;61606:12;;-1:-1:-1;;;61624:40:0;;61620:94;;61673:1;61667:7;;;;;-1:-1:-1;;;61676:36:0;61620:94;61724:5;;;61733:3;61724:12;;-1:-1:-1;;;61742:40:0;;61738:94;;61791:1;61785:7;;;;;-1:-1:-1;;;61794:36:0;61738:94;61842:5;;;61851:3;61842:12;;-1:-1:-1;;;61860:40:0;;61856:94;;61909:1;61903:7;;;;;-1:-1:-1;;;61912:36:0;61856:94;61960:5;;;61969:3;61960:12;;-1:-1:-1;;;61978:40:0;;61974:93;;62027:1;62021:7;;;;;-1:-1:-1;;;62030:35:0;61974:93;62077:5;;;62086:3;62077:12;;-1:-1:-1;;;62095:40:0;;62091:93;;62144:1;62138:7;;;;;-1:-1:-1;;;62147:35:0;62091:93;62194:5;;;62203:3;62194:12;;-1:-1:-1;;;62212:40:0;;62208:93;;62261:1;62255:7;;;;;-1:-1:-1;;;62264:35:0;62208:93;62311:5;;;62320:3;62311:12;;-1:-1:-1;;;62329:40:0;;62325:93;;62378:1;62372:7;;;;;-1:-1:-1;;;62381:35:0;62325:93;62428:5;;;62437:3;62428:12;;-1:-1:-1;;;62446:40:0;;62442:92;;62495:1;62489:7;;;;;-1:-1:-1;;;62498:34:0;62442:92;62544:5;;;62553:3;62544:12;;-1:-1:-1;;;62562:40:0;;62558:92;;62611:1;62605:7;;;;;-1:-1:-1;;;62614:34:0;62558:92;62660:5;;;62669:3;62660:12;;-1:-1:-1;;;62678:40:0;;62674:92;;62727:1;62721:7;;;;;-1:-1:-1;;;62730:34:0;62674:92;62776:5;;;62785:3;62776:12;;-1:-1:-1;;;62794:40:0;;62790:92;;62843:1;62837:7;;;;;-1:-1:-1;;;62846:34:0;62790:92;62892:5;;;62901:3;62892:12;;-1:-1:-1;;;62910:40:0;;62906:91;;62959:1;62953:7;;;;;-1:-1:-1;;;62962:33:0;62906:91;63007:5;;;63016:3;63007:12;;-1:-1:-1;;;63025:40:0;;63021:91;;63074:1;63068:7;;;;;-1:-1:-1;;;63077:33:0;63021:91;63122:5;;;63131:3;63122:12;;-1:-1:-1;;;63140:40:0;;63136:91;;63189:1;63183:7;;;;;-1:-1:-1;;;63192:33:0;63136:91;63237:5;;;63246:3;63237:12;;-1:-1:-1;;;63255:40:0;;63251:91;;63304:1;63298:7;;;;;-1:-1:-1;;;63307:33:0;63251:91;63352:5;;;63361:3;63352:12;;-1:-1:-1;;;63370:40:0;;63366:90;;63419:1;63413:7;;;;;-1:-1:-1;;;63422:32:0;63366:90;63466:5;;;63475:3;63466:12;;-1:-1:-1;;;63484:40:0;;63480:90;;63533:1;63527:7;;;;;-1:-1:-1;;;63536:32:0;63480:90;63580:5;;;63589:3;63580:12;;-1:-1:-1;;;63598:40:0;;63594:90;;63647:1;63641:7;;;;;-1:-1:-1;;;63650:32:0;63594:90;63694:5;;;63703:3;63694:12;;-1:-1:-1;;;63712:40:0;;63708:90;;63761:1;63755:7;;;;;-1:-1:-1;;;63764:32:0;63708:90;63808:5;;;63817:3;63808:12;;-1:-1:-1;;;63826:40:0;;63822:89;;63875:1;63869:7;;;;;-1:-1:-1;;;63878:31:0;63822:89;63921:5;;;63930:3;63921:12;;-1:-1:-1;;;63939:40:0;;63935:89;;63988:1;63982:7;;;;;-1:-1:-1;;;63991:31:0;63935:89;64034:5;;;64043:3;64034:12;;-1:-1:-1;;;64052:40:0;;64048:89;;64101:1;64095:7;;;;;-1:-1:-1;;;64104:31:0;64048:89;64147:5;;;64156:3;64147:12;;-1:-1:-1;;;64165:40:0;;64161:89;;64214:1;64208:7;;;;;-1:-1:-1;;;64217:31:0;64161:89;64260:5;;;64269:3;64260:12;;-1:-1:-1;;;64278:40:0;;64274:88;;64327:1;64321:7;;;;;-1:-1:-1;;;64330:30:0;64274:88;64372:5;;;64381:3;64372:12;;-1:-1:-1;;;64390:40:0;;64386:88;;64439:1;64433:7;;;;;-1:-1:-1;;;64442:30:0;64386:88;64484:5;;;64493:3;64484:12;;-1:-1:-1;;;64502:40:0;;64498:88;;64551:1;64545:7;;;;;-1:-1:-1;;;64554:30:0;64498:88;64596:5;;;64605:3;64596:12;;-1:-1:-1;;;64614:40:0;;64610:88;;64663:1;64657:7;;;;;-1:-1:-1;;;64666:30:0;64610:88;64708:5;;;64717:3;64708:12;;-1:-1:-1;;;64726:40:0;;64722:87;;64775:1;64769:7;;;;;-1:-1:-1;;;64778:29:0;64722:87;64819:5;;;64828:3;64819:12;;-1:-1:-1;;;64837:40:0;;64833:87;;64886:1;64880:7;;;;;-1:-1:-1;;;64889:29:0;64833:87;64930:5;;;64939:3;64930:12;;-1:-1:-1;;;64948:40:0;;64944:87;;64997:1;64991:7;;;;;-1:-1:-1;;;65000:29:0;64944:87;65041:5;;;65050:3;65041:12;;-1:-1:-1;;;65059:40:0;;65055:87;;65108:1;65102:7;;;;;-1:-1:-1;;;65111:29:0;65055:87;65152:5;;;65161:3;65152:12;;-1:-1:-1;;;65170:40:0;;65166:86;;65219:1;65213:7;;;;;-1:-1:-1;;;65222:28:0;65166:86;65262:5;;;65271:3;65262:12;;-1:-1:-1;;;65280:40:0;;65276:86;;65329:1;65323:7;;;;;-1:-1:-1;;;65332:28:0;65276:86;65372:5;;;65381:3;65372:12;;-1:-1:-1;;;65390:40:0;;65386:86;;65439:1;65433:7;;;;;-1:-1:-1;;;65442:28:0;65386:86;65482:5;;;65491:3;65482:12;;-1:-1:-1;;;65500:40:0;;65496:86;;65549:1;65543:7;;;;;-1:-1:-1;;;65552:28:0;65496:86;65592:5;;;65601:3;65592:12;;-1:-1:-1;;;65610:40:0;;65606:85;;65659:1;65653:7;;;;;-1:-1:-1;;;65662:27:0;65606:85;65701:5;;;65710:3;65701:12;;-1:-1:-1;;;65719:40:0;;65715:85;;65768:1;65762:7;;;;;-1:-1:-1;;;65771:27:0;65715:85;65810:5;;;65819:3;65810:12;;-1:-1:-1;;;65828:40:0;;65824:85;;65877:1;65871:7;;;;;-1:-1:-1;;;65880:27:0;65824:85;65919:5;;;65928:3;65919:12;;-1:-1:-1;;;65937:40:0;;65933:85;;65986:1;65980:7;;;;;-1:-1:-1;;;65989:27:0;65933:85;66028:5;;;66037:3;66028:12;;-1:-1:-1;;;66046:40:0;;66042:84;;66095:1;66089:7;;;;;-1:-1:-1;;;66098:26:0;66042:84;66136:5;;;66145:3;66136:12;;-1:-1:-1;;;66154:40:0;;66150:84;;66203:1;66197:7;;;;;-1:-1:-1;;;66206:26:0;66150:84;66244:5;;;66253:3;66244:12;;-1:-1:-1;;;66262:40:0;;66258:84;;66311:1;66305:7;;;;;-1:-1:-1;;;66314:26:0;66258:84;66352:5;;;66361:3;66352:12;;-1:-1:-1;;;66370:40:0;;66366:84;;66419:1;66413:7;;;;;-1:-1:-1;;;66422:26:0;66366:84;66460:5;;;66469:3;66460:12;;-1:-1:-1;;;66478:40:0;;66474:83;;66527:1;66521:7;;;;;-1:-1:-1;;;66530:25:0;66474:83;66567:5;;;66576:3;66567:12;;-1:-1:-1;;;66585:40:0;;66581:83;;66634:1;66628:7;;;;;-1:-1:-1;;;66637:25:0;66581:83;66674:5;;;66683:3;66674:12;;-1:-1:-1;;;66692:40:0;;66688:83;;66741:1;66735:7;;;;;-1:-1:-1;;;66744:25:0;66688:83;66781:5;;;66790:3;66781:12;;-1:-1:-1;;;66799:40:0;;66795:83;;66848:1;66842:7;;;;;-1:-1:-1;;;66851:25:0;66795:83;66888:5;;;66897:3;66888:12;;-1:-1:-1;;;66906:40:0;;66902:82;;66955:1;66949:7;;;;;-1:-1:-1;;;66958:24:0;66902:82;66994:5;;;67003:3;66994:12;;-1:-1:-1;;;67012:40:0;;67008:82;;67061:1;67055:7;;;;;-1:-1:-1;;;67064:24:0;67008:82;67100:5;;;67109:3;67100:12;;-1:-1:-1;;;67118:40:0;;67114:82;;67167:1;67161:7;;;;;-1:-1:-1;;;67170:24:0;67114:82;67206:5;;;67215:3;67206:12;;-1:-1:-1;;;67224:40:0;;67220:82;;-1:-1:-1;;;67276:24:0;;73600:1;-1:-1:-1;;;60040:13568:0:o;73775:10824::-;73828:7;-1:-1:-1;;;;;;73898:37:0;;:41;73894:96;;73949:34;73945:38;73987:3;73945:45;73894:96;-1:-1:-1;;;74001:36:0;;:40;73997:95;;74051:34;74047:38;74089:3;74047:45;73997:95;-1:-1:-1;;;74103:36:0;;:40;74099:95;;74153:34;74149:38;74191:3;74149:45;74099:95;-1:-1:-1;;;74205:36:0;;:40;74201:95;;74255:34;74251:38;74293:3;74251:45;74201:95;-1:-1:-1;;;74307:36:0;;:40;74303:95;;74357:34;74353:38;74395:3;74353:45;74303:95;-1:-1:-1;;;74409:35:0;;:39;74405:94;;74458:34;74454:38;74496:3;74454:45;74405:94;-1:-1:-1;;;74510:35:0;;:39;74506:94;;74559:34;74555:38;74597:3;74555:45;74506:94;-1:-1:-1;;;74611:35:0;;:39;74607:94;;74660:34;74656:38;74698:3;74656:45;74607:94;-1:-1:-1;;;74712:35:0;;:39;74708:94;;74761:34;74757:38;74799:3;74757:45;74708:94;-1:-1:-1;;;74813:34:0;;:38;74809:93;;74861:34;74857:38;74899:3;74857:45;74809:93;-1:-1:-1;;;74913:34:0;;:38;74909:93;;74961:34;74957:38;74999:3;74957:45;74909:93;-1:-1:-1;;;75013:34:0;;:38;75009:93;;75061:34;75057:38;75099:3;75057:45;75009:93;-1:-1:-1;;;75113:34:0;;:38;75109:93;;75161:34;75157:38;75199:3;75157:45;75109:93;-1:-1:-1;;;75213:33:0;;:37;75209:92;;75260:34;75256:38;75298:3;75256:45;75209:92;-1:-1:-1;;;75312:33:0;;:37;75308:92;;75359:34;75355:38;75397:3;75355:45;75308:92;-1:-1:-1;;;75411:33:0;;:37;75407:92;;75458:34;75454:38;75496:3;75454:45;75407:92;-1:-1:-1;;;75510:33:0;;:37;75506:92;;75557:34;75553:38;75595:3;75553:45;75506:92;-1:-1:-1;;;75609:32:0;;:36;75605:91;;75655:34;75651:38;75693:3;75651:45;75605:91;-1:-1:-1;;;75707:32:0;;:36;75703:91;;75753:34;75749:38;75791:3;75749:45;75703:91;-1:-1:-1;;;75805:32:0;;:36;75801:91;;75851:34;75847:38;75889:3;75847:45;75801:91;-1:-1:-1;;;75903:32:0;;:36;75899:91;;75949:34;75945:38;75987:3;75945:45;75899:91;-1:-1:-1;;;76001:31:0;;:35;75997:90;;76046:34;76042:38;76084:3;76042:45;75997:90;-1:-1:-1;;;76098:31:0;;:35;76094:90;;76143:34;76139:38;76181:3;76139:45;76094:90;-1:-1:-1;;;76195:31:0;;:35;76191:90;;76240:34;76236:38;76278:3;76236:45;76191:90;-1:-1:-1;;;76292:31:0;;:35;76288:90;;76337:34;76333:38;76375:3;76333:45;76288:90;-1:-1:-1;;;76389:30:0;;:34;76385:89;;76433:34;76429:38;76471:3;76429:45;76385:89;-1:-1:-1;;;76485:30:0;;:34;76481:89;;76529:34;76525:38;76567:3;76525:45;76481:89;-1:-1:-1;;;76581:30:0;;:34;76577:89;;76625:34;76621:38;76663:3;76621:45;76577:89;-1:-1:-1;;;76677:30:0;;:34;76673:89;;76721:34;76717:38;76759:3;76717:45;76673:89;-1:-1:-1;;;76773:29:0;;:33;76769:88;;76816:34;76812:38;76854:3;76812:45;76769:88;-1:-1:-1;;;76868:29:0;;:33;76864:88;;76911:34;76907:38;76949:3;76907:45;76864:88;-1:-1:-1;;;76963:29:0;;:33;76959:88;;77006:34;77002:38;77044:3;77002:45;76959:88;-1:-1:-1;;;77058:29:0;;:33;77054:88;;77101:34;77097:38;77139:3;77097:45;77054:88;-1:-1:-1;;;77153:28:0;;:32;77149:87;;77195:34;77191:38;77233:3;77191:45;77149:87;-1:-1:-1;;;77247:28:0;;:32;77243:87;;77289:34;77285:38;77327:3;77285:45;77243:87;-1:-1:-1;;;77341:28:0;;:32;77337:87;;77383:34;77379:38;77421:3;77379:45;77337:87;-1:-1:-1;;;77435:28:0;;:32;77431:87;;77477:34;77473:38;77515:3;77473:45;77431:87;-1:-1:-1;;;77529:27:0;;:31;77525:86;;77570:34;77566:38;77608:3;77566:45;77525:86;-1:-1:-1;;;77622:27:0;;:31;77618:86;;77663:34;77659:38;77701:3;77659:45;77618:86;-1:-1:-1;;;77715:27:0;;:31;77711:86;;77756:34;77752:38;77794:3;77752:45;77711:86;-1:-1:-1;;;77808:27:0;;:31;77804:86;;77849:34;77845:38;77887:3;77845:45;77804:86;-1:-1:-1;;;77901:26:0;;:30;77897:85;;77941:34;77937:38;77979:3;77937:45;77897:85;-1:-1:-1;;;77993:26:0;;:30;77989:85;;78033:34;78029:38;78071:3;78029:45;77989:85;-1:-1:-1;;;78085:26:0;;:30;78081:85;;78125:34;78121:38;78163:3;78121:45;78081:85;-1:-1:-1;;;78177:26:0;;:30;78173:85;;78217:34;78213:38;78255:3;78213:45;78173:85;-1:-1:-1;;;78269:25:0;;:29;78265:84;;78308:34;78304:38;78346:3;78304:45;78265:84;-1:-1:-1;;;78360:25:0;;:29;78356:84;;78399:34;78395:38;78437:3;78395:45;78356:84;-1:-1:-1;;;78451:25:0;;:29;78447:84;;78490:34;78486:38;78528:3;78486:45;78447:84;-1:-1:-1;;;78542:25:0;;:29;78538:84;;78581:34;78577:38;78619:3;78577:45;78538:84;-1:-1:-1;;;78633:24:0;;:28;78629:83;;78671:34;78667:38;78709:3;78667:45;78629:83;-1:-1:-1;;;78723:24:0;;:28;78719:83;;78761:34;78757:38;78799:3;78757:45;78719:83;-1:-1:-1;;;78813:24:0;;:28;78809:83;;78851:34;78847:38;78889:3;78847:45;78809:83;-1:-1:-1;;;78903:24:0;;:28;78899:83;;78941:34;78937:38;78979:3;78937:45;78899:83;-1:-1:-1;;;78993:23:0;;:27;78989:82;;79030:34;79026:38;79068:3;79026:45;78989:82;-1:-1:-1;;;79082:23:0;;:27;79078:82;;79119:34;79115:38;79157:3;79115:45;79078:82;-1:-1:-1;;;79171:23:0;;:27;79167:82;;79208:34;79204:38;79246:3;79204:45;79167:82;-1:-1:-1;;;79260:23:0;;:27;79256:82;;79297:34;79293:38;79335:3;79293:45;79256:82;84557:8;84562:3;84557:8;;;;;84550:16;;-1:-1:-1;;;;;84544:22:0;;;-1:-1:-1;73775:10824:0;;;:::o

Swarm Source

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