Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
65,609.033935840865884538 ERC20 ***
Holders
453
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0.00000082485844721 ERC20 ***Value
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Pool
Compiler Version
v0.6.10+commit.00c0fcaf
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
61012060408190527f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb76080528060526200549e823960405190819003605201902060c052503480156200005157600080fd5b506040516200554238038062005542833981810160405260808110156200007757600080fd5b81516020830151604080850180519151939592948301929184640100000000821115620000a357600080fd5b908301906020820185811115620000b957600080fd5b8251640100000000811182820188101715620000d457600080fd5b82525081516020918201929091019080838360005b8381101562000103578181015183820152602001620000e9565b50505050905090810190601f168015620001315780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200015557600080fd5b9083019060208201858111156200016b57600080fd5b82516401000000008111828201881017156200018657600080fd5b82525081516020918201929091019080838360005b83811015620001b55781810151838201526020016200019b565b50505050905090810190601f168015620001e35780820380516001836020036101000a031916815260200191505b50604052505050818181818160039080519060200190620002069291906200049d565b5080516200021c9060049060208401906200049d565b50506005805460ff19166012179055506040514690806052620054f08239604080516052928190038301812081830183526005825264165a595b1960da1b6020928301528251808401845260018152603160f81b908301528251808301919091527f0dc8618f4925c4319195a39ada16304f511bf885ff9f3d63bc6b0f3979e46fb6818401526000805160206200547e833981519152606082015260808101959095523060a08087019190915282518087038201815260c09096019283905285519590910194909420909352469291508190620054f08239604080519182900360520182208651602097880120838301835260018452603160f81b93880193909352815180880191909152808201929092526000805160206200547e833981519152606083015260808201939093523060a0808301919091528351808303909101815260c0820180855281519187019190912060e052600980546001600160a01b038c81166001600160a01b031992831617909255600a80548c84169216919091179081905563204f83f960e01b90925293516200041e9691909416945063204f83f99360c480840194509192909190829003018186803b158015620003e157600080fd5b505afa158015620003f6573d6000803e3d6000fd5b505050506040513d60208110156200040d57600080fd5b50516001600160e01b036200043a16565b60801b6001600160801b03191661010052506200053792505050565b60006001600160801b0382111562000499576040805162461bcd60e51b815260206004820152601360248201527f506f6f6c3a2043617374206f766572666c6f7700000000000000000000000000604482015290519081900360640190fd5b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004e057805160ff191683800117855562000510565b8280016001018555821562000510579182015b8281111562000510578251825591602001919060010190620004f3565b506200049992620005349250905b808211156200049957600081556001016200051e565b90565b60805160a05160c05160e0516101005160801c614ea0620005de60003980610b695280610cf55280610d7b5280611096528061133b528061144b52806114dd5280611607528061169952806116fe52806117845280611a475280611eaa5280612125528061270c52806134985280613614525080610c575280612254525080610c2a52806121e7525080610a285280610ccf5250806109c35280611ac35250614ea06000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806385561a341161013b578063c0bd65d7116100b8578063e71bdf411161007c578063e71bdf41146107b9578063f4b9fa75146107df578063f6b911bc146107e7578063f6bcbd3114610836578063fa352c001461086457610248565b8063c0bd65d7146106bc578063c6c3bbe6146106c4578063cc5783d3146106fa578063d505accf1461073a578063dd62ed3e1461078b57610248565b8063a9059cbb116100ff578063a9059cbb1461061a578063b26be92214610646578063b4f40c6114610686578063b5d832fe1461068e578063bdd8a366146106b457610248565b806385561a341461057457806395d89b411461059a57806398ba4aec146105a25780639ac95875146105c8578063a457c2d7146105ee57610248565b806339509351116101c95780636970a9241161018d5780636970a924146104bf57806370a08231146104e05780637543e39c1461050657806377d739f3146105465780637ecebe001461054e57610248565b8063395093511461041d578063459e414f146104495780634e20e952146104515780635f4d07dc1461047757806360561e051461047f57610248565b806323b872dd1161021057806323b872dd14610395578063284f4444146103cb57806330adf81f146103ef578063313ce567146103f75780633644e5151461041557610248565b806306fdde031461024d578063095ea7b3146102ca57806318160ddd1461030a5780631a28ff0514610324578063204f83f914610371575b600080fd5b61025561088a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561028f578181015183820152602001610277565b50505050905090810190601f1680156102bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102f6600480360360408110156102e057600080fd5b506001600160a01b038135169060200135610920565b604080519115158252519081900360200190f35b61031261093e565b60408051918252519081900360200190f35b61036f600480360360c081101561033a57600080fd5b506001600160a01b03813581169160208101359091169060408101359060ff6060820135169060808101359060a00135610944565b005b610379610b67565b604080516001600160801b039092168252519081900360200190f35b6102f6600480360360608110156103ab57600080fd5b506001600160a01b03813581169160208101359091169060400135610b8b565b6103d3610c19565b604080516001600160a01b039092168252519081900360200190f35b610312610c28565b6103ff610c4c565b6040805160ff9092168252519081900360200190f35b610312610c55565b6102f66004803603604081101561043357600080fd5b506001600160a01b038135169060200135610c79565b610312610ccd565b6103796004803603602081101561046757600080fd5b50356001600160801b0316610cf1565b610379610dbe565b6103796004803603606081101561049557600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316610e5b565b6104c761110f565b60408051600f92830b90920b8252519081900360200190f35b610312600480360360208110156104f657600080fd5b50356001600160a01b0316611122565b6103796004803603606081101561051c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b031661113d565b6103796113b2565b6103126004803603602081101561056457600080fd5b50356001600160a01b0316611435565b6103796004803603602081101561058a57600080fd5b50356001600160801b0316611447565b6102556115a2565b610379600480360360208110156105b857600080fd5b50356001600160801b0316611603565b610379600480360360208110156105de57600080fd5b50356001600160801b03166116fa565b6102f66004803603604081101561060457600080fd5b506001600160a01b0381351690602001356117c7565b6102f66004803603604081101561063057600080fd5b506001600160a01b038135169060200135611835565b6103796004803603606081101561065c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611849565b6104c7611a8d565b610312600480360360208110156106a457600080fd5b50356001600160a01b0316611a9c565b6104c7611aae565b610312611ac1565b610312600480360360608110156106da57600080fd5b506001600160a01b03813581169160208101359091169060400135611ae5565b6103796004803603606081101561071057600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611f27565b61036f600480360360e081101561075057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612168565b610312600480360360408110156107a157600080fd5b506001600160a01b0381358116916020013516612396565b61036f600480360360208110156107cf57600080fd5b50356001600160a01b03166123c1565b6103d36123ce565b61081d600480360360608110156107fd57600080fd5b506001600160a01b038135811691602081013590911690604001356123dd565b6040805192835260208301919091528051918290030190f35b6102f66004803603604081101561084c57600080fd5b506001600160a01b0381358116916020013516612788565b61036f6004803603602081101561087a57600080fd5b50356001600160a01b03166127a8565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b5050505050905090565b600061093461092d6127b2565b84846127b6565b5060015b92915050565b60025490565b42841015610999576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b6001600160a01b0380871660008181526006602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c08501825280519083012061190160f01b60e08601527f000000000000000000000000000000000000000000000000000000000000000060e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c2808401939192601f1981019281900390910190855afa158015610acb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610b015750886001600160a01b0316816001600160a01b0316145b610b52576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b610b5c89896128a2565b505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610b98848484612989565b610c0e84610ba46127b2565b610c0985604051806060016040528060288152602001614d50602891396001600160a01b038a16600090815260016020526040812090610be26127b2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff612af016565b6127b6565b5060015b9392505050565b600a546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60055460ff1690565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610934610c866127b2565b84610c098560016000610c976127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612b4a16565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210610d61576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b610938610d6c6113b2565b610d74610dbe565b84610da9427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7268010d79435e50d79435612bfc565b6000610e56610e51610dce61093e565b600a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6020811015610e4357600080fd5b50519063ffffffff612b4a16565b612ba4565b905090565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480610ec557506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190610f4f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610f14578181015183820152602001610efc565b50505050905090810190601f168015610f415780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000610f5b856116fa565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b158015610fc157600080fd5b505af1158015610fd5573d6000803e3d6000fd5b505050506040513d6020811015610feb57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561104b57600080fd5b505af115801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f00000000000000000000000000000000000000000000000000000000000000006110c76001600160801b038616612df6565b6110d98a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925260000382820152519081900360600190a392505b50509392505050565b6103b66903e800000000000000005b0481565b6001600160a01b031660009081526020819052604090205490565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806111a757506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906111f45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061120085611603565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506040513d602081101561129057600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156112f057600080fd5b505af1158015611304573d6000803e3d6000fd5b505050506040513d602081101561131a57600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f000000000000000000000000000000000000000000000000000000000000000061136c6001600160801b038616612df6565b6000036113818a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925282820152519081900360600190a39695505050505050565b600954604080516370a0823160e01b81523060048201529051600092610e56926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561140457600080fd5b505afa158015611418573d6000803e3d6000fd5b505050506040513d602081101561142e57600080fd5b5051612ba4565b60086020526000908152604090205481565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b031642106114b7576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b60006114c16113b2565b905060006114cd610dbe565b9050600061151f83838761150b427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7267f333333333333333612e4a565b905061152b8386613027565b6001600160801b031661153e838361308d565b6001600160801b0316101561159a576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b949350505050565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210611673576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b600061167d6113b2565b90506000611689610dbe565b905060006116db8383876116c7427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7267f3333333333333336130fc565b90506116e78382613027565b6001600160801b031661153e838761308d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b0316421061176a576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b6109386117756113b2565b61177d610dbe565b846117b2427f00000000000000000000000000000000000000000000000000000000000000006001600160801b031603612ba4565b64220c523d7268010d79435e50d794356132e1565b60006109346117d46127b2565b84610c0985604051806060016040528060258152602001614e4660259139600160006117fe6127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff612af016565b60006109346118426127b2565b8484612989565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806118b357506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906119005760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061190c85611447565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561197257600080fd5b505af1158015611986573d6000803e3d6000fd5b505050506040513d602081101561199c57600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b505050506040513d6020811015611a2657600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000000000000611a786001600160801b038a16612df6565b600003611381866001600160801b0316612df6565b630784ce00600160401b61111e565b60066020526000908152604090205481565b6103e86903b6000000000000000061111e565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611b4f57506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611b9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611ba761093e565b905080611bbf57611bb785613494565b935050611106565b600954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c0a57600080fd5b505afa158015611c1e573d6000803e3d6000fd5b505050506040513d6020811015611c3457600080fd5b5051600a54604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611c8757600080fd5b505afa158015611c9b573d6000803e3d6000fd5b505050506040513d6020811015611cb157600080fd5b505190506000611cd783611ccb868b63ffffffff61367d16565b9063ffffffff6136d616565b90506000611cef85611ccb858563ffffffff61367d16565b90506001600160801b03611d09858b63ffffffff612b4a16565b1115611d1457600080fd5b6001600160801b03611d3c611d2f858463ffffffff612b4a16565b879063ffffffff612b4a16565b1115611d4757600080fd5b600954604080516323b872dd60e01b81526001600160a01b038e81166004830152306024830152604482018d9052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611da357600080fd5b505af1158015611db7573d6000803e3d6000fd5b505050506040513d6020811015611dcd57600080fd5b5051611dd857600080fd5b600a54604080516323b872dd60e01b81526001600160a01b038e8116600483015230602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611e3457600080fd5b505af1158015611e48573d6000803e3d6000fd5b505050506040513d6020811015611e5e57600080fd5b5051611e6957600080fd5b611e738a83613718565b896001600160a01b03168b6001600160a01b03167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000000000000611ed28d612df6565b600003611ede86612df6565b600003611eea88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a3509998505050505050505050565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611f9157506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611fde5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611fea85610cf1565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050506040513d602081101561207a57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156120da57600080fd5b505af11580156120ee573d6000803e3d6000fd5b505050506040513d602081101561210457600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f00000000000000000000000000000000000000000000000000000000000000006121566001600160801b038a16612df6565b6110d9866001600160801b0316612df6565b428410156121bd576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b6001600160a01b0380881660008181526008602090815260408083208054600180820190925582517f00000000000000000000000000000000000000000000000000000000000000008186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e08501825280519083012061190160f01b6101008601527f000000000000000000000000000000000000000000000000000000000000000061010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e2808401939192601f1981019281900390910190855afa1580156122f8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232e5750896001600160a01b0316816001600160a01b0316145b61237f576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b61238a8a8a8a6127b6565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6123cb33826128a2565b50565b6009546001600160a01b031681565b600080846040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b0316148061244857506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906124955760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b5060006124a061093e565b600954604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156124f157600080fd5b505afa158015612505573d6000803e3d6000fd5b505050506040513d602081101561251b57600080fd5b5051600a54604080516370a0823160e01b81523060048201529051929350600092839283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561257257600080fd5b505afa158015612586573d6000803e3d6000fd5b505050506040513d602081101561259c57600080fd5b505190506125b485611ccb8c8763ffffffff61367d16565b92506125ca85611ccb8c8463ffffffff61367d16565b9150506125d78b8a613814565b6009546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561262d57600080fd5b505af1158015612641573d6000803e3d6000fd5b505050506040513d602081101561265757600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505050506040513d60208110156126d957600080fd5b50506001600160a01b03808b16908c167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f000000000000000000000000000000000000000000000000000000000000000061273486612df6565b61273d86612df6565b6127468f612df6565b604080516001600160801b0390951685526020850193909352838301919091526000036060830152519081900360800190a3909a909950975050505050505050565b600760209081526000928352604080842090915290825290205460ff1681565b6123cb338261391c565b3390565b6001600160a01b0383166127fb5760405162461bcd60e51b8152600401808060200182810382526024815260200180614dde6024913960400191505060405180910390fd5b6001600160a01b0382166128405760405162461bcd60e51b8152600401808060200182810382526022815260200180614c7c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff161561291d576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b6001600160a01b03808316600081815260076020908152604080832094861680845294825291829020805460ff19166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b6001600160a01b0383166129ce5760405162461bcd60e51b8152600401808060200182810382526025815260200180614db96025913960400191505060405180910390fd5b6001600160a01b038216612a135760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0b6023913960400191505060405180910390fd5b612a1e8383836139fa565b612a6181604051806060016040528060268152602001614c9e602691396001600160a01b038616600090815260208190526040902054919063ffffffff612af016565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a96908263ffffffff612b4a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612b425760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b505050900390565b600082820183811015610c12576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160801b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b5090565b600080612c1a84612c15876001600160801b03166139ff565b613a1d565b90506000612c35600160401b612c308685613a1d565b613a54565b9050600081600f0b13612c7d576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b03808816908a1603600160801b8110612ce4576040805162461bcd60e51b815260206004820152601b60248201527f5969656c644d6174683a20546f6f206d75636820446169206f75740000000000604482015290519081900360640190fd5b6000612cf58284600160401b613a87565b612d048b85600160401b613a87565b612d138d86600160401b613a87565b01039050600160801b8110612d595760405162461bcd60e51b815260040180806020018281038252602c815260200180614c2e602c913960400191505060405180910390fd5b60008a6001600160801b0316612d7483600160401b87613a87565b039050600160801b8110612db95760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff8110612ddd576001600160801b03612de6565b8064e8d4a51000015b9c9b505050505050505050505050565b60006001600160ff1b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b600080612e6384612c15876001600160801b03166139ff565b90506000612e79600160401b612c308685613a1d565b9050600081600f0b13612ec1576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0389811690881601600160801b8110612f28576040805162461bcd60e51b815260206004820152601a60248201527f5969656c644d6174683a20546f6f206d7563682044616920696e000000000000604482015290519081900360640190fd5b6000612f398284600160401b613a87565b612f488b85600160401b613a87565b612f578d86600160401b613a87565b01039050600160801b8110612f9d5760405162461bcd60e51b8152600401808060200182810382526026815260200180614be56026913960400191505060405180910390fd5b6000612fae82600160401b86613a87565b8b6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b64e8d4a510008111613010576000612de6565b64e8d4a50fff19019b9a5050505050505050505050565b60008282016001600160801b038085169082161015610c12576040805162461bcd60e51b815260206004820152601b60248201527f506f6f6c3a2044616920726573657276657320746f6f20686967680000000000604482015290519081900360640190fd5b6000826001600160801b0316826001600160801b031611156130f6576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b50900390565b600080613121600160401b612c3085612c1588612c158b6001600160801b03166139ff565b9050600081600f0b13613169576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0380871690881603600160801b81106131d0576040805162461bcd60e51b815260206004820152601d60248201527f5969656c644d6174683a20546f6f206d756368206679446169206f7574000000604482015290519081900360640190fd5b60006131e18284600160401b613a87565b6131f08a85600160401b613a87565b6131ff8c86600160401b613a87565b01039050600160801b81106132455760405162461bcd60e51b815260040180806020018281038252602a815260200180614d05602a913960400191505060405180910390fd5b60008a6001600160801b031661326083600160401b87613a87565b039050600160801b81106132a55760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff81106132c9576001600160801b036132d2565b8064e8d4a51000015b9b9a5050505050505050505050565b6000806132fa84612c15876001600160801b03166139ff565b90506000613310600160401b612c308685613a1d565b9050600081600f0b13613358576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0388811690881601600160801b81106133bf576040805162461bcd60e51b815260206004820152601c60248201527f5969656c644d6174683a20546f6f206d75636820667944616920696e00000000604482015290519081900360640190fd5b60006133d08a84600160401b613a87565b6133df8385600160401b613a87565b6133ee8d86600160401b613a87565b03019050600160801b81106134345760405162461bcd60e51b8152600401808060200182810382526024815260200180614e226024913960400191505060405180910390fd5b600061344582600160401b86613a87565b8c6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160801b03164210613504576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b61350c61093e565b1561355e576040805162461bcd60e51b815260206004820152601960248201527f506f6f6c3a20416c726561647920696e697469616c697a656400000000000000604482015290519081900360640190fd5b600954604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135b857600080fd5b505af11580156135cc573d6000803e3d6000fd5b505050506040513d60208110156135e257600080fd5b506135ef90503383613718565b33807fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f000000000000000000000000000000000000000000000000000000000000000061363c86612df6565b600003600061364a88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a35090565b60008261368c57506000610938565b8282028284828161369957fe5b0414610c125760405162461bcd60e51b8152600401808060200182810382526021815260200180614d2f6021913960400191505060405180910390fd5b6000610c1283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613b3d565b6001600160a01b038216613773576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61377f600083836139fa565b600254613792908263ffffffff612b4a16565b6002556001600160a01b0382166000908152602081905260409020546137be908263ffffffff612b4a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166138595760405162461bcd60e51b8152600401808060200182810382526021815260200180614d786021913960400191505060405180910390fd5b613865826000836139fa565b6138a881604051806060016040528060228152602001614c5a602291396001600160a01b038516600090815260208190526040902054919063ffffffff612af016565b6001600160a01b0383166000908152602081905260409020556002546138d4908263ffffffff613ba216565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff16613996576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b6001600160a01b038083166000818152600760209081526040808320948616808452948252808320805460ff191690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b505050565b6000677fffffffffffffff821115613a1657600080fd5b5060401b90565b6000600f83810b9083900b0260401d60016001607f1b03198112801590613a4b575060016001607f1b038113155b610c1257600080fd5b6000600f82810b9084900b0360016001607f1b03198112801590613a4b575060016001607f1b03811315610c1257600080fd5b60006001600160801b038216613a9c57600080fd5b6001600160801b038416613ac5576001600160801b038316613abd57600080fd5b506000610c12565b6000826001600160801b0316846001600160801b0316613ae487613be4565b6001600160801b03036001600160801b03160281613afe57fe5b0490506001600160801b03811115613b1a576000915050610c12565b613b2c816001600160801b030361442f565b6001600160801b0316915050610c12565b60008183613b8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000838581613b9857fe5b0495945050505050565b6000610c1283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612af0565b60006001600160801b038216613bf957600080fd5b6001600160801b038216607f60791b600160401b821015613c265760409190911b9060016001607f1b0319015b600160601b821015613c4d5760209190911b906f3fffffffffffffffffffffffffffffff19015b600160701b821015613c745760109190911b906f1fffffffffffffffffffffffffffffff19015b600160781b821015613c9b5760089190911b906f0fffffffffffffffffffffffffffffff19015b6001607c1b821015613cc25760049190911b906f07ffffffffffffffffffffffffffffff19015b6001607e1b821015613ce95760029190911b906f03ffffffffffffffffffffffffffffff19015b6001607f1b821015613d105760019190911b906f01ffffffffffffffffffffffffffffff19015b908002607f1c90600160801b8210613d305760019190911c90600160781b175b908002607f1c90600160801b8210613d505760019190911c90600160771b175b908002607f1c90600160801b8210613d705760019190911c90600160761b175b908002607f1c90600160801b8210613d905760019190911c90600160751b175b908002607f1c90600160801b8210613db05760019190911c90600160741b175b908002607f1c90600160801b8210613dd05760019190911c90600160731b175b908002607f1c90600160801b8210613df05760019190911c90600160721b175b908002607f1c90600160801b8210613e105760019190911c90600160711b175b908002607f1c90600160801b8210613e305760019190911c90600160701b175b908002607f1c90600160801b8210613e505760019190911c906001606f1b175b908002607f1c90600160801b8210613e705760019190911c906001606e1b175b908002607f1c90600160801b8210613e905760019190911c906001606d1b175b908002607f1c90600160801b8210613eb05760019190911c906001606c1b175b908002607f1c90600160801b8210613ed05760019190911c906001606b1b175b908002607f1c90600160801b8210613ef05760019190911c906001606a1b175b908002607f1c90600160801b8210613f105760019190911c90600160691b175b908002607f1c90600160801b8210613f305760019190911c90600160681b175b908002607f1c90600160801b8210613f505760019190911c90600160671b175b908002607f1c90600160801b8210613f705760019190911c90600160661b175b908002607f1c90600160801b8210613f905760019190911c90600160651b175b908002607f1c90600160801b8210613fb05760019190911c90600160641b175b908002607f1c90600160801b8210613fd05760019190911c90600160631b175b908002607f1c90600160801b8210613ff05760019190911c90600160621b175b908002607f1c90600160801b82106140105760019190911c90600160611b175b908002607f1c90600160801b82106140305760019190911c90600160601b175b908002607f1c90600160801b82106140505760019190911c906001605f1b175b908002607f1c90600160801b82106140705760019190911c906001605e1b175b908002607f1c90600160801b82106140905760019190911c906001605d1b175b908002607f1c90600160801b82106140b05760019190911c906001605c1b175b908002607f1c90600160801b82106140d05760019190911c906001605b1b175b908002607f1c90600160801b82106140f05760019190911c906001605a1b175b908002607f1c90600160801b82106141105760019190911c90600160591b175b908002607f1c90600160801b82106141305760019190911c90600160581b175b908002607f1c90600160801b82106141505760019190911c90600160571b175b908002607f1c90600160801b82106141705760019190911c90600160561b175b908002607f1c90600160801b82106141905760019190911c90600160551b175b908002607f1c90600160801b82106141b05760019190911c90600160541b175b908002607f1c90600160801b82106141d05760019190911c90600160531b175b908002607f1c90600160801b82106141f05760019190911c90600160521b175b908002607f1c90600160801b82106142105760019190911c90600160511b175b908002607f1c90600160801b82106142305760019190911c90600160501b175b908002607f1c90600160801b82106142505760019190911c906001604f1b175b908002607f1c90600160801b82106142705760019190911c906001604e1b175b908002607f1c90600160801b82106142905760019190911c906001604d1b175b908002607f1c90600160801b82106142b05760019190911c906001604c1b175b908002607f1c90600160801b82106142d05760019190911c906001604b1b175b908002607f1c90600160801b82106142f05760019190911c906001604a1b175b908002607f1c90600160801b82106143105760019190911c90600160491b175b908002607f1c90600160801b82106143305760019190911c90600160481b175b908002607f1c90600160801b82106143505760019190911c90600160471b175b908002607f1c90600160801b82106143705760019190911c90600160461b175b908002607f1c90600160801b82106143905760019190911c90600160451b175b908002607f1c90600160801b82106143b05760019190911c90600160441b175b908002607f1c90600160801b82106143d05760019190911c90600160431b175b908002607f1c90600160801b82106143f05760019190911c90600160421b175b908002607f1c90600160801b82106144105760019190911c90600160411b175b908002607f1c90600160801b8210610c1257600160401b179392505050565b60006001607f1b600160781b831615614458576fb504f333f9de6484597d89b3754abe9f02607f1c5b600160771b83161561447a576f9837f0518db8a96f46ad23182e42f6f602607f1c5b600160761b83161561449c576f8b95c1e3ea8bd6e6fbe4628758a53c9002607f1c5b600160751b8316156144be576f85aac367cc487b14c5c95b8c2154c1b202607f1c5b600160741b8316156144e0576f82cd8698ac2ba1d73e2a475b46520bff02607f1c5b600160731b831615614502576f8164d1f3bc0307737be56527bd14def402607f1c5b600160721b831615614524576f80b1ed4fd999ab6c25335719b6e6fd2002607f1c5b600160711b831615614546576f8058d7d2d5e5f6b094d589f608ee4aa202607f1c5b600160701b831615614568576f802c6436d0e04f50ff8ce94a6797b3ce02607f1c5b6001606f1b83161561458a576f8016302f174676283690dfe44d11d00802607f1c5b6001606e1b8316156145ac576f800b179c82028fd0945e54e2ae18f2f002607f1c5b6001606d1b8316156145ce576f80058baf7fee3b5d1c718b38e549cb9302607f1c5b6001606c1b8316156145f0576f8002c5d00fdcfcb6b6566a58c048be1f02607f1c5b6001606b1b831615614612576f800162e61bed4a48e84c2e1a463473d902607f1c5b6001606a1b831615614634576f8000b17292f702a3aa22beacca94901302607f1c5b600160691b831615614656576f800058b92abbae02030c5fa5256f41fe02607f1c5b600160681b831615614678576f80002c5c8dade4d71776c0f4dbea67d602607f1c5b600160671b83161561469a576f8000162e44eaf636526be456600bdbe402607f1c5b600160661b8316156146bc576f80000b1721fa7c188307016c1cd4e8b602607f1c5b600160651b8316156146de576f8000058b90de7e4cecfc487503488bb102607f1c5b600160641b831615614700576f800002c5c8678f36cbfce50a6de60b1402607f1c5b600160631b831615614722576f80000162e431db9f80b2347b5d62e51602607f1c5b600160621b831615614744576f800000b1721872d0c7b08cf1e011415202607f1c5b600160611b831615614766576f80000058b90c1aa8a5c3736cb77e8dff02607f1c5b600160601b831615614788576f8000002c5c8605a4635f2efc2362d97802607f1c5b6001605f1b8316156147aa576f800000162e4300e635cf4a109e3939bd02607f1c5b6001605e1b8316156147cc576f8000000b17217ff81bef9c551590cf8302607f1c5b6001605d1b8316156147ee576f800000058b90bfdd4e39cd52c0cfa27c02607f1c5b6001605c1b831615614810576f80000002c5c85fe6f72d669e0e76e41102607f1c5b6001605b1b831615614832576f8000000162e42ff18f9ad35186d0df2802607f1c5b6001605a1b831615614854576f80000000b17217f84cce71aa0dcfffe702607f1c5b600160591b831615614876576f8000000058b90bfc07a77ad56ed22aaa02607f1c5b600160581b831615614898576f800000002c5c85fdfc23cdead40da8d602607f1c5b600160571b8316156148ba576f80000000162e42fefc25eb1571853a6602607f1c5b600160561b8316156148dc576f800000000b17217f7d97f692baacded502607f1c5b600160551b8316156148fe576f80000000058b90bfbead3b8b5dd254d702607f1c5b600160541b831615614920576f8000000002c5c85fdf4eedd62f084e6702607f1c5b600160531b831615614942576f800000000162e42fefa58aef378bf58602607f1c5b600160521b831615614964576f8000000000b17217f7d24a78a3c7ef0202607f1c5b600160511b831615614986576f800000000058b90bfbe9067c93e474a602607f1c5b600160501b8316156149a8576f80000000002c5c85fdf47b8e5a72599f02607f1c5b6001604f1b8316156149ca576f8000000000162e42fefa3bdb315934a202607f1c5b6001604e1b8316156149ec576f80000000000b17217f7d1d7299b49c4602607f1c5b6001604d1b831615614a0e576f8000000000058b90bfbe8e9a8d1c4ea002607f1c5b6001604c1b831615614a30576f800000000002c5c85fdf4745969ea76f02607f1c5b6001604b1b831615614a52576f80000000000162e42fefa3a0df5373bf02607f1c5b6001604a1b831615614a74576f800000000000b17217f7d1cff4aac1e102607f1c5b600160491b831615614a96576f80000000000058b90bfbe8e7db95a2f102607f1c5b600160481b831615614ab8576f8000000000002c5c85fdf473e61ae1f802607f1c5b600160471b831615614ada576f800000000000162e42fefa39f121751c02607f1c5b600160461b831615614afc576f8000000000000b17217f7d1cf815bb9602607f1c5b600160451b831615614b1e576f800000000000058b90bfbe8e7bec1e0d02607f1c5b600160441b831615614b40576f80000000000002c5c85fdf473dee5f1702607f1c5b600160431b831615614b62576f8000000000000162e42fefa39ef5438f02607f1c5b600160421b831615614b84576f80000000000000b17217f7d1cf7a26c802607f1c5b600160411b831615614ba6576f8000000000000058b90bfbe8e7bcf4a402607f1c5b600160401b831615614bc8576f800000000000002c5c85fdf473de72a202607f1c5b607f607984901c811690036001600160801b03161c905091905056fe5969656c644d6174683a20496e73756666696369656e7420667944616920726573657276657345524332303a207472616e7366657220746f20746865207a65726f20616464726573735969656c644d6174683a20526573756c74696e6720667944616920726573657276657320746f6f206869676845524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63653f207773c457c66e004ab34e2ce7ae1fcafc7b4c3286f63997c87428014219155969656c644d6174683a20526f756e64696e6720696e6475636564206572726f725969656c644d6174683a20526573756c74696e672044616920726573657276657320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f2061646472657373506f6f6c3a204f6e6c7920486f6c646572204f722044656c656761746500000045524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735969656c644d6174683a20546f6f206661722066726f6d206d617475726974795969656c644d6174683a20496e73756666696369656e742044616920726573657276657345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220dfcf38324d56249e8a26c32edabb5f6f86fc1ce3ab9e6844ae333018550aedef64736f6c634300060a0033c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc65065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374290000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000009d7e85d095934471a2788f485a3c765d0a463bd7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001b5969656c6420446169202d20323032312d31322d33312d506f6f6c0000000000000000000000000000000000000000000000000000000000000000000000000c66794461694c5032314465630000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102485760003560e01c806385561a341161013b578063c0bd65d7116100b8578063e71bdf411161007c578063e71bdf41146107b9578063f4b9fa75146107df578063f6b911bc146107e7578063f6bcbd3114610836578063fa352c001461086457610248565b8063c0bd65d7146106bc578063c6c3bbe6146106c4578063cc5783d3146106fa578063d505accf1461073a578063dd62ed3e1461078b57610248565b8063a9059cbb116100ff578063a9059cbb1461061a578063b26be92214610646578063b4f40c6114610686578063b5d832fe1461068e578063bdd8a366146106b457610248565b806385561a341461057457806395d89b411461059a57806398ba4aec146105a25780639ac95875146105c8578063a457c2d7146105ee57610248565b806339509351116101c95780636970a9241161018d5780636970a924146104bf57806370a08231146104e05780637543e39c1461050657806377d739f3146105465780637ecebe001461054e57610248565b8063395093511461041d578063459e414f146104495780634e20e952146104515780635f4d07dc1461047757806360561e051461047f57610248565b806323b872dd1161021057806323b872dd14610395578063284f4444146103cb57806330adf81f146103ef578063313ce567146103f75780633644e5151461041557610248565b806306fdde031461024d578063095ea7b3146102ca57806318160ddd1461030a5780631a28ff0514610324578063204f83f914610371575b600080fd5b61025561088a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561028f578181015183820152602001610277565b50505050905090810190601f1680156102bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102f6600480360360408110156102e057600080fd5b506001600160a01b038135169060200135610920565b604080519115158252519081900360200190f35b61031261093e565b60408051918252519081900360200190f35b61036f600480360360c081101561033a57600080fd5b506001600160a01b03813581169160208101359091169060408101359060ff6060820135169060808101359060a00135610944565b005b610379610b67565b604080516001600160801b039092168252519081900360200190f35b6102f6600480360360608110156103ab57600080fd5b506001600160a01b03813581169160208101359091169060400135610b8b565b6103d3610c19565b604080516001600160a01b039092168252519081900360200190f35b610312610c28565b6103ff610c4c565b6040805160ff9092168252519081900360200190f35b610312610c55565b6102f66004803603604081101561043357600080fd5b506001600160a01b038135169060200135610c79565b610312610ccd565b6103796004803603602081101561046757600080fd5b50356001600160801b0316610cf1565b610379610dbe565b6103796004803603606081101561049557600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316610e5b565b6104c761110f565b60408051600f92830b90920b8252519081900360200190f35b610312600480360360208110156104f657600080fd5b50356001600160a01b0316611122565b6103796004803603606081101561051c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b031661113d565b6103796113b2565b6103126004803603602081101561056457600080fd5b50356001600160a01b0316611435565b6103796004803603602081101561058a57600080fd5b50356001600160801b0316611447565b6102556115a2565b610379600480360360208110156105b857600080fd5b50356001600160801b0316611603565b610379600480360360208110156105de57600080fd5b50356001600160801b03166116fa565b6102f66004803603604081101561060457600080fd5b506001600160a01b0381351690602001356117c7565b6102f66004803603604081101561063057600080fd5b506001600160a01b038135169060200135611835565b6103796004803603606081101561065c57600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611849565b6104c7611a8d565b610312600480360360208110156106a457600080fd5b50356001600160a01b0316611a9c565b6104c7611aae565b610312611ac1565b610312600480360360608110156106da57600080fd5b506001600160a01b03813581169160208101359091169060400135611ae5565b6103796004803603606081101561071057600080fd5b5080356001600160a01b0390811691602081013590911690604001356001600160801b0316611f27565b61036f600480360360e081101561075057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612168565b610312600480360360408110156107a157600080fd5b506001600160a01b0381358116916020013516612396565b61036f600480360360208110156107cf57600080fd5b50356001600160a01b03166123c1565b6103d36123ce565b61081d600480360360608110156107fd57600080fd5b506001600160a01b038135811691602081013590911690604001356123dd565b6040805192835260208301919091528051918290030190f35b6102f66004803603604081101561084c57600080fd5b506001600160a01b0381358116916020013516612788565b61036f6004803603602081101561087a57600080fd5b50356001600160a01b03166127a8565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b5050505050905090565b600061093461092d6127b2565b84846127b6565b5060015b92915050565b60025490565b42841015610999576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a205369676e6174757265206578706972656400000000604482015290519081900360640190fd5b6001600160a01b0380871660008181526006602090815260408083208054600180820190925582517f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb78186015280840196909652958b166060860152608085019590955260a08085018a90528151808603909101815260c08501825280519083012061190160f01b60e08601527f449247df3eb4d7fb3b5d0b8c1416e3831b94e325cee0ad7ec7f833df5c34199460e286015261010280860182905282518087039091018152610122860180845281519185019190912090859052610142860180845281905260ff8a1661016287015261018286018990526101a2860188905291519095919491926101c2808401939192601f1981019281900390910190855afa158015610acb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610b015750886001600160a01b0316816001600160a01b0316145b610b52576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20496e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b610b5c89896128a2565b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000061cf997f81565b6000610b98848484612989565b610c0e84610ba46127b2565b610c0985604051806060016040528060288152602001614d50602891396001600160a01b038a16600090815260016020526040812090610be26127b2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff612af016565b6127b6565b5060015b9392505050565b600a546001600160a01b031681565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b7fa652f871f99749df17333b21b05c2eff92ae2114e2df4ce48a2cbb3456307a7a81565b6000610934610c866127b2565b84610c098560016000610c976127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612b4a16565b7f449247df3eb4d7fb3b5d0b8c1416e3831b94e325cee0ad7ec7f833df5c34199481565b60007f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b03164210610d61576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b610938610d6c6113b2565b610d74610dbe565b84610da9427f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b031603612ba4565b64220c523d7268010d79435e50d79435612bfc565b6000610e56610e51610dce61093e565b600a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6020811015610e4357600080fd5b50519063ffffffff612b4a16565b612ba4565b905090565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480610ec557506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190610f4f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610f14578181015183820152602001610efc565b50505050905090810190601f168015610f415780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000610f5b856116fa565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b158015610fc157600080fd5b505af1158015610fd5573d6000803e3d6000fd5b505050506040513d6020811015610feb57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561104b57600080fd5b505af115801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061cf997f6110c76001600160801b038616612df6565b6110d98a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925260000382820152519081900360600190a392505b50509392505050565b6103b66903e800000000000000005b0481565b6001600160a01b031660009081526020819052604090205490565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806111a757506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906111f45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061120085611603565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506040513d602081101561129057600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156112f057600080fd5b505af1158015611304573d6000803e3d6000fd5b505050506040513d602081101561131a57600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061cf997f61136c6001600160801b038616612df6565b6000036113818a6001600160801b0316612df6565b604080516001600160801b039094168452602084019290925282820152519081900360600190a39695505050505050565b600954604080516370a0823160e01b81523060048201529051600092610e56926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561140457600080fd5b505afa158015611418573d6000803e3d6000fd5b505050506040513d602081101561142e57600080fd5b5051612ba4565b60086020526000908152604090205481565b60007f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b031642106114b7576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b60006114c16113b2565b905060006114cd610dbe565b9050600061151f83838761150b427f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b031603612ba4565b64220c523d7267f333333333333333612e4a565b905061152b8386613027565b6001600160801b031661153e838361308d565b6001600160801b0316101561159a576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b949350505050565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109165780601f106108eb57610100808354040283529160200191610916565b60007f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b03164210611673576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b600061167d6113b2565b90506000611689610dbe565b905060006116db8383876116c7427f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b031603612ba4565b64220c523d7267f3333333333333336130fc565b90506116e78382613027565b6001600160801b031661153e838761308d565b60007f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b0316421061176a576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b6109386117756113b2565b61177d610dbe565b846117b2427f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b031603612ba4565b64220c523d7268010d79435e50d794356132e1565b60006109346117d46127b2565b84610c0985604051806060016040528060258152602001614e4660259139600160006117fe6127b2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff612af016565b60006109346118426127b2565b8484612989565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b031614806118b357506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906119005760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b50600061190c85611447565b600954604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038a16604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561197257600080fd5b505af1158015611986573d6000803e3d6000fd5b505050506040513d602081101561199c57600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03851660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b505050506040513d6020811015611a2657600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061cf997f611a786001600160801b038a16612df6565b600003611381866001600160801b0316612df6565b630784ce00600160401b61111e565b60066020526000908152604090205481565b6103e86903b6000000000000000061111e565b7f0d077601844dd17f704bafff948229d27f33b57445915754dfe3d095fda2beb781565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611b4f57506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611b9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611ba761093e565b905080611bbf57611bb785613494565b935050611106565b600954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c0a57600080fd5b505afa158015611c1e573d6000803e3d6000fd5b505050506040513d6020811015611c3457600080fd5b5051600a54604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611c8757600080fd5b505afa158015611c9b573d6000803e3d6000fd5b505050506040513d6020811015611cb157600080fd5b505190506000611cd783611ccb868b63ffffffff61367d16565b9063ffffffff6136d616565b90506000611cef85611ccb858563ffffffff61367d16565b90506001600160801b03611d09858b63ffffffff612b4a16565b1115611d1457600080fd5b6001600160801b03611d3c611d2f858463ffffffff612b4a16565b879063ffffffff612b4a16565b1115611d4757600080fd5b600954604080516323b872dd60e01b81526001600160a01b038e81166004830152306024830152604482018d9052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611da357600080fd5b505af1158015611db7573d6000803e3d6000fd5b505050506040513d6020811015611dcd57600080fd5b5051611dd857600080fd5b600a54604080516323b872dd60e01b81526001600160a01b038e8116600483015230602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015611e3457600080fd5b505af1158015611e48573d6000803e3d6000fd5b505050506040513d6020811015611e5e57600080fd5b5051611e6957600080fd5b611e738a83613718565b896001600160a01b03168b6001600160a01b03167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061cf997f611ed28d612df6565b600003611ede86612df6565b600003611eea88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a3509998505050505050505050565b6000836040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b03161480611f9157506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b8190611fde5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000611fea85610cf1565b600a54604080516323b872dd60e01b81526001600160a01b038b811660048301523060248301526001600160801b038516604483015291519394509116916323b872dd916064808201926020929091908290030181600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050506040513d602081101561207a57600080fd5b50506009546040805163a9059cbb60e01b81526001600160a01b0389811660048301526001600160801b03891660248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156120da57600080fd5b505af11580156120ee573d6000803e3d6000fd5b505050506040513d602081101561210457600080fd5b50506001600160a01b03808716908816600080516020614cc48339815191527f0000000000000000000000000000000000000000000000000000000061cf997f6121566001600160801b038a16612df6565b6110d9866001600160801b0316612df6565b428410156121bd576040805162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015290519081900360640190fd5b6001600160a01b0380881660008181526008602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e08501825280519083012061190160f01b6101008601527fa652f871f99749df17333b21b05c2eff92ae2114e2df4ce48a2cbb3456307a7a61010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e2808401939192601f1981019281900390910190855afa1580156122f8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061232e5750896001600160a01b0316816001600160a01b0316145b61237f576040805162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b61238a8a8a8a6127b6565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6123cb33826128a2565b50565b6009546001600160a01b031681565b600080846040518060400160405280601d8152602001600080516020614d99833981519152815250816001600160a01b0316336001600160a01b0316148061244857506001600160a01b038216600090815260076020908152604080832033845290915290205460ff165b81906124955760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b5060006124a061093e565b600954604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156124f157600080fd5b505afa158015612505573d6000803e3d6000fd5b505050506040513d602081101561251b57600080fd5b5051600a54604080516370a0823160e01b81523060048201529051929350600092839283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561257257600080fd5b505afa158015612586573d6000803e3d6000fd5b505050506040513d602081101561259c57600080fd5b505190506125b485611ccb8c8763ffffffff61367d16565b92506125ca85611ccb8c8463ffffffff61367d16565b9150506125d78b8a613814565b6009546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561262d57600080fd5b505af1158015612641573d6000803e3d6000fd5b505050506040513d602081101561265757600080fd5b5050600a546040805163a9059cbb60e01b81526001600160a01b038d81166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156126af57600080fd5b505af11580156126c3573d6000803e3d6000fd5b505050506040513d60208110156126d957600080fd5b50506001600160a01b03808b16908c167fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061cf997f61273486612df6565b61273d86612df6565b6127468f612df6565b604080516001600160801b0390951685526020850193909352838301919091526000036060830152519081900360800190a3909a909950975050505050505050565b600760209081526000928352604080842090915290825290205460ff1681565b6123cb338261391c565b3390565b6001600160a01b0383166127fb5760405162461bcd60e51b8152600401808060200182810382526024815260200180614dde6024913960400191505060405180910390fd5b6001600160a01b0382166128405760405162461bcd60e51b8152600401808060200182810382526022815260200180614c7c6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff161561291d576040805162461bcd60e51b815260206004820152601c60248201527f44656c656761626c653a20416c72656164792064656c65676174656400000000604482015290519081900360640190fd5b6001600160a01b03808316600081815260076020908152604080832094861680845294825291829020805460ff19166001908117909155825190815291517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b6001600160a01b0383166129ce5760405162461bcd60e51b8152600401808060200182810382526025815260200180614db96025913960400191505060405180910390fd5b6001600160a01b038216612a135760405162461bcd60e51b8152600401808060200182810382526023815260200180614c0b6023913960400191505060405180910390fd5b612a1e8383836139fa565b612a6181604051806060016040528060268152602001614c9e602691396001600160a01b038616600090815260208190526040902054919063ffffffff612af016565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612a96908263ffffffff612b4a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612b425760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b505050900390565b600082820183811015610c12576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006001600160801b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b5090565b600080612c1a84612c15876001600160801b03166139ff565b613a1d565b90506000612c35600160401b612c308685613a1d565b613a54565b9050600081600f0b13612c7d576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b03808816908a1603600160801b8110612ce4576040805162461bcd60e51b815260206004820152601b60248201527f5969656c644d6174683a20546f6f206d75636820446169206f75740000000000604482015290519081900360640190fd5b6000612cf58284600160401b613a87565b612d048b85600160401b613a87565b612d138d86600160401b613a87565b01039050600160801b8110612d595760405162461bcd60e51b815260040180806020018281038252602c815260200180614c2e602c913960400191505060405180910390fd5b60008a6001600160801b0316612d7483600160401b87613a87565b039050600160801b8110612db95760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff8110612ddd576001600160801b03612de6565b8064e8d4a51000015b9c9b505050505050505050505050565b60006001600160ff1b03821115612bf8576040805162461bcd60e51b8152602060048201526013602482015272506f6f6c3a2043617374206f766572666c6f7760681b604482015290519081900360640190fd5b600080612e6384612c15876001600160801b03166139ff565b90506000612e79600160401b612c308685613a1d565b9050600081600f0b13612ec1576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0389811690881601600160801b8110612f28576040805162461bcd60e51b815260206004820152601a60248201527f5969656c644d6174683a20546f6f206d7563682044616920696e000000000000604482015290519081900360640190fd5b6000612f398284600160401b613a87565b612f488b85600160401b613a87565b612f578d86600160401b613a87565b01039050600160801b8110612f9d5760405162461bcd60e51b8152600401808060200182810382526026815260200180614be56026913960400191505060405180910390fd5b6000612fae82600160401b86613a87565b8b6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b64e8d4a510008111613010576000612de6565b64e8d4a50fff19019b9a5050505050505050505050565b60008282016001600160801b038085169082161015610c12576040805162461bcd60e51b815260206004820152601b60248201527f506f6f6c3a2044616920726573657276657320746f6f20686967680000000000604482015290519081900360640190fd5b6000826001600160801b0316826001600160801b031611156130f6576040805162461bcd60e51b815260206004820152601c60248201527f506f6f6c3a20667944616920726573657276657320746f6f206c6f7700000000604482015290519081900360640190fd5b50900390565b600080613121600160401b612c3085612c1588612c158b6001600160801b03166139ff565b9050600081600f0b13613169576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0380871690881603600160801b81106131d0576040805162461bcd60e51b815260206004820152601d60248201527f5969656c644d6174683a20546f6f206d756368206679446169206f7574000000604482015290519081900360640190fd5b60006131e18284600160401b613a87565b6131f08a85600160401b613a87565b6131ff8c86600160401b613a87565b01039050600160801b81106132455760405162461bcd60e51b815260040180806020018281038252602a815260200180614d05602a913960400191505060405180910390fd5b60008a6001600160801b031661326083600160401b87613a87565b039050600160801b81106132a55760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b6fffffffffffffffffffffff172b5aefff81106132c9576001600160801b036132d2565b8064e8d4a51000015b9b9a5050505050505050505050565b6000806132fa84612c15876001600160801b03166139ff565b90506000613310600160401b612c308685613a1d565b9050600081600f0b13613358576040805162461bcd60e51b81526020600482018190526024820152600080516020614e02833981519152604482015290519081900360640190fd5b6001600160801b0388811690881601600160801b81106133bf576040805162461bcd60e51b815260206004820152601c60248201527f5969656c644d6174683a20546f6f206d75636820667944616920696e00000000604482015290519081900360640190fd5b60006133d08a84600160401b613a87565b6133df8385600160401b613a87565b6133ee8d86600160401b613a87565b03019050600160801b81106134345760405162461bcd60e51b8152600401808060200182810382526024815260200180614e226024913960400191505060405180910390fd5b600061344582600160401b86613a87565b8c6001600160801b0316039050600160801b8110612ffd5760405162461bcd60e51b8152600401808060200182810382526021815260200180614ce46021913960400191505060405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000061cf997f6001600160801b03164210613504576040805162461bcd60e51b815260206004820152600e60248201526d506f6f6c3a20546f6f206c61746560901b604482015290519081900360640190fd5b61350c61093e565b1561355e576040805162461bcd60e51b815260206004820152601960248201527f506f6f6c3a20416c726561647920696e697469616c697a656400000000000000604482015290519081900360640190fd5b600954604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135b857600080fd5b505af11580156135cc573d6000803e3d6000fd5b505050506040513d60208110156135e257600080fd5b506135ef90503383613718565b33807fd9b421596e3bc3caf78305bc0d270566916f58cd61b71c9c2a3d923a3ea3ea8b7f0000000000000000000000000000000000000000000000000000000061cf997f61363c86612df6565b600003600061364a88612df6565b604080516001600160801b0390951685526020850193909352838301919091526060830152519081900360800190a35090565b60008261368c57506000610938565b8282028284828161369957fe5b0414610c125760405162461bcd60e51b8152600401808060200182810382526021815260200180614d2f6021913960400191505060405180910390fd5b6000610c1283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613b3d565b6001600160a01b038216613773576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61377f600083836139fa565b600254613792908263ffffffff612b4a16565b6002556001600160a01b0382166000908152602081905260409020546137be908263ffffffff612b4a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b0382166138595760405162461bcd60e51b8152600401808060200182810382526021815260200180614d786021913960400191505060405180910390fd5b613865826000836139fa565b6138a881604051806060016040528060228152602001614c5a602291396001600160a01b038516600090815260208190526040902054919063ffffffff612af016565b6001600160a01b0383166000908152602081905260409020556002546138d4908263ffffffff613ba216565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b0380831660009081526007602090815260408083209385168352929052205460ff16613996576040805162461bcd60e51b815260206004820152601e60248201527f44656c656761626c653a20416c726561647920756e64656c6567617465640000604482015290519081900360640190fd5b6001600160a01b038083166000818152600760209081526040808320948616808452948252808320805460ff191690558051928352517f045b0fef01772d2fbba53dbd38c9777806eac0865b00af43abcfbcaf50da92069281900390910190a35050565b505050565b6000677fffffffffffffff821115613a1657600080fd5b5060401b90565b6000600f83810b9083900b0260401d60016001607f1b03198112801590613a4b575060016001607f1b038113155b610c1257600080fd5b6000600f82810b9084900b0360016001607f1b03198112801590613a4b575060016001607f1b03811315610c1257600080fd5b60006001600160801b038216613a9c57600080fd5b6001600160801b038416613ac5576001600160801b038316613abd57600080fd5b506000610c12565b6000826001600160801b0316846001600160801b0316613ae487613be4565b6001600160801b03036001600160801b03160281613afe57fe5b0490506001600160801b03811115613b1a576000915050610c12565b613b2c816001600160801b030361442f565b6001600160801b0316915050610c12565b60008183613b8c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610f14578181015183820152602001610efc565b506000838581613b9857fe5b0495945050505050565b6000610c1283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612af0565b60006001600160801b038216613bf957600080fd5b6001600160801b038216607f60791b600160401b821015613c265760409190911b9060016001607f1b0319015b600160601b821015613c4d5760209190911b906f3fffffffffffffffffffffffffffffff19015b600160701b821015613c745760109190911b906f1fffffffffffffffffffffffffffffff19015b600160781b821015613c9b5760089190911b906f0fffffffffffffffffffffffffffffff19015b6001607c1b821015613cc25760049190911b906f07ffffffffffffffffffffffffffffff19015b6001607e1b821015613ce95760029190911b906f03ffffffffffffffffffffffffffffff19015b6001607f1b821015613d105760019190911b906f01ffffffffffffffffffffffffffffff19015b908002607f1c90600160801b8210613d305760019190911c90600160781b175b908002607f1c90600160801b8210613d505760019190911c90600160771b175b908002607f1c90600160801b8210613d705760019190911c90600160761b175b908002607f1c90600160801b8210613d905760019190911c90600160751b175b908002607f1c90600160801b8210613db05760019190911c90600160741b175b908002607f1c90600160801b8210613dd05760019190911c90600160731b175b908002607f1c90600160801b8210613df05760019190911c90600160721b175b908002607f1c90600160801b8210613e105760019190911c90600160711b175b908002607f1c90600160801b8210613e305760019190911c90600160701b175b908002607f1c90600160801b8210613e505760019190911c906001606f1b175b908002607f1c90600160801b8210613e705760019190911c906001606e1b175b908002607f1c90600160801b8210613e905760019190911c906001606d1b175b908002607f1c90600160801b8210613eb05760019190911c906001606c1b175b908002607f1c90600160801b8210613ed05760019190911c906001606b1b175b908002607f1c90600160801b8210613ef05760019190911c906001606a1b175b908002607f1c90600160801b8210613f105760019190911c90600160691b175b908002607f1c90600160801b8210613f305760019190911c90600160681b175b908002607f1c90600160801b8210613f505760019190911c90600160671b175b908002607f1c90600160801b8210613f705760019190911c90600160661b175b908002607f1c90600160801b8210613f905760019190911c90600160651b175b908002607f1c90600160801b8210613fb05760019190911c90600160641b175b908002607f1c90600160801b8210613fd05760019190911c90600160631b175b908002607f1c90600160801b8210613ff05760019190911c90600160621b175b908002607f1c90600160801b82106140105760019190911c90600160611b175b908002607f1c90600160801b82106140305760019190911c90600160601b175b908002607f1c90600160801b82106140505760019190911c906001605f1b175b908002607f1c90600160801b82106140705760019190911c906001605e1b175b908002607f1c90600160801b82106140905760019190911c906001605d1b175b908002607f1c90600160801b82106140b05760019190911c906001605c1b175b908002607f1c90600160801b82106140d05760019190911c906001605b1b175b908002607f1c90600160801b82106140f05760019190911c906001605a1b175b908002607f1c90600160801b82106141105760019190911c90600160591b175b908002607f1c90600160801b82106141305760019190911c90600160581b175b908002607f1c90600160801b82106141505760019190911c90600160571b175b908002607f1c90600160801b82106141705760019190911c90600160561b175b908002607f1c90600160801b82106141905760019190911c90600160551b175b908002607f1c90600160801b82106141b05760019190911c90600160541b175b908002607f1c90600160801b82106141d05760019190911c90600160531b175b908002607f1c90600160801b82106141f05760019190911c90600160521b175b908002607f1c90600160801b82106142105760019190911c90600160511b175b908002607f1c90600160801b82106142305760019190911c90600160501b175b908002607f1c90600160801b82106142505760019190911c906001604f1b175b908002607f1c90600160801b82106142705760019190911c906001604e1b175b908002607f1c90600160801b82106142905760019190911c906001604d1b175b908002607f1c90600160801b82106142b05760019190911c906001604c1b175b908002607f1c90600160801b82106142d05760019190911c906001604b1b175b908002607f1c90600160801b82106142f05760019190911c906001604a1b175b908002607f1c90600160801b82106143105760019190911c90600160491b175b908002607f1c90600160801b82106143305760019190911c90600160481b175b908002607f1c90600160801b82106143505760019190911c90600160471b175b908002607f1c90600160801b82106143705760019190911c90600160461b175b908002607f1c90600160801b82106143905760019190911c90600160451b175b908002607f1c90600160801b82106143b05760019190911c90600160441b175b908002607f1c90600160801b82106143d05760019190911c90600160431b175b908002607f1c90600160801b82106143f05760019190911c90600160421b175b908002607f1c90600160801b82106144105760019190911c90600160411b175b908002607f1c90600160801b8210610c1257600160401b179392505050565b60006001607f1b600160781b831615614458576fb504f333f9de6484597d89b3754abe9f02607f1c5b600160771b83161561447a576f9837f0518db8a96f46ad23182e42f6f602607f1c5b600160761b83161561449c576f8b95c1e3ea8bd6e6fbe4628758a53c9002607f1c5b600160751b8316156144be576f85aac367cc487b14c5c95b8c2154c1b202607f1c5b600160741b8316156144e0576f82cd8698ac2ba1d73e2a475b46520bff02607f1c5b600160731b831615614502576f8164d1f3bc0307737be56527bd14def402607f1c5b600160721b831615614524576f80b1ed4fd999ab6c25335719b6e6fd2002607f1c5b600160711b831615614546576f8058d7d2d5e5f6b094d589f608ee4aa202607f1c5b600160701b831615614568576f802c6436d0e04f50ff8ce94a6797b3ce02607f1c5b6001606f1b83161561458a576f8016302f174676283690dfe44d11d00802607f1c5b6001606e1b8316156145ac576f800b179c82028fd0945e54e2ae18f2f002607f1c5b6001606d1b8316156145ce576f80058baf7fee3b5d1c718b38e549cb9302607f1c5b6001606c1b8316156145f0576f8002c5d00fdcfcb6b6566a58c048be1f02607f1c5b6001606b1b831615614612576f800162e61bed4a48e84c2e1a463473d902607f1c5b6001606a1b831615614634576f8000b17292f702a3aa22beacca94901302607f1c5b600160691b831615614656576f800058b92abbae02030c5fa5256f41fe02607f1c5b600160681b831615614678576f80002c5c8dade4d71776c0f4dbea67d602607f1c5b600160671b83161561469a576f8000162e44eaf636526be456600bdbe402607f1c5b600160661b8316156146bc576f80000b1721fa7c188307016c1cd4e8b602607f1c5b600160651b8316156146de576f8000058b90de7e4cecfc487503488bb102607f1c5b600160641b831615614700576f800002c5c8678f36cbfce50a6de60b1402607f1c5b600160631b831615614722576f80000162e431db9f80b2347b5d62e51602607f1c5b600160621b831615614744576f800000b1721872d0c7b08cf1e011415202607f1c5b600160611b831615614766576f80000058b90c1aa8a5c3736cb77e8dff02607f1c5b600160601b831615614788576f8000002c5c8605a4635f2efc2362d97802607f1c5b6001605f1b8316156147aa576f800000162e4300e635cf4a109e3939bd02607f1c5b6001605e1b8316156147cc576f8000000b17217ff81bef9c551590cf8302607f1c5b6001605d1b8316156147ee576f800000058b90bfdd4e39cd52c0cfa27c02607f1c5b6001605c1b831615614810576f80000002c5c85fe6f72d669e0e76e41102607f1c5b6001605b1b831615614832576f8000000162e42ff18f9ad35186d0df2802607f1c5b6001605a1b831615614854576f80000000b17217f84cce71aa0dcfffe702607f1c5b600160591b831615614876576f8000000058b90bfc07a77ad56ed22aaa02607f1c5b600160581b831615614898576f800000002c5c85fdfc23cdead40da8d602607f1c5b600160571b8316156148ba576f80000000162e42fefc25eb1571853a6602607f1c5b600160561b8316156148dc576f800000000b17217f7d97f692baacded502607f1c5b600160551b8316156148fe576f80000000058b90bfbead3b8b5dd254d702607f1c5b600160541b831615614920576f8000000002c5c85fdf4eedd62f084e6702607f1c5b600160531b831615614942576f800000000162e42fefa58aef378bf58602607f1c5b600160521b831615614964576f8000000000b17217f7d24a78a3c7ef0202607f1c5b600160511b831615614986576f800000000058b90bfbe9067c93e474a602607f1c5b600160501b8316156149a8576f80000000002c5c85fdf47b8e5a72599f02607f1c5b6001604f1b8316156149ca576f8000000000162e42fefa3bdb315934a202607f1c5b6001604e1b8316156149ec576f80000000000b17217f7d1d7299b49c4602607f1c5b6001604d1b831615614a0e576f8000000000058b90bfbe8e9a8d1c4ea002607f1c5b6001604c1b831615614a30576f800000000002c5c85fdf4745969ea76f02607f1c5b6001604b1b831615614a52576f80000000000162e42fefa3a0df5373bf02607f1c5b6001604a1b831615614a74576f800000000000b17217f7d1cff4aac1e102607f1c5b600160491b831615614a96576f80000000000058b90bfbe8e7db95a2f102607f1c5b600160481b831615614ab8576f8000000000002c5c85fdf473e61ae1f802607f1c5b600160471b831615614ada576f800000000000162e42fefa39f121751c02607f1c5b600160461b831615614afc576f8000000000000b17217f7d1cf815bb9602607f1c5b600160451b831615614b1e576f800000000000058b90bfbe8e7bec1e0d02607f1c5b600160441b831615614b40576f80000000000002c5c85fdf473dee5f1702607f1c5b600160431b831615614b62576f8000000000000162e42fefa39ef5438f02607f1c5b600160421b831615614b84576f80000000000000b17217f7d1cf7a26c802607f1c5b600160411b831615614ba6576f8000000000000058b90bfbe8e7bcf4a402607f1c5b600160401b831615614bc8576f800000000000002c5c85fdf473de72a202607f1c5b607f607984901c811690036001600160801b03161c905091905056fe5969656c644d6174683a20496e73756666696369656e7420667944616920726573657276657345524332303a207472616e7366657220746f20746865207a65726f20616464726573735969656c644d6174683a20526573756c74696e6720667944616920726573657276657320746f6f206869676845524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63653f207773c457c66e004ab34e2ce7ae1fcafc7b4c3286f63997c87428014219155969656c644d6174683a20526f756e64696e6720696e6475636564206572726f725969656c644d6174683a20526573756c74696e672044616920726573657276657320746f6f2068696768536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f2061646472657373506f6f6c3a204f6e6c7920486f6c646572204f722044656c656761746500000045524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735969656c644d6174683a20546f6f206661722066726f6d206d617475726974795969656c644d6174683a20496e73756666696369656e742044616920726573657276657345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220dfcf38324d56249e8a26c32edabb5f6f86fc1ce3ab9e6844ae333018550aedef64736f6c634300060a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000009d7e85d095934471a2788f485a3c765d0a463bd7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001b5969656c6420446169202d20323032312d31322d33312d506f6f6c0000000000000000000000000000000000000000000000000000000000000000000000000c66794461694c5032314465630000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : dai_ (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [1] : fyDai_ (address): 0x9D7e85d095934471a2788F485A3c765d0A463bD7
Arg [2] : name_ (string): Yield Dai - 2021-12-31-Pool
Arg [3] : symbol_ (string): fyDaiLP21Dec
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [1] : 0000000000000000000000009d7e85d095934471a2788f485a3c765d0a463bd7
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000001b
Arg [5] : 5969656c6420446169202d20323032312d31322d33312d506f6f6c0000000000
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [7] : 66794461694c5032314465630000000000000000000000000000000000000000
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.