ETH Price: $2,685.40 (+2.56%)
Gas: 0.88 Gwei

Token

IdleUSDT v3 [Max yield] (idleUSDTYield)
 

Overview

Max Total Supply

595.910641823352731944 idleUSDTYield

Holders

10 (0.00%)

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
Null: 0x000...000
Balance
0 idleUSDTYield

Value
$0.00
0x0000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

IdleUSDT v3 [Max yield] token contract has migrated to a 0xf34842d05a1c888ca02769a633df37177415c2f8

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
IdleTokenV3USDT

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 45000 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-05-17
*/

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

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
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/GSN/Context.sol

pragma solidity ^0.5.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.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view 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/math/SafeMath.sol

pragma solidity ^0.5.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.
     *
     * _Available since v2.4.0._
     */
    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.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        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.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

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

pragma solidity ^0.5.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 {ERC20Mintable}.
 *
 * 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;

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view 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 returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public 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 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 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 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 {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _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 {
        require(account != address(0), "ERC20: mint to the zero address");

        _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 {
        require(account != address(0), "ERC20: burn from the zero address");

        _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 {
        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 Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

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

pragma solidity ^0.5.0;


/**
 * @dev Optional functions from the ERC20 standard.
 */
contract ERC20Detailed is IERC20 {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
     * these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }

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

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

pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard {
    // counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;

    constructor () internal {
        // The counter starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

// File: @openzeppelin/contracts/ownership/Ownable.sol

pragma solidity ^0.5.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

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

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

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

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// File: @openzeppelin/contracts/access/Roles.sol

pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

// File: @openzeppelin/contracts/access/roles/PauserRole.sol

pragma solidity ^0.5.0;



contract PauserRole is Context {
    using Roles for Roles.Role;

    event PauserAdded(address indexed account);
    event PauserRemoved(address indexed account);

    Roles.Role private _pausers;

    constructor () internal {
        _addPauser(_msgSender());
    }

    modifier onlyPauser() {
        require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role");
        _;
    }

    function isPauser(address account) public view returns (bool) {
        return _pausers.has(account);
    }

    function addPauser(address account) public onlyPauser {
        _addPauser(account);
    }

    function renouncePauser() public {
        _removePauser(_msgSender());
    }

    function _addPauser(address account) internal {
        _pausers.add(account);
        emit PauserAdded(account);
    }

    function _removePauser(address account) internal {
        _pausers.remove(account);
        emit PauserRemoved(account);
    }
}

// File: @openzeppelin/contracts/lifecycle/Pausable.sol

pragma solidity ^0.5.0;



/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
contract Pausable is Context, PauserRole {
    /**
     * @dev Emitted when the pause is triggered by a pauser (`account`).
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by a pauser (`account`).
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state. Assigns the Pauser role
     * to the deployer.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!_paused, "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(_paused, "Pausable: not paused");
        _;
    }

    /**
     * @dev Called by a pauser to pause, triggers stopped state.
     */
    function pause() public onlyPauser whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Called by a pauser to unpause, returns to normal state.
     */
    function unpause() public onlyPauser whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

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

pragma solidity ^0.5.5;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing 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.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        // 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 != 0x0 && codehash != accountHash);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    /**
     * @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].
     *
     * _Available since v2.4.0._
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

pragma solidity ^0.5.0;




/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// File: contracts/interfaces/iERC20Fulcrum.sol

pragma solidity 0.5.16;

interface iERC20Fulcrum {
  function mint(
    address receiver,
    uint256 depositAmount)
    external
    returns (uint256 mintAmount);

  function burn(
    address receiver,
    uint256 burnAmount)
    external
    returns (uint256 loanAmountPaid);

  function tokenPrice()
    external
    view
    returns (uint256 price);

  function supplyInterestRate()
    external
    view
    returns (uint256);

  function rateMultiplier()
    external
    view
    returns (uint256);
  function baseRate()
    external
    view
    returns (uint256);

  function borrowInterestRate()
    external
    view
    returns (uint256);

  function avgBorrowInterestRate()
    external
    view
    returns (uint256);

  function protocolInterestRate()
    external
    view
    returns (uint256);

  function spreadMultiplier()
    external
    view
    returns (uint256);

  function totalAssetBorrow()
    external
    view
    returns (uint256);

  function totalAssetSupply()
    external
    view
    returns (uint256);

  function nextSupplyInterestRate(uint256)
    external
    view
    returns (uint256);

  function nextBorrowInterestRate(uint256)
    external
    view
    returns (uint256);
  function nextLoanInterestRate(uint256)
    external
    view
    returns (uint256);
  function totalSupplyInterestRate(uint256)
    external
    view
    returns (uint256);

  function claimLoanToken()
    external
    returns (uint256 claimedAmount);

  function dsr()
    external
    view
    returns (uint256);

  function chaiPrice()
    external
    view
    returns (uint256);
}

// File: contracts/interfaces/ILendingProtocol.sol

pragma solidity 0.5.16;

interface ILendingProtocol {
  function mint() external returns (uint256);
  function redeem(address account) external returns (uint256);
  function nextSupplyRate(uint256 amount) external view returns (uint256);
  function nextSupplyRateWithParams(uint256[] calldata params) external view returns (uint256);
  function getAPR() external view returns (uint256);
  function getPriceInToken() external view returns (uint256);
  function token() external view returns (address);
  function underlying() external view returns (address);
  function availableLiquidity() external view returns (uint256);
}

// File: contracts/interfaces/IIdleTokenV3.sol

/**
 * @title: Idle Token interface
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;

interface IIdleTokenV3 {
  // view
  /**
   * IdleToken price calculation, in underlying
   *
   * @return : price in underlying token
   */
  function tokenPrice() external view returns (uint256 price);

  /**
   * underlying token decimals
   *
   * @return : decimals of underlying token
   */
  function tokenDecimals() external view returns (uint256 decimals);

  /**
   * Get APR of every ILendingProtocol
   *
   * @return addresses: array of token addresses
   * @return aprs: array of aprs (ordered in respect to the `addresses` array)
   */
  function getAPRs() external view returns (address[] memory addresses, uint256[] memory aprs);

  // external
  // We should save the amount one has deposited to calc interests

  /**
   * Used to mint IdleTokens, given an underlying amount (eg. DAI).
   * This method triggers a rebalance of the pools if needed
   * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken
   * NOTE 2: this method can be paused
   *
   * @param _amount : amount of underlying token to be lended
   * @param : pass []
   * @return mintedTokens : amount of IdleTokens minted
   */
  function mintIdleToken(uint256 _amount, uint256[] calldata) external returns (uint256 mintedTokens);

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * This method triggers a rebalance of the pools if needed
   * NOTE: If the contract is paused or iToken price has decreased one can still redeem but no rebalance happens.
   * NOTE 2: If iToken price has decresed one should not redeem (but can do it) otherwise he would capitalize the loss.
   *         Ideally one should wait until the black swan event is terminated
   *
   * @param _amount : amount of IdleTokens to be burned
   * @param : pass []
   * @return redeemedTokens : amount of underlying tokens redeemed
   */
  function redeemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata)
    external returns (uint256 redeemedTokens);

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * and send interest-bearing tokens (eg. cDAI/iDAI) directly to the user.
   * Underlying (eg. DAI) is not redeemed here.
   *
   * @param _amount : amount of IdleTokens to be burned
   */
  function redeemInterestBearingTokens(uint256 _amount) external;

  /**
   * @param _newAmount : amount of underlying tokens that needs to be minted with this rebalance
   * @param : pass []
   * @return : whether has rebalanced or not
   */
  function rebalance(uint256 _newAmount, uint256[] calldata) external returns (bool);

  /**
   * @return : whether has rebalanced or not
   */
  function rebalance() external returns (bool);
}

// File: contracts/interfaces/USDT.sol

pragma solidity 0.5.16;

interface USDT {
  function basisPointsRate() external returns (uint256);
}

// File: contracts/interfaces/IIdleRebalancerV3.sol

/**
 * @title: Idle Rebalancer interface
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;

interface IIdleRebalancerV3 {
  function getAllocations() external view returns (uint256[] memory _allocations);
}

// File: contracts/IdleRebalancerV3.sol

/**
 * @title: Idle Rebalancer contract
 * @summary: Used for calculating amounts to lend on each implemented protocol.
 *           This implementation works with Compound and Fulcrum only,
 *           when a new protocol will be added this should be replaced
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;




contract IdleRebalancerV3 is IIdleRebalancerV3, Ownable {
  using SafeMath for uint256;
  uint256[] public lastAmounts;
  address[] public lastAmountsAddresses;
  address public rebalancerManager;
  address public idleToken;

  /**
   * @param _cToken : cToken address
   * @param _iToken : iToken address
   * @param _aToken : aToken address
   * @param _yxToken : yxToken address
   * @param _rebalancerManager : rebalancerManager address
   */
  constructor(address _cToken, address _iToken, address _aToken, address _yxToken, address _rebalancerManager) public {
    require(_cToken != address(0) && _iToken != address(0) && _aToken != address(0) && _yxToken != address(0) && _rebalancerManager != address(0), 'some addr is 0');
    rebalancerManager = _rebalancerManager;

    // Initially 100% on first lending protocol
    lastAmounts = [100000, 0, 0, 0];
    lastAmountsAddresses = [_cToken, _iToken, _aToken, _yxToken];
  }

  /**
   * Throws if called by any account other than rebalancerManager.
   */
  modifier onlyRebalancerAndIdle() {
    require(msg.sender == rebalancerManager || msg.sender == idleToken, "Only rebalacer and IdleToken");
    _;
  }

  /**
   * It allows owner to set the allowed rebalancer address
   *
   * @param _rebalancerManager : rebalance manager address
   */
  function setRebalancerManager(address _rebalancerManager)
    external onlyOwner {
      require(_rebalancerManager != address(0), "_rebalancerManager addr is 0");

      rebalancerManager = _rebalancerManager;
  }

  function setIdleToken(address _idleToken)
    external onlyOwner {
      require(idleToken == address(0), "idleToken addr already set");
      require(_idleToken != address(0), "_idleToken addr is 0");
      idleToken = _idleToken;
  }

  /**
   * It adds a new token address to lastAmountsAddresses list
   *
   * @param _newToken : new interest bearing token address
   */
  function setNewToken(address _newToken)
    external onlyOwner {
      require(_newToken != address(0), "New token should be != 0");
      for (uint256 i = 0; i < lastAmountsAddresses.length; i++) {
        if (lastAmountsAddresses[i] == _newToken) {
          return;
        }
      }

      lastAmountsAddresses.push(_newToken);
      lastAmounts.push(0);
  }
  // end onlyOwner

  /**
   * Used by Rebalance manager to set the new allocations
   *
   * @param _allocations : array with allocations in percentages (100% => 100000)
   * @param _addresses : array with addresses of tokens used, should be equal to lastAmountsAddresses
   */
  function setAllocations(uint256[] calldata _allocations, address[] calldata _addresses)
    external onlyRebalancerAndIdle
  {
    require(_allocations.length == lastAmounts.length, "Alloc lengths are different, allocations");
    require(_allocations.length == _addresses.length, "Alloc lengths are different, addresses");

    uint256 total;
    for (uint256 i = 0; i < _allocations.length; i++) {
      require(_addresses[i] == lastAmountsAddresses[i], "Addresses do not match");
      total = total.add(_allocations[i]);
      lastAmounts[i] = _allocations[i];
    }
    require(total == 100000, "Not allocating 100%");
  }

  function getAllocations()
    external view returns (uint256[] memory _allocations) {
    return lastAmounts;
  }

  function getAllocationsLength()
    external view returns (uint256) {
    return lastAmounts.length;
  }
}

// File: contracts/interfaces/IIdleToken.sol

/**
 * @title: Idle Token interface
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;

interface IIdleToken {
  // view
  /**
   * IdleToken price calculation, in underlying
   *
   * @return : price in underlying token
   */
  function tokenPrice() external view returns (uint256 price);

  /**
   * underlying token decimals
   *
   * @return : decimals of underlying token
   */
  function tokenDecimals() external view returns (uint256 decimals);

  /**
   * Get APR of every ILendingProtocol
   *
   * @return addresses: array of token addresses
   * @return aprs: array of aprs (ordered in respect to the `addresses` array)
   */
  function getAPRs() external view returns (address[] memory addresses, uint256[] memory aprs);

  // external
  // We should save the amount one has deposited to calc interests

  /**
   * Used to mint IdleTokens, given an underlying amount (eg. DAI).
   * This method triggers a rebalance of the pools if needed
   * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken
   * NOTE 2: this method can be paused
   *
   * @param _amount : amount of underlying token to be lended
   * @param _clientProtocolAmounts : client side calculated amounts to put on each lending protocol
   * @return mintedTokens : amount of IdleTokens minted
   */
  function mintIdleToken(uint256 _amount, uint256[] calldata _clientProtocolAmounts) external returns (uint256 mintedTokens);

  /**
   * @param _amount : amount of underlying token to be lended
   * @return : address[] array with all token addresses used,
   *                          eg [cTokenAddress, iTokenAddress]
   * @return : uint256[] array with all amounts for each protocol in order,
   *                   eg [amountCompound, amountFulcrum]
   */
  function getParamsForMintIdleToken(uint256 _amount) external returns (address[] memory, uint256[] memory);

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * This method triggers a rebalance of the pools if needed
   * NOTE: If the contract is paused or iToken price has decreased one can still redeem but no rebalance happens.
   * NOTE 2: If iToken price has decresed one should not redeem (but can do it) otherwise he would capitalize the loss.
   *         Ideally one should wait until the black swan event is terminated
   *
   * @param _amount : amount of IdleTokens to be burned
   * @param _clientProtocolAmounts : client side calculated amounts to put on each lending protocol
   * @return redeemedTokens : amount of underlying tokens redeemed
   */
  function redeemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata _clientProtocolAmounts)
    external returns (uint256 redeemedTokens);

  /**
   * @param _amount : amount of IdleTokens to be burned
   * @param _skipRebalance : whether to skip the rebalance process or not
   * @return : address[] array with all token addresses used,
   *                          eg [cTokenAddress, iTokenAddress]
   * @return : uint256[] array with all amounts for each protocol in order,
   *                   eg [amountCompound, amountFulcrum]
   */
  function getParamsForRedeemIdleToken(uint256 _amount, bool _skipRebalance)
    external returns (address[] memory, uint256[] memory);

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * and send interest-bearing tokens (eg. cDAI/iDAI) directly to the user.
   * Underlying (eg. DAI) is not redeemed here.
   *
   * @param _amount : amount of IdleTokens to be burned
   */
  function redeemInterestBearingTokens(uint256 _amount) external;

  /**
   * @param _clientProtocolAmounts : client side calculated amounts to put on each lending protocol
   * @return claimedTokens : amount of underlying tokens claimed
   */
  function claimITokens(uint256[] calldata _clientProtocolAmounts) external returns (uint256 claimedTokens);

  /**
   * @param _newAmount : amount of underlying tokens that needs to be minted with this rebalance
   * @param _clientProtocolAmounts : client side calculated amounts to put on each lending protocol
   * @return : whether has rebalanced or not
   */
  function rebalance(uint256 _newAmount, uint256[] calldata _clientProtocolAmounts) external returns (bool);

  /**
   * @param _newAmount : amount of underlying tokens that needs to be minted with this rebalance
   * @return : address[] array with all token addresses used,
   *                          eg [cTokenAddress, iTokenAddress]
   * @return : uint256[] array with all amounts for each protocol in order,
   *                   eg [amountCompound, amountFulcrum]
   */
  function getParamsForRebalance(uint256 _newAmount) external returns (address[] memory, uint256[] memory);
}

// File: contracts/IdlePriceCalculator.sol

/**
 * @title: Idle Price Calculator contract
 * @summary: Used for calculating the current IdleToken price in underlying (eg. DAI)
 *          price is: Net Asset Value / totalSupply
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;






contract IdlePriceCalculator {
  using SafeMath for uint256;
  /**
   * IdleToken price calculation, in underlying (eg. DAI)
   *
   * @return : price in underlying token
   */
  function tokenPrice(
    uint256 totalSupply,
    address idleToken,
    address[] calldata currentTokensUsed,
    address[] calldata protocolWrappersAddresses
  )
    external view
    returns (uint256 price) {
      require(currentTokensUsed.length == protocolWrappersAddresses.length, "Different Length");

      if (totalSupply == 0) {
        return 10**(IIdleToken(idleToken).tokenDecimals());
      }

      uint256 currPrice;
      uint256 currNav;
      uint256 totNav;

      for (uint256 i = 0; i < currentTokensUsed.length; i++) {
        currPrice = ILendingProtocol(protocolWrappersAddresses[i]).getPriceInToken();
        // NAV = price * poolSupply
        currNav = currPrice.mul(IERC20(currentTokensUsed[i]).balanceOf(idleToken));
        totNav = totNav.add(currNav);
      }

      price = totNav.div(totalSupply); // idleToken price in token wei
  }
}

// File: contracts/interfaces/GasToken.sol

pragma solidity 0.5.16;

interface GasToken {
  function freeUpTo(uint256 value) external returns (uint256 freed);
  function freeFromUpTo(address from, uint256 value) external returns (uint256 freed);
  function balanceOf(address from) external returns (uint256 balance);
}

// File: contracts/GST2Consumer.sol

pragma solidity 0.5.16;


contract GST2Consumer {
  GasToken public constant gst2 = GasToken(0x0000000000b3F879cb30FE243b4Dfee438691c04);
  uint256[] internal gasAmounts = [14154, 41130, 27710, 7020];

  modifier gasDiscountFrom(address from) {
    uint256 initialGasLeft = gasleft();
    _;
    _makeGasDiscount(initialGasLeft - gasleft(), from);
  }

  function _makeGasDiscount(uint256 gasSpent, address from) internal {
    // For more info https://gastoken.io/
    // 14154 -> FREE_BASE -> base cost of freeing
    // 41130 -> 2 * REIMBURSE - FREE_TOKEN -> 2 * 24000 - 6870
    uint256 tokens = (gasSpent + gasAmounts[0]) / gasAmounts[1];
    uint256 safeNumTokens;
    uint256 gas = gasleft();

    // For more info https://github.com/projectchicago/gastoken/blob/master/contract/gst2_free_example.sol
    if (gas >= gasAmounts[2]) {
      safeNumTokens = (gas - gasAmounts[2]) / gasAmounts[3];
    }

    if (tokens > safeNumTokens) {
      tokens = safeNumTokens;
    }

    if (tokens > 0) {
      if (from == address(this)) {
        gst2.freeUpTo(tokens);
      } else {
        gst2.freeFromUpTo(from, tokens);
      }
    }
  }
}

// File: contracts/IdleTokenV3USDT.sol

/**
 * @title: Idle Token (V3) main contract
 * @summary: ERC20 that holds pooled user funds together
 *           Each token rapresent a share of the underlying pools
 *           and with each token user have the right to redeem a portion of these pools
 * @author: Idle Labs Inc., idle.finance
 */
pragma solidity 0.5.16;
















contract IdleTokenV3USDT is ERC20, ERC20Detailed, ReentrancyGuard, Ownable, Pausable, IIdleTokenV3, GST2Consumer {
  using SafeERC20 for IERC20;
  using SafeMath for uint256;

  // eg. cTokenAddress => IdleCompoundAddress
  mapping(address => address) public protocolWrappers;
  // eg. DAI address
  address public token;
  // eg. iDAI address
  address public iToken; // used for claimITokens and userClaimITokens
  // Idle rebalancer current implementation address
  address public rebalancer;
  // Idle price calculator current implementation address
  address public priceCalculator;
  // Address collecting underlying fees
  address public feeAddress;
  // Last iToken price, used to pause contract in case of a black swan event
  uint256 public lastITokenPrice;
  // eg. 18 for DAI
  uint256 public tokenDecimals;
  // Max possible fee on interest gained
  uint256 constant MAX_FEE = 10000; // 100000 == 100% -> 10000 == 10%
  // Min delay for adding a new protocol
  uint256 constant NEW_PROTOCOL_DELAY = 60 * 60 * 24 * 3; // 3 days in seconds
  // Current fee on interest gained
  uint256 public fee;
  // Manual trigger for unpausing contract in case of a black swan event that caused the iToken price to not
  // return to the normal level
  bool public manualPlay;
  // Flag for disabling openRebalance for the risk adjusted variant
  bool public isRiskAdjusted;
  // Flag for disabling instant new protocols additions
  bool public isNewProtocolDelayed;
  // eg. [cTokenAddress, iTokenAddress, ...]
  address[] public allAvailableTokens;
  // eg. [5000, 0, 5000, 0] for 50% in compound, 0% fulcrum, 50% aave, 0 dydx. same order of allAvailableTokens
  uint256[] public lastAllocations;
  // Map that saves avg idleToken price paid for each user
  mapping(address => uint256) public userAvgPrices;
  // Map that saves amount with no fee for each user
  mapping(address => uint256) private userNoFeeQty;
  // timestamp when new protocol wrapper has been queued for change
  // protocol_wrapper_address -> timestamp
  mapping(address => uint256) public releaseTimes;

  /**
   * @dev constructor, initialize some variables, mainly addresses of other contracts
   *
   * @param _name : IdleToken name
   * @param _symbol : IdleToken symbol
   * @param _decimals : IdleToken decimals
   * @param _token : underlying token address
   * @param _cToken : cToken address
   * @param _iToken : iToken address
   * @param _rebalancer : Idle Rebalancer address
   * @param _idleCompound : Idle Compound address
   * @param _idleFulcrum : Idle Fulcrum address
   */
  constructor(
    string memory _name, // eg. IdleDAI
    string memory _symbol, // eg. IDLEDAI
    uint8 _decimals, // eg. 18
    address _token,
    address _cToken,
    address _iToken,
    address _rebalancer,
    address _priceCalculator,
    address _idleCompound,
    address _idleFulcrum)
    public
    ERC20Detailed(_name, _symbol, _decimals) {
      token = _token;
      tokenDecimals = ERC20Detailed(_token).decimals();
      iToken = _iToken;
      rebalancer = _rebalancer;
      priceCalculator = _priceCalculator;
      protocolWrappers[_cToken] = _idleCompound;
      protocolWrappers[_iToken] = _idleFulcrum;
      allAvailableTokens = [_cToken, _iToken];
  }

  // During a black swan event is possible that iToken price decreases instead of increasing,
  // with the consequence of lowering the IdleToken price. To mitigate this we implemented a
  // check on the iToken price that prevents users from minting cheap IdleTokens or rebalancing
  // the pool in this specific case. The redeemIdleToken won't be paused but the rebalance process
  // won't be triggered in this case.
  modifier whenITokenPriceHasNotDecreased() {
    uint256 iTokenPrice = iERC20Fulcrum(iToken).tokenPrice();
    require(
      iTokenPrice >= lastITokenPrice || manualPlay,
      "Paused: iToken price decreased"
    );

    _;

    if (iTokenPrice > lastITokenPrice) {
      lastITokenPrice = iTokenPrice;
    }
  }
  modifier whenUSDThasNoFee() {
    require(
      USDT(token).basisPointsRate() == 0 || manualPlay,
      "Paused: USDT introduced fee"
    );

    _;
  }

  // onlyOwner
  /**
   * It allows owner to set the IdleRebalancerV3 address
   *
   * @param _rebalancer : new IdleRebalancerV3 address
   */
  function setRebalancer(address _rebalancer)
    external onlyOwner {
      require(_rebalancer != address(0), 'Addr is 0');
      rebalancer = _rebalancer;
  }
  /**
   * It allows owner to set the IdlePriceCalculator address
   *
   * @param _priceCalculator : new IdlePriceCalculator address
   */
  function setPriceCalculator(address _priceCalculator)
    external onlyOwner {
      require(_priceCalculator != address(0), 'Addr is 0');
      if (!isNewProtocolDelayed || (releaseTimes[_priceCalculator] != 0 && now - releaseTimes[_priceCalculator] > NEW_PROTOCOL_DELAY)) {
        priceCalculator = _priceCalculator;
        releaseTimes[_priceCalculator] = 0;
        return;
      }
      releaseTimes[_priceCalculator] = now;
  }

  /**
   * It allows owner to set a protocol wrapper address
   *
   * @param _token : underlying token address (eg. DAI)
   * @param _wrapper : Idle protocol wrapper address
   */
  function setProtocolWrapper(address _token, address _wrapper)
    external onlyOwner {
      require(_token != address(0) && _wrapper != address(0), 'some addr is 0');

      if (!isNewProtocolDelayed || (releaseTimes[_wrapper] != 0 && now - releaseTimes[_wrapper] > NEW_PROTOCOL_DELAY)) {
        // update allAvailableTokens if needed
        if (protocolWrappers[_token] == address(0)) {
          allAvailableTokens.push(_token);
        }
        protocolWrappers[_token] = _wrapper;
        releaseTimes[_wrapper] = 0;
        return;
      }

      releaseTimes[_wrapper] = now;
  }

  /**
   * It allows owner to unpause the contract when iToken price decreased and didn't return to the expected level
   *
   * @param _manualPlay : flag
   */
  function setManualPlay(bool _manualPlay)
    external onlyOwner {
      manualPlay = _manualPlay;
  }

  /**
   * It allows owner to disable openRebalance
   *
   * @param _isRiskAdjusted : flag
   */
  function setIsRiskAdjusted(bool _isRiskAdjusted)
    external onlyOwner {
      isRiskAdjusted = _isRiskAdjusted;
  }

  /**
   * It permanently disable instant new protocols additions
   */
  function delayNewProtocols()
    external onlyOwner {
      isNewProtocolDelayed = true;
  }

  /**
   * It allows owner to set the fee (1000 == 10% of gained interest)
   *
   * @param _fee : fee amount where 100000 is 100%, max settable is MAX_FEE constant
   */
  function setFee(uint256 _fee)
    external onlyOwner {
      require(_fee <= MAX_FEE, "Fee too high");
      fee = _fee;
  }

  /**
   * It allows owner to set the fee address
   *
   * @param _feeAddress : fee address
   */
  function setFeeAddress(address _feeAddress)
    external onlyOwner {
      require(_feeAddress != address(0), 'Addr is 0');
      feeAddress = _feeAddress;
  }

  /**
   * It allows owner to set gas parameters
   *
   * @param _amounts : Gas tokens params
   */
  function setGasParams(uint256[] calldata _amounts)
    external onlyOwner {
      gasAmounts = _amounts;
  }
  // view
  /**
   * IdleToken price calculation, in underlying
   *
   * @return : price in underlying token
   */
  function tokenPrice()
    public view
    returns (uint256 price) {
      address[] memory protocolWrappersAddresses = new address[](allAvailableTokens.length);
      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        protocolWrappersAddresses[i] = protocolWrappers[allAvailableTokens[i]];
      }
      price = IdlePriceCalculator(priceCalculator).tokenPrice(
        totalSupply(), address(this), allAvailableTokens, protocolWrappersAddresses
      );
  }

  /**
   * Get APR of every ILendingProtocol
   *
   * @return addresses: array of token addresses
   * @return aprs: array of aprs (ordered in respect to the `addresses` array)
   */
  function getAPRs()
    external view
    returns (address[] memory addresses, uint256[] memory aprs) {
      address currToken;
      addresses = new address[](allAvailableTokens.length);
      aprs = new uint256[](allAvailableTokens.length);
      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        currToken = allAvailableTokens[i];
        addresses[i] = currToken;
        aprs[i] = ILendingProtocol(protocolWrappers[currToken]).getAPR();
      }
  }

  /**
   * Get current avg APR of this IdleToken
   *
   * @return avgApr: current weighted avg apr
   */
  function getAvgAPR()
    public view
    returns (uint256 avgApr) {
      (, uint256[] memory amounts, uint256 total) = _getCurrentAllocations();
      uint256 currApr;
      uint256 weight;
      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        if (amounts[i] == 0) {
          continue;
        }
        currApr = ILendingProtocol(protocolWrappers[allAvailableTokens[i]]).getAPR();
        weight = amounts[i].mul(10**18).div(total);
        avgApr = avgApr.add(currApr.mul(weight).div(10**18));
      }
  }

  // ##### ERC20 modified transfer and transferFrom that also update the avgPrice paid for the recipient
  function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
    _transfer(sender, recipient, amount);
    _approve(sender, msg.sender, allowance(sender, msg.sender).sub(amount, "ERC20: transfer amount exceeds allowance"));
    _updateAvgPrice(recipient, amount, userAvgPrices[sender]);
    return true;
  }
  function transfer(address recipient, uint256 amount) public returns (bool) {
    _transfer(msg.sender, recipient, amount);
    _updateAvgPrice(recipient, amount, userAvgPrices[msg.sender]);
    return true;
  }
  // #####

  // external
  /**
   * Used to mint IdleTokens, given an underlying amount (eg. DAI).
   * This method triggers a rebalance of the pools if needed and if _skipWholeRebalance is false
   * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken
   * NOTE 2: this method can be paused
   * This method use GasTokens of this contract (if present) to get a gas discount
   *
   * @param _amount : amount of underlying token to be lended
   * @param _skipWholeRebalance : flag to choose whter to do a full rebalance or not
   * @return mintedTokens : amount of IdleTokens minted
   */
  function mintIdleToken(uint256 _amount, bool _skipWholeRebalance)
    external nonReentrant gasDiscountFrom(address(this))
    returns (uint256 mintedTokens) {
    return _mintIdleToken(_amount, new uint256[](0), _skipWholeRebalance);
  }

  /**
   * DEPRECATED: Used to mint IdleTokens, given an underlying amount (eg. DAI).
   * Keep for backward compatibility with IdleV2
   *
   * @param _amount : amount of underlying token to be lended
   * @param : not used, pass empty array
   * @return mintedTokens : amount of IdleTokens minted
   */
  function mintIdleToken(uint256 _amount, uint256[] calldata)
    external nonReentrant gasDiscountFrom(address(this))
    returns (uint256 mintedTokens) {
    return _mintIdleToken(_amount, new uint256[](0), false);
  }

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * This method triggers a rebalance of the pools if needed
   * NOTE: If the contract is paused or iToken price has decreased one can still redeem but no rebalance happens.
   * NOTE 2: If iToken price has decresed one should not redeem (but can do it) otherwise he would capitalize the loss.
   *         Ideally one should wait until the black swan event is terminated
   *
   * @param _amount : amount of IdleTokens to be burned
   * @param _skipRebalance : whether to skip the rebalance process or not
   * @param : not used
   * @return redeemedTokens : amount of underlying tokens redeemed
   */
  function redeemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata)
    external nonReentrant
    returns (uint256 redeemedTokens) {
      uint256 balance;
      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        balance = IERC20(allAvailableTokens[i]).balanceOf(address(this));
        if (balance == 0) {
          continue;
        }
        redeemedTokens = redeemedTokens.add(
          _redeemProtocolTokens(
            protocolWrappers[allAvailableTokens[i]],
            allAvailableTokens[i],
            // _amount * protocolPoolBalance / idleSupply
            _amount.mul(balance).div(totalSupply()), // amount to redeem
            address(this)
          )
        );
      }

      _burn(msg.sender, _amount);
      if (fee > 0 && feeAddress != address(0)) {
        redeemedTokens = _getFee(_amount, redeemedTokens);
      }
      // send underlying minus fee to msg.sender
      IERC20(token).safeTransfer(msg.sender, redeemedTokens);

      if (this.paused() || iERC20Fulcrum(iToken).tokenPrice() < lastITokenPrice || _skipRebalance) {
        return redeemedTokens;
      }

      _rebalance(0, false);
  }

  /**
   * Here we calc the pool share one can withdraw given the amount of IdleToken they want to burn
   * and send interest-bearing tokens (eg. cDAI/iDAI) directly to the user.
   * Underlying (eg. DAI) is not redeemed here.
   *
   * @param _amount : amount of IdleTokens to be burned
   */
  function redeemInterestBearingTokens(uint256 _amount)
    external nonReentrant {
      uint256 idleSupply = totalSupply();
      address currentToken;
      uint256 balance;

      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        currentToken = allAvailableTokens[i];
        balance = IERC20(currentToken).balanceOf(address(this));
        if (balance == 0) {
          continue;
        }
        IERC20(currentToken).safeTransfer(
          msg.sender,
          _amount.mul(balance).div(idleSupply) // amount to redeem
        );
      }

      _burn(msg.sender, _amount);
  }

  /**
   * Allow any users to set new allocations as long as the new allocations
   * give a better avg APR than before
   * Allocations should be in the format [100000, 0, 0, 0, ...] where length is the same
   * as lastAllocations variable and the sum of all value should be == 100000
   *
   * This method is not callble if this instance of IdleToken is a risk adjusted instance
   * NOTE: this method can be paused
   *
   * @param _newAllocations : array with new allocations in percentage
   * @return : whether has rebalanced or not
   * @return avgApr : the new avg apr after rebalance
   */
  function openRebalance(uint256[] calldata _newAllocations)
    external whenNotPaused whenITokenPriceHasNotDecreased whenUSDThasNoFee
    returns (bool, uint256 avgApr) {
      require(!isRiskAdjusted, "Setting allocations not allowed");
      uint256 initialAPR = getAvgAPR();
      // Validate and update rebalancer allocations
      IdleRebalancerV3(rebalancer).setAllocations(_newAllocations, allAvailableTokens);
      bool hasRebalanced = _rebalance(0, false);
      uint256 newAprAfterRebalance = getAvgAPR();
      require(newAprAfterRebalance > initialAPR, "APR not improved");
      return (hasRebalanced, newAprAfterRebalance);
  }

  /**
   * Dynamic allocate all the pool across different lending protocols if needed, use gas refund from gasToken
   *
   * NOTE: this method can be paused.
   * msg.sender should approve this contract to spend GST2 tokens before calling
   * this method
   *
   * @return : whether has rebalanced or not
   */
  function rebalanceWithGST()
    external gasDiscountFrom(msg.sender)
    returns (bool) {
      return _rebalance(0, false);
  }

  /**
   * DEPRECATED: Dynamic allocate all the pool across different lending protocols if needed,
   * Keep for backward compatibility with IdleV2
   *
   * NOTE: this method can be paused
   *
   * @param : not used
   * @param : not used
   * @return : whether has rebalanced or not
   */
  function rebalance(uint256, uint256[] calldata)
    external returns (bool) {
    return _rebalance(0, false);
  }

  /**
   * Dynamic allocate all the pool across different lending protocols if needed,
   * rebalance without params
   *
   * NOTE: this method can be paused
   *
   * @return : whether has rebalanced or not
   */
  function rebalance() external returns (bool) {
    return _rebalance(0, false);
  }

  /**
   * Get the contract balance of every protocol currently used
   *
   * @return tokenAddresses : array with all token addresses used,
   *                          eg [cTokenAddress, iTokenAddress]
   * @return amounts : array with all amounts for each protocol in order,
   *                   eg [amountCompoundInUnderlying, amountFulcrumInUnderlying]
   * @return total : total AUM in underlying
   */
  function getCurrentAllocations() external view
    returns (address[] memory tokenAddresses, uint256[] memory amounts, uint256 total) {
    return _getCurrentAllocations();
  }

  // internal
  /**
   * Used to mint IdleTokens, given an underlying amount (eg. DAI).
   * This method triggers a rebalance of the pools if needed
   * NOTE: User should 'approve' _amount of tokens before calling mintIdleToken
   * NOTE 2: this method can be paused
   * This method use GasTokens of this contract (if present) to get a gas discount
   *
   * @param _amount : amount of underlying token to be lended
   * @param : not used
   * @param _skipWholeRebalance : flag to decide if doing a simple mint or mint + rebalance
   * @return mintedTokens : amount of IdleTokens minted
   */
  function _mintIdleToken(uint256 _amount, uint256[] memory, bool _skipWholeRebalance)
    internal whenNotPaused whenITokenPriceHasNotDecreased whenUSDThasNoFee
    returns (uint256 mintedTokens) {
      // Get current IdleToken price
      uint256 idlePrice = tokenPrice();
      // transfer tokens to this contract
      IERC20(token).safeTransferFrom(msg.sender, address(this), _amount);

      // Rebalance the current pool if needed and mint new supplied amount
      _rebalance(0, _skipWholeRebalance);

      mintedTokens = _amount.mul(10**18).div(idlePrice);
      _mint(msg.sender, mintedTokens);

      _updateAvgPrice(msg.sender, mintedTokens, idlePrice);
  }

  /**
   * Dynamic allocate all the pool across different lending protocols if needed
   *
   * NOTE: this method can be paused
   *
   * @param : not used
   * @return : whether has rebalanced or not
   */
  function _rebalance(uint256, bool _skipWholeRebalance)
    internal whenNotPaused whenITokenPriceHasNotDecreased whenUSDThasNoFee
    returns (bool) {
      // check if we need to rebalance by looking at the allocations in rebalancer contract
      uint256[] memory rebalancerLastAllocations = IdleRebalancerV3(rebalancer).getAllocations();
      bool areAllocationsEqual = rebalancerLastAllocations.length == lastAllocations.length;
      if (areAllocationsEqual) {
        for (uint256 i = 0; i < lastAllocations.length || !areAllocationsEqual; i++) {
          if (lastAllocations[i] != rebalancerLastAllocations[i]) {
            areAllocationsEqual = false;
            break;
          }
        }
      }
      uint256 balance = IERC20(token).balanceOf(address(this));
      if (areAllocationsEqual && balance == 0) {
        return false;
      }

      if (balance > 0) {
        if (lastAllocations.length == 0 && _skipWholeRebalance) {
          // set in storage
          lastAllocations = rebalancerLastAllocations;
        }
        _mintWithAmounts(allAvailableTokens, _amountsFromAllocations(rebalancerLastAllocations, balance));
      }

      if (_skipWholeRebalance || areAllocationsEqual) {
        return false;
      }

      // Instead of redeeming everything during rebalance we redeem and mint only what needs
      // to be reallocated
      // get current allocations in underlying
      (address[] memory tokenAddresses, uint256[] memory amounts, uint256 totalInUnderlying) = _getCurrentAllocations();
      // calculate new allocations given the total
      uint256[] memory newAmounts = _amountsFromAllocations(rebalancerLastAllocations, totalInUnderlying);
      (uint256[] memory toMintAllocations, uint256 totalToMint, bool lowLiquidity) = _redeemAllNeeded(tokenAddresses, amounts, newAmounts);

      // if some protocol has liquidity that we should redeem, we do not update
      // lastAllocations to force another rebalance next time
      if (!lowLiquidity) {
        // Update lastAllocations with rebalancerLastAllocations
        delete lastAllocations;
        lastAllocations = rebalancerLastAllocations;
      }
      uint256 totalRedeemd = IERC20(token).balanceOf(address(this));
      if (totalRedeemd > 1 && totalToMint > 1) {
        // Do not mint directly using toMintAllocations check with totalRedeemd
        uint256[] memory tempAllocations = new uint256[](toMintAllocations.length);
        for (uint256 i = 0; i < toMintAllocations.length; i++) {
          // Calc what would have been the correct allocations percentage if all was available
          tempAllocations[i] = toMintAllocations[i].mul(100000).div(totalToMint);
        }

        uint256[] memory partialAmounts = _amountsFromAllocations(tempAllocations, totalRedeemd);
        _mintWithAmounts(allAvailableTokens, partialAmounts);
      }

      return true; // hasRebalanced
  }

  /**
   * Update avg price paid for each idle token of a user
   *
   * @param usr : user that should have balance update
   * @param qty : new amount deposited / transferred, in idleToken
   * @param price : curr idleToken price in underlying
   */
  function _updateAvgPrice(address usr, uint256 qty, uint256 price) internal {
    if (fee == 0) {
      userNoFeeQty[usr] = userNoFeeQty[usr].add(qty);
      return;
    }

    uint256 totBalance = balanceOf(usr).sub(userNoFeeQty[usr]);
    uint256 oldAvgPrice = userAvgPrices[usr];
    uint256 oldBalance = totBalance.sub(qty);
    userAvgPrices[usr] = oldAvgPrice.mul(oldBalance).div(totBalance).add(price.mul(qty).div(totBalance));
  }

  /**
   * Calculate fee and send them to feeAddress
   *
   * @param amount : in idleTokens
   * @param redeemed : in underlying
   * @return : net value in underlying
   */
  function _getFee(uint256 amount, uint256 redeemed) internal returns (uint256) {
    uint256 noFeeQty = userNoFeeQty[msg.sender];
    uint256 currPrice = tokenPrice();
    if (noFeeQty > 0 && noFeeQty > amount) {
      noFeeQty = amount;
    }

    uint256 totalValPaid = noFeeQty.mul(currPrice).add(amount.sub(noFeeQty).mul(userAvgPrices[msg.sender])).div(10**18);
    uint256 currVal = amount.mul(currPrice).div(10**18);
    if (currVal < totalValPaid) {
      return redeemed;
    }
    uint256 gain = currVal.sub(totalValPaid);
    uint256 feeDue = gain.mul(fee).div(100000);
    IERC20(token).safeTransfer(feeAddress, feeDue);
    userNoFeeQty[msg.sender] = userNoFeeQty[msg.sender].sub(noFeeQty);
    return currVal.sub(feeDue);
  }

  /**
   * Mint specific amounts of protocols tokens
   *
   * @param tokenAddresses : array of protocol tokens
   * @param protocolAmounts : array of amounts to be minted
   * @return : net value in underlying
   */
  function _mintWithAmounts(address[] memory tokenAddresses, uint256[] memory protocolAmounts) internal {
    // mint for each protocol and update currentTokensUsed
    require(tokenAddresses.length == protocolAmounts.length, "All tokens length != allocations length");

    uint256 currAmount;

    for (uint256 i = 0; i < protocolAmounts.length; i++) {
      currAmount = protocolAmounts[i];
      if (currAmount == 0) {
        continue;
      }
      _mintProtocolTokens(protocolWrappers[tokenAddresses[i]], currAmount);
    }
  }

  /**
   * Calculate amounts from percentage allocations (100000 => 100%)
   *
   * @param allocations : array of protocol allocations in percentage
   * @param total : total amount
   * @return : array with amounts
   */
  function _amountsFromAllocations(uint256[] memory allocations, uint256 total)
    internal pure returns (uint256[] memory) {
    uint256[] memory newAmounts = new uint256[](allocations.length);
    uint256 currBalance = 0;
    uint256 allocatedBalance = 0;

    for (uint256 i = 0; i < allocations.length; i++) {
      if (i == allocations.length - 1) {
        newAmounts[i] = total.sub(allocatedBalance);
      } else {
        currBalance = total.mul(allocations[i]).div(100000);
        allocatedBalance = allocatedBalance.add(currBalance);
        newAmounts[i] = currBalance;
      }
    }
    return newAmounts;
  }

  /**
   * Redeem all underlying needed from each protocol
   *
   * @param tokenAddresses : array of protocol tokens addresses
   * @param amounts : array with current allocations in underlying
   * @param newAmounts : array with new allocations in underlying
   * @return toMintAllocations : array with amounts to be minted
   * @return totalToMint : total amount that needs to be minted
   */
  function _redeemAllNeeded(
    address[] memory tokenAddresses,
    uint256[] memory amounts,
    uint256[] memory newAmounts
    ) internal returns (
      uint256[] memory toMintAllocations,
      uint256 totalToMint,
      bool lowLiquidity
    ) {
    require(amounts.length == newAmounts.length, 'Lengths not equal');
    toMintAllocations = new uint256[](amounts.length);
    ILendingProtocol protocol;
    uint256 currAmount;
    uint256 newAmount;
    address currToken;
    // check the difference between amounts and newAmounts
    for (uint256 i = 0; i < amounts.length; i++) {
      currToken = tokenAddresses[i];
      newAmount = newAmounts[i];
      currAmount = amounts[i];
      protocol = ILendingProtocol(protocolWrappers[currToken]);
      if (currAmount > newAmount) {
        toMintAllocations[i] = 0;
        uint256 toRedeem = currAmount.sub(newAmount);
        uint256 availableLiquidity = protocol.availableLiquidity();
        if (availableLiquidity < toRedeem) {
          lowLiquidity = true;
          toRedeem = availableLiquidity;
        }
        // redeem the difference
        _redeemProtocolTokens(
          protocolWrappers[currToken],
          currToken,
          // convert amount from underlying to protocol token
          toRedeem.mul(10**18).div(protocol.getPriceInToken()),
          address(this) // tokens are now in this contract
        );
      } else {
        toMintAllocations[i] = newAmount.sub(currAmount);
        totalToMint = totalToMint.add(toMintAllocations[i]);
      }
    }
  }

  /**
   * Get the contract balance of every protocol currently used
   *
   * @return tokenAddresses : array with all token addresses used,
   *                          eg [cTokenAddress, iTokenAddress]
   * @return amounts : array with all amounts for each protocol in order,
   *                   eg [amountCompoundInUnderlying, amountFulcrumInUnderlying]
   * @return total : total AUM in underlying
   */
  function _getCurrentAllocations() internal view
    returns (address[] memory tokenAddresses, uint256[] memory amounts, uint256 total) {
      // Get balance of every protocol implemented
      tokenAddresses = new address[](allAvailableTokens.length);
      amounts = new uint256[](allAvailableTokens.length);

      address currentToken;
      uint256 currTokenPrice;

      for (uint256 i = 0; i < allAvailableTokens.length; i++) {
        currentToken = allAvailableTokens[i];
        tokenAddresses[i] = currentToken;
        currTokenPrice = ILendingProtocol(protocolWrappers[currentToken]).getPriceInToken();
        amounts[i] = currTokenPrice.mul(
          IERC20(currentToken).balanceOf(address(this))
        ).div(10**18);
        total = total.add(amounts[i]);
      }

      // return addresses and respective amounts in underlying
      return (tokenAddresses, amounts, total);
  }

  // ILendingProtocols calls
  /**
   * Mint protocol tokens through protocol wrapper
   *
   * @param _wrapperAddr : address of protocol wrapper
   * @param _amount : amount of underlying to be lended
   * @return tokens : new tokens minted
   */
  function _mintProtocolTokens(address _wrapperAddr, uint256 _amount)
    internal
    returns (uint256 tokens) {
      if (_amount == 0) {
        return tokens;
      }
      // Transfer _amount underlying token (eg. DAI) to _wrapperAddr
      IERC20(token).safeTransfer(_wrapperAddr, _amount);
      tokens = ILendingProtocol(_wrapperAddr).mint();
  }

  /**
   * Redeem underlying tokens through protocol wrapper
   *
   * @param _wrapperAddr : address of protocol wrapper
   * @param _amount : amount of `_token` to redeem
   * @param _token : protocol token address
   * @param _account : should be msg.sender when rebalancing and final user when redeeming
   * @return tokens : new tokens minted
   */
  function _redeemProtocolTokens(address _wrapperAddr, address _token, uint256 _amount, address _account)
    internal
    returns (uint256 tokens) {
      if (_amount == 0) {
        return tokens;
      }
      // Transfer _amount of _protocolToken (eg. cDAI) to _wrapperAddr
      IERC20(_token).safeTransfer(_wrapperAddr, _amount);
      tokens = ILendingProtocol(_wrapperAddr).redeem(_account);
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_cToken","type":"address"},{"internalType":"address","name":"_iToken","type":"address"},{"internalType":"address","name":"_rebalancer","type":"address"},{"internalType":"address","name":"_priceCalculator","type":"address"},{"internalType":"address","name":"_idleCompound","type":"address"},{"internalType":"address","name":"_idleFulcrum","type":"address"}],"payable":false,"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":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allAvailableTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"delayNewProtocols","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAPRs","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"aprs","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAvgAPR","outputs":[{"internalType":"uint256","name":"avgApr","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentAllocations","outputs":[{"internalType":"address[]","name":"tokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"total","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gst2","outputs":[{"internalType":"contract GasToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"iToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isNewProtocolDelayed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isRiskAdjusted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastAllocations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastITokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manualPlay","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"mintIdleToken","outputs":[{"internalType":"uint256","name":"mintedTokens","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_skipWholeRebalance","type":"bool"}],"name":"mintIdleToken","outputs":[{"internalType":"uint256","name":"mintedTokens","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_newAllocations","type":"uint256[]"}],"name":"openRebalance","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"avgApr","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceCalculator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolWrappers","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"rebalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"rebalance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"rebalanceWithGST","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rebalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_skipRebalance","type":"bool"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"redeemIdleToken","outputs":[{"internalType":"uint256","name":"redeemedTokens","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeemInterestBearingTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"releaseTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"setGasParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_isRiskAdjusted","type":"bool"}],"name":"setIsRiskAdjusted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_manualPlay","type":"bool"}],"name":"setManualPlay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_priceCalculator","type":"address"}],"name":"setPriceCalculator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_wrapper","type":"address"}],"name":"setProtocolWrapper","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rebalancer","type":"address"}],"name":"setRebalancer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"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"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userAvgPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

61010060405261374a608090815261a0aa60a052616c3e60c052611b6c60e0526200002f90600a9060046200054c565b503480156200003d57600080fd5b506040516200602e3803806200602e83398181016040526101408110156200006457600080fd5b81019080805160405193929190846401000000008211156200008557600080fd5b9083019060208201858111156200009b57600080fd5b8251640100000000811182820188101715620000b657600080fd5b82525081516020918201929091019080838360005b83811015620000e5578181015183820152602001620000cb565b50505050905090810190601f168015620001135780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200013757600080fd5b9083019060208201858111156200014d57600080fd5b82516401000000008111828201881017156200016857600080fd5b82525081516020918201929091019080838360005b83811015620001975781810151838201526020016200017d565b50505050905090810190601f168015620001c55780820380516001836020036101000a031916815260200191505b506040908152602082810151918301516060840151608085015160a086015160c087015160e0880151610100909801518c51979a50949850929691959094929391928b918b918b916200021f9160039190860190620005a2565b50815162000235906004906020850190620005a2565b506005805460ff191660ff92909216919091179055505060016006556200025b620003ff565b600780546001600160a01b0319166001600160a01b0392831617908190556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620002cd620002be6001600160e01b03620003ff16565b6001600160e01b036200040416565b6009805460ff19169055600c80546001600160a01b0319166001600160a01b0389169081179091556040805163313ce56760e01b8152905163313ce56791600480820192602092909190829003018186803b1580156200032c57600080fd5b505afa15801562000341573d6000803e3d6000fd5b505050506040513d60208110156200035857600080fd5b505160ff16601255600d80546001600160a01b03199081166001600160a01b03888116918217909355600e80548316888516179055600f805483168785161790558883166000818152600b60209081526040808320805487168a8916179055848352918290208054909516958716959095179093558251808401909352825291810191909152620003ee90601590600262000615565b5050505050505050505050620006bf565b335b90565b6200041f8160086200045660201b6200546b1790919060201c565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b6200046b82826001600160e01b03620004e316565b15620004be576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60006001600160a01b0382166200052c5760405162461bcd60e51b81526004018080602001828103825260228152602001806200600c6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b82805482825590600052602060002090810192821562000590579160200282015b8281111562000590578251829061ffff169055916020019190600101906200056d565b506200059e9291506200067b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005e557805160ff191683800117855562000590565b8280016001018555821562000590579182015b8281111562000590578251825591602001919060010190620005f8565b8280548282559060005260206000209081019282156200066d579160200282015b828111156200066d57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000636565b506200059e92915062000698565b6200040191905b808211156200059e576000815560010162000682565b6200040191905b808211156200059e5780546001600160a01b03191681556001016200069f565b61593d80620006cf6000396000f3fe608060405234801561001057600080fd5b50600436106103995760003560e01c8063715018a6116101e9578063b13bd4911161010f578063dae0f05e116100ad578063f2ce58061161007c578063f2ce580614610cfe578063f2d50ba614610d39578063f2fde38b14610d41578063fc0c546a14610d7457610399565b8063dae0f05e14610c80578063dba2d85d14610cb3578063dd62ed3e14610cbb578063ddca3f4314610cf657610399565b8063c85c93aa116100e9578063c85c93aa14610b50578063cb390f9714610bce578063cb50648814610bd6578063da5163cc14610bf557610399565b8063b13bd49114610a82578063be6fb53614610b23578063bf7143c114610b2b57610399565b80638b95e335116101875780639fc7875b116101565780639fc7875b146109eb578063a457c2d7146109f3578063a9059cbb14610a2c578063afdd3fc314610a6557610399565b80638b95e335146109cb5780638da5cb5b146109d35780638f32d59b146109db57806395d89b41146109e357610399565b806382ba653d116101c357806382ba653d1461093e57806382dc1ec41461095d5780638456cb59146109905780638705fcd41461099857610399565b8063715018a6146109265780637d7c2a1c1461092e5780637ff9b5961461093657610399565b80633b97e856116102ce57806346fbf68e1161026c57806369fe0e2d1161023b57806369fe0e2d1461089b5780636cfd1553146108b85780636ef8d66d146108eb57806370a08231146108f357610399565b806346fbf68e146107b65780635c975abb146107e95780636922d7b6146107f157806369ad6af21461082457610399565b8063408cfe24116102a8578063408cfe24146106cb57806341275358146106d357806341826c2d146106db57806345c8026c1461078357610399565b80633b97e856146106445780633cfcef641461064c5780633f4ba83a146106c357610399565b80631f80b18a1161033b578063313ce56711610315578063313ce56714610560578063321551251461057e57806336a00082146105ee578063395093511461060b57610399565b80631f80b18a1461050d57806323b872dd1461051557806323d39ab51461055857610399565b80630df94ef2116103775780630df94ef214610499578063154cf14e146104de57806318160ddd146104e8578063194a62a8146104f057610399565b806301d22ccd1461039e57806306fdde03146103cf578063095ea7b31461044c575b600080fd5b6103a6610d7c565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103d7610d98565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104115781810151838201526020016103f9565b50505050905090810190601f16801561043e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104856004803603604081101561046257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610e4d565b604080519115158252519081900360200190f35b6104cc600480360360208110156104af57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610e6b565b60408051918252519081900360200190f35b6104e6610e7d565b005b6104cc610f05565b6104e66004803603602081101561050657600080fd5b5035610f0b565b6104cc6110a6565b6104856004803603606081101561052b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611228565b6103a66112b0565b6105686112c3565b6040805160ff9092168252519081900360200190f35b6104e66004803603602081101561059457600080fd5b8101906020810181356401000000008111156105af57600080fd5b8201836020820111156105c157600080fd5b803590602001918460208302840111640100000000831117156105e357600080fd5b5090925090506112cc565b6103a66004803603602081101561060457600080fd5b5035611336565b6104856004803603604081101561062157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561136a565b6104cc6113cb565b6104cc6004803603604081101561066257600080fd5b8135919081019060408101602082013564010000000081111561068457600080fd5b82018360208201111561069657600080fd5b803590602001918460208302840111640100000000831117156106b857600080fd5b5090925090506113d1565b6104e661146e565b6103a661158b565b6103a66115a7565b6106e36115c3565b604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b8381101561072d578181015183820152602001610715565b50505050905001838103825285818151815260200191508051906020019060200280838360005b8381101561076c578181015183820152602001610754565b505050509050019550505050505060405180910390f35b6103a66004803603602081101561079957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166115db565b610485600480360360208110156107cc57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611603565b610485611616565b6104e66004803603602081101561080757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661161f565b6104856004803603604081101561083a57600080fd5b8135919081019060408101602082013564010000000081111561085c57600080fd5b82018360208201111561086e57600080fd5b8035906020019184602083028401116401000000008311171561089057600080fd5b5090925090506117db565b6104e6600480360360208110156108b157600080fd5b50356117f0565b6104e6600480360360208110156108ce57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118a5565b6104e66119ad565b6104cc6004803603602081101561090957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119bf565b6104e66119e7565b610485611aaf565b6104cc611ac1565b6104e66004803603602081101561095457600080fd5b50351515611ceb565b6104e66004803603602081101561097357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d75565b6104e6611dc4565b6104e6600480360360208110156109ae57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611eb6565b6103a6611fbe565b6103a6611fda565b610485611ff6565b6103d7612036565b6104856120b5565b61048560048036036040811015610a0957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356120be565b61048560048036036040811015610a4257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612139565b6104cc60048036036020811015610a7b57600080fd5b5035612163565b610a8a612181565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610ace578181015183820152602001610ab6565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610b0d578181015183820152602001610af5565b5050505090500194505050505060405180910390f35b610485612315565b6104cc60048036036040811015610b4157600080fd5b50803590602001351515612324565b6104cc60048036036060811015610b6657600080fd5b8135916020810135151591810190606081016040820135640100000000811115610b8f57600080fd5b820183602082011115610ba157600080fd5b80359060200191846020830284011164010000000083111715610bc357600080fd5b5090925090506123c0565b610485612753565b6104e660048036036020811015610bec57600080fd5b50351515612761565b610c6560048036036020811015610c0b57600080fd5b810190602081018135640100000000811115610c2657600080fd5b820183602082011115610c3857600080fd5b80359060200191846020830284011164010000000083111715610c5a57600080fd5b5090925090506127f1565b60408051921515835260208301919091528051918290030190f35b6104cc60048036036020811015610c9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c67565b610485612c79565b6104cc60048036036040811015610cd157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612c9f565b6104cc612cd7565b6104e660048036036040811015610d1457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612cdd565b6104cc612f65565b6104e660048036036020811015610d5757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f6b565b6103a6612fcd565b600e5473ffffffffffffffffffffffffffffffffffffffff1681565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e425780601f10610e1757610100808354040283529160200191610e42565b820191906000526020600020905b815481529060010190602001808311610e2557829003601f168201915b505050505090505b90565b6000610e61610e5a612fe9565b8484612fed565b5060015b92915050565b60176020526000908152604090205481565b610e85611ff6565b610ed6576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055565b60025490565b60068054600101908190556000610f20610f05565b9050600080805b60155481101561103e5760158181548110610f3e57fe5b60009182526020918290200154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216955085926370a0823192602480840193829003018186803b158015610fb657600080fd5b505afa158015610fca573d6000803e3d6000fd5b505050506040513d6020811015610fe057600080fd5b5051915081610fee57611036565b61103633611012866110068a8763ffffffff61310016565b9063ffffffff61316016565b73ffffffffffffffffffffffffffffffffffffffff8616919063ffffffff6131a216565b600101610f27565b50611049338661322f565b50505060065481146110a2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b6000606060006110b461335f565b90935091506000905080805b601554811015611220578481815181106110d657fe5b6020026020010151600014156110eb57611218565b600b6000601583815481106110fc57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811684528382019490945260409283019091205482517fc89d5b8b000000000000000000000000000000000000000000000000000000008152925193169263c89d5b8b926004808201939291829003018186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d60208110156111aa57600080fd5b505185519093506111e790859061100690670de0b6b3a7640000908990869081106111d157fe5b602002602001015161310090919063ffffffff16565b9150611215611208670de0b6b3a7640000611006868663ffffffff61310016565b879063ffffffff6135d816565b95505b6001016110c0565b505050505090565b6000611235848484613632565b611273843361126e85604051806060016040528060288152602001615806602891396112618a33612c9f565b919063ffffffff6137cf16565b612fed565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601760205260409020546112a69084908490613866565b5060019392505050565b6eb3f879cb30fe243b4dfee438691c0481565b60055460ff1690565b6112d4611ff6565b611325576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611331600a83836155ff565b505050565b6015818154811061134357fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6000610e61611377612fe9565b8461126e8560016000611388612fe9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6135d816565b60125481565b600680546001019081905560009030825a604080516000808252602082019092529192506114009189916139ad565b935061140e5a820383613c87565b50506006548114611466576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b509392505050565b61147e611479612fe9565b611603565b6114b95760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b60095460ff16611510576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611561612fe9565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190a1565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b60105473ffffffffffffffffffffffffffffffffffffffff1681565b60608060006115d061335f565b925092509250909192565b600b6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6000610e6560088363ffffffff613ea716565b60095460ff1690565b611627611ff6565b611678576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166116e0576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60145462010000900460ff161580611753575073ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090205415801590611753575073ffffffffffffffffffffffffffffffffffffffff81166000908152601960205260409020546203f4804291909103115b156117af57600f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556000908152601960205260408120556117d8565b73ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090204290555b50565b60006117e8600080613f28565b949350505050565b6117f8611ff6565b611849576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6127108111156118a0576040805162461bcd60e51b815260206004820152600c60248201527f46656520746f6f20686967680000000000000000000000000000000000000000604482015290519081900360640190fd5b601355565b6118ad611ff6565b6118fe576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611966576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6119bd6119b8612fe9565b6146dc565b565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6119ef611ff6565b611a40576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60075460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6000611abc600080613f28565b905090565b60006060601580549050604051908082528060200260200182016040528015611af4578160200160208202803883390190505b50905060005b601554811015611b8a57600b600060158381548110611b1557fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811684529083019390935260409091019020548351911690839083908110611b5d57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611afa565b50600f5473ffffffffffffffffffffffffffffffffffffffff1663f28f3221611bb1610f05565b306015856040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352858181548152602001915080548015611c5c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611c31575b50508381038252845181528451602091820191808701910280838360005b83811015611c92578181015183820152602001611c7a565b50505050905001965050505050505060206040518083038186803b158015611cb957600080fd5b505afa158015611ccd573d6000803e3d6000fd5b505050506040513d6020811015611ce357600080fd5b505192915050565b611cf3611ff6565b611d44576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b611d80611479612fe9565b611dbb5760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b6117d881614731565b611dcf611479612fe9565b611e0a5760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b60095460ff1615611e62576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611561612fe9565b611ebe611ff6565b611f0f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611f77576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b601080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600f5473ffffffffffffffffffffffffffffffffffffffff1681565b60075473ffffffffffffffffffffffffffffffffffffffff1690565b60075460009073ffffffffffffffffffffffffffffffffffffffff1661201a612fe9565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e425780601f10610e1757610100808354040283529160200191610e42565b60145460ff1681565b6000610e616120cb612fe9565b8461126e856040518060600160405280602581526020016158e460259139600160006120f5612fe9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6137cf16565b6000612146338484613632565b33600090815260176020526040902054610e619084908490613866565b6016818154811061217057fe5b600091825260209091200154905081565b60608060006015805490506040519080825280602002602001820160405280156121b5578160200160208202803883390190505b5060155460408051828152602080840282010190915291945080156121e4578160200160208202803883390190505b50915060005b60155481101561230f576015818154811061220157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508184828151811061223b57fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092018101919091528382166000908152600b82526040908190205481517fc89d5b8b000000000000000000000000000000000000000000000000000000008152915193169263c89d5b8b92600480840193919291829003018186803b1580156122c257600080fd5b505afa1580156122d6573d6000803e3d6000fd5b505050506040513d60208110156122ec57600080fd5b505183518490839081106122fc57fe5b60209081029190910101526001016121ea565b50509091565b60145462010000900460ff1681565b600680546001019081905560009030825a604080516000815260208101909152909150612353908790876139ad565b93506123615a820383613c87565b505060065481146123b9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5092915050565b600680546001019081905560009081805b60155481101561255257601581815481106123e857fe5b60009182526020918290200154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216926370a0823192602480840193829003018186803b15801561245d57600080fd5b505afa158015612471573d6000803e3d6000fd5b505050506040513d602081101561248757600080fd5b50519150816124955761254a565b61254761253a600b6000601585815481106124ac57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff908116845290830193909352604090910190205460158054919092169190859081106124f757fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16612534612524610f05565b6110068e8963ffffffff61310016565b30614786565b859063ffffffff6135d816565b93505b6001016123d1565b5061255d338861322f565b6000601354118015612586575060105473ffffffffffffffffffffffffffffffffffffffff1615155b1561259857612595878461486d565b92505b600c546125c29073ffffffffffffffffffffffffffffffffffffffff16338563ffffffff6131a216565b3073ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561260857600080fd5b505afa15801561261c573d6000803e3d6000fd5b505050506040513d602081101561263257600080fd5b5051806126d35750601154600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637ff9b5966040518163ffffffff1660e01b815260040160206040518083038186803b1580156126a557600080fd5b505afa1580156126b9573d6000803e3d6000fd5b505050506040513d60208110156126cf57600080fd5b5051105b806126db5750855b156126e657506126f4565b6126f1600080613f28565b50505b600654811461274a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50949350505050565b601454610100900460ff1681565b612769611ff6565b6127ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60148054911515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909216919091179055565b600954600090819060ff161561284e576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b1580156128b957600080fd5b505afa1580156128cd573d6000803e3d6000fd5b505050506040513d60208110156128e357600080fd5b5051601154909150811015806128fb575060145460ff165b61294c576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156129b657600080fd5b505af11580156129ca573d6000803e3d6000fd5b505050506040513d60208110156129e057600080fd5b505115806129f0575060145460ff165b612a41576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b601454610100900460ff1615612a9e576040805162461bcd60e51b815260206004820152601f60248201527f53657474696e6720616c6c6f636174696f6e73206e6f7420616c6c6f77656400604482015290519081900360640190fd5b6000612aa86110a6565b600e54604080517fae773c10000000000000000000000000000000000000000000000000000000008152600481019182526044810189905292935073ffffffffffffffffffffffffffffffffffffffff9091169163ae773c10918991899160159181906024810190606401866020870280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909101848103835285548082526020909101915085908015612b9f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612b74575b505095505050505050600060405180830381600087803b158015612bc257600080fd5b505af1158015612bd6573d6000803e3d6000fd5b505050506000612be7600080613f28565b90506000612bf36110a6565b9050828111612c49576040805162461bcd60e51b815260206004820152601060248201527f415052206e6f7420696d70726f76656400000000000000000000000000000000604482015290519081900360640190fd5b909450925050601154811115612c5f5760118190555b509250929050565b60196020526000908152604090205481565b60003360005a9050612c8c600080613f28565b9250612c9a5a820383613c87565b505090565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60135481565b612ce5611ff6565b612d36576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821615801590612d70575073ffffffffffffffffffffffffffffffffffffffff811615155b612dc1576040805162461bcd60e51b815260206004820152600e60248201527f736f6d6520616464722069732030000000000000000000000000000000000000604482015290519081900360640190fd5b60145462010000900460ff161580612e34575073ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090205415801590612e34575073ffffffffffffffffffffffffffffffffffffffff81166000908152601960205260409020546203f4804291909103115b15612f3b5773ffffffffffffffffffffffffffffffffffffffff8281166000908152600b602052604090205416612ed657601580546001810182556000919091527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec4750180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790555b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600b6020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948616948517905592825260199052908120556110a2565b73ffffffffffffffffffffffffffffffffffffffff16600090815260196020526040902042905550565b60115481565b612f73611ff6565b612fc4576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6117d8816149da565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b3390565b73ffffffffffffffffffffffffffffffffffffffff831661303f5760405162461bcd60e51b81526004018080602001828103825260248152602001806158966024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166130915760405162461bcd60e51b81526004018080602001828103825260228152602001806157556022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008261310f57506000610e65565b8282028284828161311c57fe5b04146131595760405162461bcd60e51b81526004018080602001828103825260218152602001806157e56021913960400191505060405180910390fd5b9392505050565b600061315983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614aba565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611331908490614b1f565b73ffffffffffffffffffffffffffffffffffffffff82166132815760405162461bcd60e51b81526004018080602001828103825260218152602001806158506021913960400191505060405180910390fd5b6132d1816040518060600160405280602281526020016156dd6022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff6137cf16565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205560025461330a908263ffffffff614d1516565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6060806000601580549050604051908082528060200260200182016040528015613393578160200160208202803883390190505b5060155460408051828152602080840282010190915291945080156133c2578160200160208202803883390190505b509150600080805b6015548110156135d057601581815481106133e157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692508286828151811061341b57fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092018101919091528482166000908152600b82526040908190205481517f02bbce4600000000000000000000000000000000000000000000000000000000815291519316926302bbce4692600480840193919291829003018186803b1580156134a257600080fd5b505afa1580156134b6573d6000803e3d6000fd5b505050506040513d60208110156134cc57600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191935061358891670de0b6b3a7640000916110069173ffffffffffffffffffffffffffffffffffffffff8816916370a08231916024808301926020929190829003018186803b15801561354f57600080fd5b505afa158015613563573d6000803e3d6000fd5b505050506040513d602081101561357957600080fd5b5051859063ffffffff61310016565b85828151811061359457fe5b6020026020010181815250506135c68582815181106135af57fe5b6020026020010151856135d890919063ffffffff16565b93506001016133ca565b505050909192565b600082820183811015613159576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166136845760405162461bcd60e51b81526004018080602001828103825260258152602001806158716025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166136d65760405162461bcd60e51b81526004018080602001828103825260238152602001806156ba6023913960400191505060405180910390fd5b613726816040518060600160405280602681526020016157776026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff6137cf16565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054613768908263ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561385e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561382357818101518382015260200161380b565b50505050905090810190601f1680156138505780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6013546138ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152601860205260409020546138a3908363ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260186020526040902055611331565b73ffffffffffffffffffffffffffffffffffffffff831660009081526018602052604081205461390d90613901866119bf565b9063ffffffff614d1516565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260176020526040812054919250613946838663ffffffff614d1516565b905061397f61395f84611006878963ffffffff61310016565b61397385611006868663ffffffff61310016565b9063ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260176020526040902055505050505050565b60095460009060ff1615613a08576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b158015613a7357600080fd5b505afa158015613a87573d6000803e3d6000fd5b505050506040513d6020811015613a9d57600080fd5b505160115490915081101580613ab5575060145460ff165b613b06576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613b7057600080fd5b505af1158015613b84573d6000803e3d6000fd5b505050506040513d6020811015613b9a57600080fd5b50511580613baa575060145460ff165b613bfb576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b6000613c05611ac1565b600c54909150613c339073ffffffffffffffffffffffffffffffffffffffff1633308963ffffffff614d5716565b613c3e600085613f28565b50613c5b8161100688670de0b6b3a764000063ffffffff61310016565b9250613c673384614dec565b613c72338483613866565b50601154811115611466576011559392505050565b6000600a600181548110613c9757fe5b9060005260206000200154600a600081548110613cb057fe5b9060005260206000200154840181613cc457fe5b0490506000805a9050600a600281548110613cdb57fe5b90600052602060002001548110613d2b57600a600381548110613cfa57fe5b9060005260206000200154600a600281548110613d1357fe5b9060005260206000200154820381613d2757fe5b0491505b81831115613d37578192505b8215613ea05773ffffffffffffffffffffffffffffffffffffffff8416301415613def576eb3f879cb30fe243b4dfee438691c0473ffffffffffffffffffffffffffffffffffffffff16636366b936846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613dbd57600080fd5b505af1158015613dd1573d6000803e3d6000fd5b505050506040513d6020811015613de757600080fd5b50613ea09050565b604080517f079d229f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024810185905290516eb3f879cb30fe243b4dfee438691c049163079d229f9160448083019260209291908290030181600087803b158015613e7357600080fd5b505af1158015613e87573d6000803e3d6000fd5b505050506040513d6020811015613e9d57600080fd5b50505b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216613efb5760405162461bcd60e51b815260040180806020018281038252602281526020018061582e6022913960400191505060405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff166000908152602091909152604090205460ff1690565b60095460009060ff1615613f83576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b158015613fee57600080fd5b505afa158015614002573d6000803e3d6000fd5b505050506040513d602081101561401857600080fd5b505160115490915081101580614030575060145460ff165b614081576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156140eb57600080fd5b505af11580156140ff573d6000803e3d6000fd5b505050506040513d602081101561411557600080fd5b50511580614125575060145460ff165b614176576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b600e54604080517f65ed6e23000000000000000000000000000000000000000000000000000000008152905160609273ffffffffffffffffffffffffffffffffffffffff16916365ed6e23916004808301926000929190829003018186803b1580156141e157600080fd5b505afa1580156141f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561423c57600080fd5b810190808051604051939291908464010000000082111561425c57600080fd5b90830190602082018581111561427157600080fd5b825186602082028301116401000000008211171561428e57600080fd5b82525081516020918201928201910280838360005b838110156142bb5781810151838201526020016142a3565b5050505090500160405250505090506000601680549050825114905080156143375760005b6016548110806142ee575081155b15614335578281815181106142ff57fe5b60200260200101516016828154811061431457fe5b90600052602060002001541461432d5760009150614335565b6001016142e0565b505b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b1580156143a857600080fd5b505afa1580156143bc573d6000803e3d6000fd5b505050506040513d60208110156143d257600080fd5b505190508180156143e1575080155b156143f257600094505050506146c9565b8015614499576016541580156144055750855b1561441f57825161441d90601690602086019061564a565b505b614499601580548060200260200160405190810160405280929190818152602001828054801561448557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161445a575b50505050506144948584614f03565b614fe9565b85806144a25750815b156144b357600094505050506146c9565b60608060006144c061335f565b92509250925060606144d28783614f03565b905060606000806144e48787866150b2565b92509250925080614510576144fb60166000615685565b895161450e9060169060208d019061564a565b505b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561458157600080fd5b505afa158015614595573d6000803e3d6000fd5b505050506040513d60208110156145ab57600080fd5b505190506001811180156145bf5750600183115b156146b957606084516040519080825280602002602001820160405280156145f1578160200160208202803883390190505b50905060005b85518110156146365761461785611006620186a08985815181106111d157fe5b82828151811061462357fe5b60209081029190910101526001016145f7565b5060606146438284614f03565b90506146b660158054806020026020016040519081016040528092919081815260200182805480156146ab57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311614680575b505050505082614fe9565b50505b60019c5050505050505050505050505b6011548111156123b95760115592915050565b6146ed60088263ffffffff6153d916565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61474260088263ffffffff61546b16565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b600082614792576117e8565b6147b973ffffffffffffffffffffffffffffffffffffffff8516868563ffffffff6131a216565b8473ffffffffffffffffffffffffffffffffffffffff166395a2251f836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561483857600080fd5b505af115801561484c573d6000803e3d6000fd5b505050506040513d602081101561486257600080fd5b505195945050505050565b3360009081526018602052604081205481614886611ac1565b905060008211801561489757508482115b156148a0578491505b336000908152601760205260408120546148f290670de0b6b3a764000090611006906148e2906148d68b8963ffffffff614d1516565b9063ffffffff61310016565b613973878763ffffffff61310016565b90506000614912670de0b6b3a7640000611006898663ffffffff61310016565b9050818110156149285785945050505050610e65565b600061493a828463ffffffff614d1516565b9050600061495a620186a06110066013548561310090919063ffffffff16565b601054600c5491925061498d9173ffffffffffffffffffffffffffffffffffffffff90811691168363ffffffff6131a216565b336000908152601860205260409020546149ad908763ffffffff614d1516565b336000908152601860205260409020556149cd838263ffffffff614d1516565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116614a2c5760405162461bcd60e51b815260040180806020018281038252602681526020018061572f6026913960400191505060405180910390fd5b60075460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008183614b095760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561382357818101518382015260200161380b565b506000838581614b1557fe5b0495945050505050565b614b3e8273ffffffffffffffffffffffffffffffffffffffff16615517565b614b8f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b60208310614bf857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614bbb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614c5a576040519150601f19603f3d011682016040523d82523d6000602084013e614c5f565b606091505b509150915081614cb6576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115614d0f57808060200190516020811015614cd257600080fd5b5051614d0f5760405162461bcd60e51b815260040180806020018281038252602a8152602001806158ba602a913960400191505060405180910390fd5b50505050565b600061315983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506137cf565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052614d0f908590614b1f565b73ffffffffffffffffffffffffffffffffffffffff8216614e54576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254614e67908263ffffffff6135d816565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054614ea0908263ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6060808351604051908082528060200260200182016040528015614f31578160200160208202803883390190505b509050600080805b8651811015614fde576001875103811415614f7b57614f5e868363ffffffff614d1516565b848281518110614f6a57fe5b602002602001018181525050614fd6565b614fa8620186a0611006898481518110614f9157fe5b60200260200101518961310090919063ffffffff16565b9250614fba828463ffffffff6135d816565b915082848281518110614fc957fe5b6020026020010181815250505b600101614f39565b509195945050505050565b80518251146150295760405162461bcd60e51b815260040180806020018281038252602781526020018061579d6027913960400191505060405180910390fd5b6000805b8251811015614d0f5782818151811061504257fe5b60200260200101519150816000141561505a576150aa565b6150a8600b600086848151811061506d57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260400160002054168361554e565b505b60010161502d565b6060600080835185511461510d576040805162461bcd60e51b815260206004820152601160248201527f4c656e67746873206e6f7420657175616c000000000000000000000000000000604482015290519081900360640190fd5b8451604051908082528060200260200182016040528015615138578160200160208202803883390190505b5092506000808080805b89518110156153cb578a818151811061515757fe5b6020026020010151915088818151811061516d57fe5b6020026020010151925089818151811061518357fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8085166000908152600b90935260409092205490911695509350828411156153725760008882815181106151d457fe5b602090810291909101015260006151f1858563ffffffff614d1516565b905060008673ffffffffffffffffffffffffffffffffffffffff1663743753596040518163ffffffff1660e01b815260040160206040518083038186803b15801561523b57600080fd5b505afa15801561524f573d6000803e3d6000fd5b505050506040513d602081101561526557600080fd5b505190508181101561527957600197508091505b61536a600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856125348a73ffffffffffffffffffffffffffffffffffffffff166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b15801561532657600080fd5b505afa15801561533a573d6000803e3d6000fd5b505050506040513d602081101561535057600080fd5b505161100687670de0b6b3a764000063ffffffff61310016565b5050506153c3565b615382838563ffffffff614d1516565b88828151811061538e57fe5b6020026020010181815250506153c08882815181106153a957fe5b6020026020010151886135d890919063ffffffff16565b96505b600101615142565b505050505093509350939050565b6153e38282613ea7565b61541e5760405162461bcd60e51b81526004018080602001828103825260218152602001806157c46021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6154758282613ea7565b156154c7576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906117e85750141592915050565b60008161555a57610e65565b600c546155849073ffffffffffffffffffffffffffffffffffffffff16848463ffffffff6131a216565b8273ffffffffffffffffffffffffffffffffffffffff16631249c58b6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156155cc57600080fd5b505af11580156155e0573d6000803e3d6000fd5b505050506040513d60208110156155f657600080fd5b50519392505050565b82805482825590600052602060002090810192821561563a579160200282015b8281111561563a57823582559160200191906001019061561f565b5061564692915061569f565b5090565b82805482825590600052602060002090810192821561563a579160200282015b8281111561563a57825182559160200191906001019061566a565b50805460008255906000526020600020908101906117d891905b610e4a91905b8082111561564657600081556001016156a556fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416c6c20746f6b656e73206c656e67746820213d20616c6c6f636174696f6e73206c656e677468526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f206164647265737345524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7231582051c4fdcd9f1bbf5db6b87ac9afb84770f1f76dfe1400ee5ff128ff170945c92964736f6c63430005100032526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000012000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000f650c3d88d12db855b8bf7d11be6c55a4e07dcc90000000000000000000000008326645f3aa6de6420102fdb7da9e3a91855045b0000000000000000000000002403457ce59e56dd69d2fc4f22e77d7ab180deb1000000000000000000000000aefb1325a2c1756bc3fcc516d6c2cf947d225358000000000000000000000000d4d7e65a66850a19680802096896a31866131a9b000000000000000000000000cdd7db5c25f0de4e3194f56456d504a03676a8c9000000000000000000000000000000000000000000000000000000000000001749646c6555534454207633205b4d6178207969656c645d000000000000000000000000000000000000000000000000000000000000000000000000000000000d69646c65555344545969656c6400000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103995760003560e01c8063715018a6116101e9578063b13bd4911161010f578063dae0f05e116100ad578063f2ce58061161007c578063f2ce580614610cfe578063f2d50ba614610d39578063f2fde38b14610d41578063fc0c546a14610d7457610399565b8063dae0f05e14610c80578063dba2d85d14610cb3578063dd62ed3e14610cbb578063ddca3f4314610cf657610399565b8063c85c93aa116100e9578063c85c93aa14610b50578063cb390f9714610bce578063cb50648814610bd6578063da5163cc14610bf557610399565b8063b13bd49114610a82578063be6fb53614610b23578063bf7143c114610b2b57610399565b80638b95e335116101875780639fc7875b116101565780639fc7875b146109eb578063a457c2d7146109f3578063a9059cbb14610a2c578063afdd3fc314610a6557610399565b80638b95e335146109cb5780638da5cb5b146109d35780638f32d59b146109db57806395d89b41146109e357610399565b806382ba653d116101c357806382ba653d1461093e57806382dc1ec41461095d5780638456cb59146109905780638705fcd41461099857610399565b8063715018a6146109265780637d7c2a1c1461092e5780637ff9b5961461093657610399565b80633b97e856116102ce57806346fbf68e1161026c57806369fe0e2d1161023b57806369fe0e2d1461089b5780636cfd1553146108b85780636ef8d66d146108eb57806370a08231146108f357610399565b806346fbf68e146107b65780635c975abb146107e95780636922d7b6146107f157806369ad6af21461082457610399565b8063408cfe24116102a8578063408cfe24146106cb57806341275358146106d357806341826c2d146106db57806345c8026c1461078357610399565b80633b97e856146106445780633cfcef641461064c5780633f4ba83a146106c357610399565b80631f80b18a1161033b578063313ce56711610315578063313ce56714610560578063321551251461057e57806336a00082146105ee578063395093511461060b57610399565b80631f80b18a1461050d57806323b872dd1461051557806323d39ab51461055857610399565b80630df94ef2116103775780630df94ef214610499578063154cf14e146104de57806318160ddd146104e8578063194a62a8146104f057610399565b806301d22ccd1461039e57806306fdde03146103cf578063095ea7b31461044c575b600080fd5b6103a6610d7c565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103d7610d98565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104115781810151838201526020016103f9565b50505050905090810190601f16801561043e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104856004803603604081101561046257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610e4d565b604080519115158252519081900360200190f35b6104cc600480360360208110156104af57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610e6b565b60408051918252519081900360200190f35b6104e6610e7d565b005b6104cc610f05565b6104e66004803603602081101561050657600080fd5b5035610f0b565b6104cc6110a6565b6104856004803603606081101561052b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611228565b6103a66112b0565b6105686112c3565b6040805160ff9092168252519081900360200190f35b6104e66004803603602081101561059457600080fd5b8101906020810181356401000000008111156105af57600080fd5b8201836020820111156105c157600080fd5b803590602001918460208302840111640100000000831117156105e357600080fd5b5090925090506112cc565b6103a66004803603602081101561060457600080fd5b5035611336565b6104856004803603604081101561062157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561136a565b6104cc6113cb565b6104cc6004803603604081101561066257600080fd5b8135919081019060408101602082013564010000000081111561068457600080fd5b82018360208201111561069657600080fd5b803590602001918460208302840111640100000000831117156106b857600080fd5b5090925090506113d1565b6104e661146e565b6103a661158b565b6103a66115a7565b6106e36115c3565b604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b8381101561072d578181015183820152602001610715565b50505050905001838103825285818151815260200191508051906020019060200280838360005b8381101561076c578181015183820152602001610754565b505050509050019550505050505060405180910390f35b6103a66004803603602081101561079957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166115db565b610485600480360360208110156107cc57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611603565b610485611616565b6104e66004803603602081101561080757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661161f565b6104856004803603604081101561083a57600080fd5b8135919081019060408101602082013564010000000081111561085c57600080fd5b82018360208201111561086e57600080fd5b8035906020019184602083028401116401000000008311171561089057600080fd5b5090925090506117db565b6104e6600480360360208110156108b157600080fd5b50356117f0565b6104e6600480360360208110156108ce57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118a5565b6104e66119ad565b6104cc6004803603602081101561090957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119bf565b6104e66119e7565b610485611aaf565b6104cc611ac1565b6104e66004803603602081101561095457600080fd5b50351515611ceb565b6104e66004803603602081101561097357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611d75565b6104e6611dc4565b6104e6600480360360208110156109ae57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611eb6565b6103a6611fbe565b6103a6611fda565b610485611ff6565b6103d7612036565b6104856120b5565b61048560048036036040811015610a0957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356120be565b61048560048036036040811015610a4257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612139565b6104cc60048036036020811015610a7b57600080fd5b5035612163565b610a8a612181565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610ace578181015183820152602001610ab6565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610b0d578181015183820152602001610af5565b5050505090500194505050505060405180910390f35b610485612315565b6104cc60048036036040811015610b4157600080fd5b50803590602001351515612324565b6104cc60048036036060811015610b6657600080fd5b8135916020810135151591810190606081016040820135640100000000811115610b8f57600080fd5b820183602082011115610ba157600080fd5b80359060200191846020830284011164010000000083111715610bc357600080fd5b5090925090506123c0565b610485612753565b6104e660048036036020811015610bec57600080fd5b50351515612761565b610c6560048036036020811015610c0b57600080fd5b810190602081018135640100000000811115610c2657600080fd5b820183602082011115610c3857600080fd5b80359060200191846020830284011164010000000083111715610c5a57600080fd5b5090925090506127f1565b60408051921515835260208301919091528051918290030190f35b6104cc60048036036020811015610c9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c67565b610485612c79565b6104cc60048036036040811015610cd157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612c9f565b6104cc612cd7565b6104e660048036036040811015610d1457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612cdd565b6104cc612f65565b6104e660048036036020811015610d5757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f6b565b6103a6612fcd565b600e5473ffffffffffffffffffffffffffffffffffffffff1681565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e425780601f10610e1757610100808354040283529160200191610e42565b820191906000526020600020905b815481529060010190602001808311610e2557829003601f168201915b505050505090505b90565b6000610e61610e5a612fe9565b8484612fed565b5060015b92915050565b60176020526000908152604090205481565b610e85611ff6565b610ed6576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055565b60025490565b60068054600101908190556000610f20610f05565b9050600080805b60155481101561103e5760158181548110610f3e57fe5b60009182526020918290200154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216955085926370a0823192602480840193829003018186803b158015610fb657600080fd5b505afa158015610fca573d6000803e3d6000fd5b505050506040513d6020811015610fe057600080fd5b5051915081610fee57611036565b61103633611012866110068a8763ffffffff61310016565b9063ffffffff61316016565b73ffffffffffffffffffffffffffffffffffffffff8616919063ffffffff6131a216565b600101610f27565b50611049338661322f565b50505060065481146110a2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b6000606060006110b461335f565b90935091506000905080805b601554811015611220578481815181106110d657fe5b6020026020010151600014156110eb57611218565b600b6000601583815481106110fc57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811684528382019490945260409283019091205482517fc89d5b8b000000000000000000000000000000000000000000000000000000008152925193169263c89d5b8b926004808201939291829003018186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d60208110156111aa57600080fd5b505185519093506111e790859061100690670de0b6b3a7640000908990869081106111d157fe5b602002602001015161310090919063ffffffff16565b9150611215611208670de0b6b3a7640000611006868663ffffffff61310016565b879063ffffffff6135d816565b95505b6001016110c0565b505050505090565b6000611235848484613632565b611273843361126e85604051806060016040528060288152602001615806602891396112618a33612c9f565b919063ffffffff6137cf16565b612fed565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601760205260409020546112a69084908490613866565b5060019392505050565b6eb3f879cb30fe243b4dfee438691c0481565b60055460ff1690565b6112d4611ff6565b611325576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611331600a83836155ff565b505050565b6015818154811061134357fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6000610e61611377612fe9565b8461126e8560016000611388612fe9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6135d816565b60125481565b600680546001019081905560009030825a604080516000808252602082019092529192506114009189916139ad565b935061140e5a820383613c87565b50506006548114611466576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b509392505050565b61147e611479612fe9565b611603565b6114b95760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b60095460ff16611510576040805162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611561612fe9565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190a1565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b60105473ffffffffffffffffffffffffffffffffffffffff1681565b60608060006115d061335f565b925092509250909192565b600b6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6000610e6560088363ffffffff613ea716565b60095460ff1690565b611627611ff6565b611678576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166116e0576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60145462010000900460ff161580611753575073ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090205415801590611753575073ffffffffffffffffffffffffffffffffffffffff81166000908152601960205260409020546203f4804291909103115b156117af57600f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556000908152601960205260408120556117d8565b73ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090204290555b50565b60006117e8600080613f28565b949350505050565b6117f8611ff6565b611849576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6127108111156118a0576040805162461bcd60e51b815260206004820152600c60248201527f46656520746f6f20686967680000000000000000000000000000000000000000604482015290519081900360640190fd5b601355565b6118ad611ff6565b6118fe576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611966576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6119bd6119b8612fe9565b6146dc565b565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6119ef611ff6565b611a40576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60075460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6000611abc600080613f28565b905090565b60006060601580549050604051908082528060200260200182016040528015611af4578160200160208202803883390190505b50905060005b601554811015611b8a57600b600060158381548110611b1557fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811684529083019390935260409091019020548351911690839083908110611b5d57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611afa565b50600f5473ffffffffffffffffffffffffffffffffffffffff1663f28f3221611bb1610f05565b306015856040518563ffffffff1660e01b8152600401808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352858181548152602001915080548015611c5c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611c31575b50508381038252845181528451602091820191808701910280838360005b83811015611c92578181015183820152602001611c7a565b50505050905001965050505050505060206040518083038186803b158015611cb957600080fd5b505afa158015611ccd573d6000803e3d6000fd5b505050506040513d6020811015611ce357600080fd5b505192915050565b611cf3611ff6565b611d44576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b611d80611479612fe9565b611dbb5760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b6117d881614731565b611dcf611479612fe9565b611e0a5760405162461bcd60e51b81526004018080602001828103825260308152602001806156ff6030913960400191505060405180910390fd5b60095460ff1615611e62576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611561612fe9565b611ebe611ff6565b611f0f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611f77576040805162461bcd60e51b815260206004820152600960248201527f4164647220697320300000000000000000000000000000000000000000000000604482015290519081900360640190fd5b601080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600f5473ffffffffffffffffffffffffffffffffffffffff1681565b60075473ffffffffffffffffffffffffffffffffffffffff1690565b60075460009073ffffffffffffffffffffffffffffffffffffffff1661201a612fe9565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610e425780601f10610e1757610100808354040283529160200191610e42565b60145460ff1681565b6000610e616120cb612fe9565b8461126e856040518060600160405280602581526020016158e460259139600160006120f5612fe9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6137cf16565b6000612146338484613632565b33600090815260176020526040902054610e619084908490613866565b6016818154811061217057fe5b600091825260209091200154905081565b60608060006015805490506040519080825280602002602001820160405280156121b5578160200160208202803883390190505b5060155460408051828152602080840282010190915291945080156121e4578160200160208202803883390190505b50915060005b60155481101561230f576015818154811061220157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508184828151811061223b57fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092018101919091528382166000908152600b82526040908190205481517fc89d5b8b000000000000000000000000000000000000000000000000000000008152915193169263c89d5b8b92600480840193919291829003018186803b1580156122c257600080fd5b505afa1580156122d6573d6000803e3d6000fd5b505050506040513d60208110156122ec57600080fd5b505183518490839081106122fc57fe5b60209081029190910101526001016121ea565b50509091565b60145462010000900460ff1681565b600680546001019081905560009030825a604080516000815260208101909152909150612353908790876139ad565b93506123615a820383613c87565b505060065481146123b9576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5092915050565b600680546001019081905560009081805b60155481101561255257601581815481106123e857fe5b60009182526020918290200154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216926370a0823192602480840193829003018186803b15801561245d57600080fd5b505afa158015612471573d6000803e3d6000fd5b505050506040513d602081101561248757600080fd5b50519150816124955761254a565b61254761253a600b6000601585815481106124ac57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff908116845290830193909352604090910190205460158054919092169190859081106124f757fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16612534612524610f05565b6110068e8963ffffffff61310016565b30614786565b859063ffffffff6135d816565b93505b6001016123d1565b5061255d338861322f565b6000601354118015612586575060105473ffffffffffffffffffffffffffffffffffffffff1615155b1561259857612595878461486d565b92505b600c546125c29073ffffffffffffffffffffffffffffffffffffffff16338563ffffffff6131a216565b3073ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561260857600080fd5b505afa15801561261c573d6000803e3d6000fd5b505050506040513d602081101561263257600080fd5b5051806126d35750601154600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637ff9b5966040518163ffffffff1660e01b815260040160206040518083038186803b1580156126a557600080fd5b505afa1580156126b9573d6000803e3d6000fd5b505050506040513d60208110156126cf57600080fd5b5051105b806126db5750855b156126e657506126f4565b6126f1600080613f28565b50505b600654811461274a576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50949350505050565b601454610100900460ff1681565b612769611ff6565b6127ba576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60148054911515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909216919091179055565b600954600090819060ff161561284e576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b1580156128b957600080fd5b505afa1580156128cd573d6000803e3d6000fd5b505050506040513d60208110156128e357600080fd5b5051601154909150811015806128fb575060145460ff165b61294c576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156129b657600080fd5b505af11580156129ca573d6000803e3d6000fd5b505050506040513d60208110156129e057600080fd5b505115806129f0575060145460ff165b612a41576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b601454610100900460ff1615612a9e576040805162461bcd60e51b815260206004820152601f60248201527f53657474696e6720616c6c6f636174696f6e73206e6f7420616c6c6f77656400604482015290519081900360640190fd5b6000612aa86110a6565b600e54604080517fae773c10000000000000000000000000000000000000000000000000000000008152600481019182526044810189905292935073ffffffffffffffffffffffffffffffffffffffff9091169163ae773c10918991899160159181906024810190606401866020870280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909101848103835285548082526020909101915085908015612b9f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612b74575b505095505050505050600060405180830381600087803b158015612bc257600080fd5b505af1158015612bd6573d6000803e3d6000fd5b505050506000612be7600080613f28565b90506000612bf36110a6565b9050828111612c49576040805162461bcd60e51b815260206004820152601060248201527f415052206e6f7420696d70726f76656400000000000000000000000000000000604482015290519081900360640190fd5b909450925050601154811115612c5f5760118190555b509250929050565b60196020526000908152604090205481565b60003360005a9050612c8c600080613f28565b9250612c9a5a820383613c87565b505090565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60135481565b612ce5611ff6565b612d36576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821615801590612d70575073ffffffffffffffffffffffffffffffffffffffff811615155b612dc1576040805162461bcd60e51b815260206004820152600e60248201527f736f6d6520616464722069732030000000000000000000000000000000000000604482015290519081900360640190fd5b60145462010000900460ff161580612e34575073ffffffffffffffffffffffffffffffffffffffff811660009081526019602052604090205415801590612e34575073ffffffffffffffffffffffffffffffffffffffff81166000908152601960205260409020546203f4804291909103115b15612f3b5773ffffffffffffffffffffffffffffffffffffffff8281166000908152600b602052604090205416612ed657601580546001810182556000919091527f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec4750180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790555b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600b6020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948616948517905592825260199052908120556110a2565b73ffffffffffffffffffffffffffffffffffffffff16600090815260196020526040902042905550565b60115481565b612f73611ff6565b612fc4576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6117d8816149da565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b3390565b73ffffffffffffffffffffffffffffffffffffffff831661303f5760405162461bcd60e51b81526004018080602001828103825260248152602001806158966024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166130915760405162461bcd60e51b81526004018080602001828103825260228152602001806157556022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008261310f57506000610e65565b8282028284828161311c57fe5b04146131595760405162461bcd60e51b81526004018080602001828103825260218152602001806157e56021913960400191505060405180910390fd5b9392505050565b600061315983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614aba565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611331908490614b1f565b73ffffffffffffffffffffffffffffffffffffffff82166132815760405162461bcd60e51b81526004018080602001828103825260218152602001806158506021913960400191505060405180910390fd5b6132d1816040518060600160405280602281526020016156dd6022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff6137cf16565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205560025461330a908263ffffffff614d1516565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6060806000601580549050604051908082528060200260200182016040528015613393578160200160208202803883390190505b5060155460408051828152602080840282010190915291945080156133c2578160200160208202803883390190505b509150600080805b6015548110156135d057601581815481106133e157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692508286828151811061341b57fe5b73ffffffffffffffffffffffffffffffffffffffff9283166020918202929092018101919091528482166000908152600b82526040908190205481517f02bbce4600000000000000000000000000000000000000000000000000000000815291519316926302bbce4692600480840193919291829003018186803b1580156134a257600080fd5b505afa1580156134b6573d6000803e3d6000fd5b505050506040513d60208110156134cc57600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191935061358891670de0b6b3a7640000916110069173ffffffffffffffffffffffffffffffffffffffff8816916370a08231916024808301926020929190829003018186803b15801561354f57600080fd5b505afa158015613563573d6000803e3d6000fd5b505050506040513d602081101561357957600080fd5b5051859063ffffffff61310016565b85828151811061359457fe5b6020026020010181815250506135c68582815181106135af57fe5b6020026020010151856135d890919063ffffffff16565b93506001016133ca565b505050909192565b600082820183811015613159576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166136845760405162461bcd60e51b81526004018080602001828103825260258152602001806158716025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166136d65760405162461bcd60e51b81526004018080602001828103825260238152602001806156ba6023913960400191505060405180910390fd5b613726816040518060600160405280602681526020016157776026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff6137cf16565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054613768908263ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000818484111561385e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561382357818101518382015260200161380b565b50505050905090810190601f1680156138505780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6013546138ce5773ffffffffffffffffffffffffffffffffffffffff83166000908152601860205260409020546138a3908363ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260186020526040902055611331565b73ffffffffffffffffffffffffffffffffffffffff831660009081526018602052604081205461390d90613901866119bf565b9063ffffffff614d1516565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260176020526040812054919250613946838663ffffffff614d1516565b905061397f61395f84611006878963ffffffff61310016565b61397385611006868663ffffffff61310016565b9063ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260176020526040902055505050505050565b60095460009060ff1615613a08576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b158015613a7357600080fd5b505afa158015613a87573d6000803e3d6000fd5b505050506040513d6020811015613a9d57600080fd5b505160115490915081101580613ab5575060145460ff165b613b06576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613b7057600080fd5b505af1158015613b84573d6000803e3d6000fd5b505050506040513d6020811015613b9a57600080fd5b50511580613baa575060145460ff165b613bfb576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b6000613c05611ac1565b600c54909150613c339073ffffffffffffffffffffffffffffffffffffffff1633308963ffffffff614d5716565b613c3e600085613f28565b50613c5b8161100688670de0b6b3a764000063ffffffff61310016565b9250613c673384614dec565b613c72338483613866565b50601154811115611466576011559392505050565b6000600a600181548110613c9757fe5b9060005260206000200154600a600081548110613cb057fe5b9060005260206000200154840181613cc457fe5b0490506000805a9050600a600281548110613cdb57fe5b90600052602060002001548110613d2b57600a600381548110613cfa57fe5b9060005260206000200154600a600281548110613d1357fe5b9060005260206000200154820381613d2757fe5b0491505b81831115613d37578192505b8215613ea05773ffffffffffffffffffffffffffffffffffffffff8416301415613def576eb3f879cb30fe243b4dfee438691c0473ffffffffffffffffffffffffffffffffffffffff16636366b936846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613dbd57600080fd5b505af1158015613dd1573d6000803e3d6000fd5b505050506040513d6020811015613de757600080fd5b50613ea09050565b604080517f079d229f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024810185905290516eb3f879cb30fe243b4dfee438691c049163079d229f9160448083019260209291908290030181600087803b158015613e7357600080fd5b505af1158015613e87573d6000803e3d6000fd5b505050506040513d6020811015613e9d57600080fd5b50505b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff8216613efb5760405162461bcd60e51b815260040180806020018281038252602281526020018061582e6022913960400191505060405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff166000908152602091909152604090205460ff1690565b60095460009060ff1615613f83576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600d54604080517f7ff9b596000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691637ff9b596916004808301926020929190829003018186803b158015613fee57600080fd5b505afa158015614002573d6000803e3d6000fd5b505050506040513d602081101561401857600080fd5b505160115490915081101580614030575060145460ff165b614081576040805162461bcd60e51b815260206004820152601e60248201527f5061757365643a2069546f6b656e207072696365206465637265617365640000604482015290519081900360640190fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd644f726040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156140eb57600080fd5b505af11580156140ff573d6000803e3d6000fd5b505050506040513d602081101561411557600080fd5b50511580614125575060145460ff165b614176576040805162461bcd60e51b815260206004820152601b60248201527f5061757365643a205553445420696e74726f6475636564206665650000000000604482015290519081900360640190fd5b600e54604080517f65ed6e23000000000000000000000000000000000000000000000000000000008152905160609273ffffffffffffffffffffffffffffffffffffffff16916365ed6e23916004808301926000929190829003018186803b1580156141e157600080fd5b505afa1580156141f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561423c57600080fd5b810190808051604051939291908464010000000082111561425c57600080fd5b90830190602082018581111561427157600080fd5b825186602082028301116401000000008211171561428e57600080fd5b82525081516020918201928201910280838360005b838110156142bb5781810151838201526020016142a3565b5050505090500160405250505090506000601680549050825114905080156143375760005b6016548110806142ee575081155b15614335578281815181106142ff57fe5b60200260200101516016828154811061431457fe5b90600052602060002001541461432d5760009150614335565b6001016142e0565b505b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b1580156143a857600080fd5b505afa1580156143bc573d6000803e3d6000fd5b505050506040513d60208110156143d257600080fd5b505190508180156143e1575080155b156143f257600094505050506146c9565b8015614499576016541580156144055750855b1561441f57825161441d90601690602086019061564a565b505b614499601580548060200260200160405190810160405280929190818152602001828054801561448557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161445a575b50505050506144948584614f03565b614fe9565b85806144a25750815b156144b357600094505050506146c9565b60608060006144c061335f565b92509250925060606144d28783614f03565b905060606000806144e48787866150b2565b92509250925080614510576144fb60166000615685565b895161450e9060169060208d019061564a565b505b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561458157600080fd5b505afa158015614595573d6000803e3d6000fd5b505050506040513d60208110156145ab57600080fd5b505190506001811180156145bf5750600183115b156146b957606084516040519080825280602002602001820160405280156145f1578160200160208202803883390190505b50905060005b85518110156146365761461785611006620186a08985815181106111d157fe5b82828151811061462357fe5b60209081029190910101526001016145f7565b5060606146438284614f03565b90506146b660158054806020026020016040519081016040528092919081815260200182805480156146ab57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311614680575b505050505082614fe9565b50505b60019c5050505050505050505050505b6011548111156123b95760115592915050565b6146ed60088263ffffffff6153d916565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61474260088263ffffffff61546b16565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b600082614792576117e8565b6147b973ffffffffffffffffffffffffffffffffffffffff8516868563ffffffff6131a216565b8473ffffffffffffffffffffffffffffffffffffffff166395a2251f836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561483857600080fd5b505af115801561484c573d6000803e3d6000fd5b505050506040513d602081101561486257600080fd5b505195945050505050565b3360009081526018602052604081205481614886611ac1565b905060008211801561489757508482115b156148a0578491505b336000908152601760205260408120546148f290670de0b6b3a764000090611006906148e2906148d68b8963ffffffff614d1516565b9063ffffffff61310016565b613973878763ffffffff61310016565b90506000614912670de0b6b3a7640000611006898663ffffffff61310016565b9050818110156149285785945050505050610e65565b600061493a828463ffffffff614d1516565b9050600061495a620186a06110066013548561310090919063ffffffff16565b601054600c5491925061498d9173ffffffffffffffffffffffffffffffffffffffff90811691168363ffffffff6131a216565b336000908152601860205260409020546149ad908763ffffffff614d1516565b336000908152601860205260409020556149cd838263ffffffff614d1516565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116614a2c5760405162461bcd60e51b815260040180806020018281038252602681526020018061572f6026913960400191505060405180910390fd5b60075460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008183614b095760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561382357818101518382015260200161380b565b506000838581614b1557fe5b0495945050505050565b614b3e8273ffffffffffffffffffffffffffffffffffffffff16615517565b614b8f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b60208310614bf857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614bbb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614c5a576040519150601f19603f3d011682016040523d82523d6000602084013e614c5f565b606091505b509150915081614cb6576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115614d0f57808060200190516020811015614cd257600080fd5b5051614d0f5760405162461bcd60e51b815260040180806020018281038252602a8152602001806158ba602a913960400191505060405180910390fd5b50505050565b600061315983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506137cf565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052614d0f908590614b1f565b73ffffffffffffffffffffffffffffffffffffffff8216614e54576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254614e67908263ffffffff6135d816565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054614ea0908263ffffffff6135d816565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6060808351604051908082528060200260200182016040528015614f31578160200160208202803883390190505b509050600080805b8651811015614fde576001875103811415614f7b57614f5e868363ffffffff614d1516565b848281518110614f6a57fe5b602002602001018181525050614fd6565b614fa8620186a0611006898481518110614f9157fe5b60200260200101518961310090919063ffffffff16565b9250614fba828463ffffffff6135d816565b915082848281518110614fc957fe5b6020026020010181815250505b600101614f39565b509195945050505050565b80518251146150295760405162461bcd60e51b815260040180806020018281038252602781526020018061579d6027913960400191505060405180910390fd5b6000805b8251811015614d0f5782818151811061504257fe5b60200260200101519150816000141561505a576150aa565b6150a8600b600086848151811061506d57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260400160002054168361554e565b505b60010161502d565b6060600080835185511461510d576040805162461bcd60e51b815260206004820152601160248201527f4c656e67746873206e6f7420657175616c000000000000000000000000000000604482015290519081900360640190fd5b8451604051908082528060200260200182016040528015615138578160200160208202803883390190505b5092506000808080805b89518110156153cb578a818151811061515757fe5b6020026020010151915088818151811061516d57fe5b6020026020010151925089818151811061518357fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8085166000908152600b90935260409092205490911695509350828411156153725760008882815181106151d457fe5b602090810291909101015260006151f1858563ffffffff614d1516565b905060008673ffffffffffffffffffffffffffffffffffffffff1663743753596040518163ffffffff1660e01b815260040160206040518083038186803b15801561523b57600080fd5b505afa15801561524f573d6000803e3d6000fd5b505050506040513d602081101561526557600080fd5b505190508181101561527957600197508091505b61536a600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856125348a73ffffffffffffffffffffffffffffffffffffffff166302bbce466040518163ffffffff1660e01b815260040160206040518083038186803b15801561532657600080fd5b505afa15801561533a573d6000803e3d6000fd5b505050506040513d602081101561535057600080fd5b505161100687670de0b6b3a764000063ffffffff61310016565b5050506153c3565b615382838563ffffffff614d1516565b88828151811061538e57fe5b6020026020010181815250506153c08882815181106153a957fe5b6020026020010151886135d890919063ffffffff16565b96505b600101615142565b505050505093509350939050565b6153e38282613ea7565b61541e5760405162461bcd60e51b81526004018080602001828103825260218152602001806157c46021913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6154758282613ea7565b156154c7576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff1660009081526020919091526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906117e85750141592915050565b60008161555a57610e65565b600c546155849073ffffffffffffffffffffffffffffffffffffffff16848463ffffffff6131a216565b8273ffffffffffffffffffffffffffffffffffffffff16631249c58b6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156155cc57600080fd5b505af11580156155e0573d6000803e3d6000fd5b505050506040513d60208110156155f657600080fd5b50519392505050565b82805482825590600052602060002090810192821561563a579160200282015b8281111561563a57823582559160200191906001019061561f565b5061564692915061569f565b5090565b82805482825590600052602060002090810192821561563a579160200282015b8281111561563a57825182559160200191906001019061566a565b50805460008255906000526020600020908101906117d891905b610e4a91905b8082111561564657600081556001016156a556fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416c6c20746f6b656e73206c656e67746820213d20616c6c6f636174696f6e73206c656e677468526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f206164647265737345524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7231582051c4fdcd9f1bbf5db6b87ac9afb84770f1f76dfe1400ee5ff128ff170945c92964736f6c63430005100032

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

000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000012000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000f650c3d88d12db855b8bf7d11be6c55a4e07dcc90000000000000000000000008326645f3aa6de6420102fdb7da9e3a91855045b0000000000000000000000002403457ce59e56dd69d2fc4f22e77d7ab180deb1000000000000000000000000aefb1325a2c1756bc3fcc516d6c2cf947d225358000000000000000000000000d4d7e65a66850a19680802096896a31866131a9b000000000000000000000000cdd7db5c25f0de4e3194f56456d504a03676a8c9000000000000000000000000000000000000000000000000000000000000001749646c6555534454207633205b4d6178207969656c645d000000000000000000000000000000000000000000000000000000000000000000000000000000000d69646c65555344545969656c6400000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): IdleUSDT v3 [Max yield]
Arg [1] : _symbol (string): idleUSDTYield
Arg [2] : _decimals (uint8): 18
Arg [3] : _token (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [4] : _cToken (address): 0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9
Arg [5] : _iToken (address): 0x8326645f3Aa6De6420102Fdb7Da9E3a91855045B
Arg [6] : _rebalancer (address): 0x2403457Ce59e56Dd69d2Fc4F22e77d7AB180dEb1
Arg [7] : _priceCalculator (address): 0xAefb1325A2C1756Bc3fcc516D6C2CF947D225358
Arg [8] : _idleCompound (address): 0xD4d7E65A66850a19680802096896a31866131a9b
Arg [9] : _idleFulcrum (address): 0xCDD7DB5c25f0de4E3194F56456D504a03676a8C9

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [3] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [4] : 000000000000000000000000f650c3d88d12db855b8bf7d11be6c55a4e07dcc9
Arg [5] : 0000000000000000000000008326645f3aa6de6420102fdb7da9e3a91855045b
Arg [6] : 0000000000000000000000002403457ce59e56dd69d2fc4f22e77d7ab180deb1
Arg [7] : 000000000000000000000000aefb1325a2c1756bc3fcc516d6c2cf947d225358
Arg [8] : 000000000000000000000000d4d7e65a66850a19680802096896a31866131a9b
Arg [9] : 000000000000000000000000cdd7db5c25f0de4e3194f56456d504a03676a8c9
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [11] : 49646c6555534454207633205b4d6178207969656c645d000000000000000000
Arg [12] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [13] : 69646c65555344545969656c6400000000000000000000000000000000000000


Deployed Bytecode Sourcemap

52837:29915:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52837:29915:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53317:25;;;:::i;:::-;;;;;;;;;;;;;;;;;;;18593:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;18593:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12136:152;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12136:152:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;54634:48;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54634:48:0;;;;:::i;:::-;;;;;;;;;;;;;;;;59375:95;;;:::i;:::-;;11157:91;;;:::i;66532:617::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66532:617:0;;:::i;61677:541::-;;;:::i;62330:348::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62330:348:0;;;;;;;;;;;;;;;;;;:::i;51302:84::-;;;:::i;19445:83::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;60165:111;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;60165:111:0;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;60165:111:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;60165:111:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;60165:111:0;;-1:-1:-1;60165:111:0;-1:-1:-1;60165:111:0;:::i;54384:35::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54384:35:0;;:::i;13473:210::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13473:210:0;;;;;;;;;:::i;53646:28::-;;;:::i;64088:222::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;64088:222:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;64088:222:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;64088:222:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;64088:222:0;;-1:-1:-1;64088:222:0;-1:-1:-1;64088:222:0;:::i;27690:120::-;;;:::i;53192:21::-;;;:::i;53482:25::-;;;:::i;70047:179::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;70047:179:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;70047:179:0;;;;;;;;;;;;;;;;;;;;53066:51;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;53066:51:0;;;;:::i;25169:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25169:109:0;;;;:::i;26897:78::-;;;:::i;57548:444::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57548:444:0;;;;:::i;69189:117::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;69189:117:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;69189:117:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;69189:117:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;69189:117:0;;-1:-1:-1;69189:117:0;-1:-1:-1;69189:117:0;:::i;59652:128::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59652:128:0;;:::i;57236:163::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57236:163:0;;;;:::i;25386:79::-;;;:::i;11311:110::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11311:110:0;;;;:::i;22825:140::-;;;:::i;69535:85::-;;;:::i;60402:482::-;;;:::i;58961:104::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58961:104:0;;;;:::i;25286:92::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25286:92:0;;;;:::i;27477:118::-;;;:::i;59890:163::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59890:163:0;;;;:::i;53406:30::-;;;:::i;22014:79::-;;;:::i;22380:94::-;;;:::i;18795:87::-;;;:::i;54117:22::-;;;:::i;14186:261::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;14186:261:0;;;;;;;;;:::i;62682:214::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62682:214:0;;;;;;;;;:::i;54537:32::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54537:32:0;;:::i;61080:480::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61080:480:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61080:480:0;;;;;;;;;;;;;;;;;;;54301:32;;;:::i;63527:242::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63527:242:0;;;;;;;;;:::i;65036:1188::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;65036:1188:0;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;65036:1188:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;65036:1188:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;65036:1188:0;;-1:-1:-1;65036:1188:0;-1:-1:-1;65036:1188:0;:::i;54213:26::-;;;:::i;59174:120::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59174:120:0;;;;:::i;67768:653::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;67768:653:0;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;67768:653:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;67768:653:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;67768:653:0;;-1:-1:-1;67768:653:0;-1:-1:-1;67768:653:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;54907:47;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54907:47:0;;;;:::i;68749:132::-;;;:::i;11855:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11855:134:0;;;;;;;;;;;:::i;53951:18::-;;;:::i;58185:604::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58185:604:0;;;;;;;;;;;:::i;53590:30::-;;;:::i;23120:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23120:109:0;;;;:::i;53144:20::-;;;:::i;53317:25::-;;;;;;:::o;18593:83::-;18663:5;18656:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18630:13;;18656:12;;18663:5;;18656:12;;18663:5;18656:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18593:83;;:::o;12136:152::-;12202:4;12219:39;12228:12;:10;:12::i;:::-;12242:7;12251:6;12219:8;:39::i;:::-;-1:-1:-1;12276:4:0;12136:152;;;;;:::o;54634:48::-;;;;;;;;;;;;;:::o;59375:95::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59437:20;:27;;;;;;;;59375:95::o;11157:91::-;11228:12;;11157:91;:::o;66532:617::-;20925:13;:18;;20942:1;20925:18;;;;;:13;66643;:11;:13::i;:::-;66622:34;-1:-1:-1;66665:20:0;;;66720:387;66744:18;:25;66740:29;;66720:387;;;66802:18;66821:1;66802:21;;;;;;;;;;;;;;;;;;;66844:45;;;;;;66883:4;66844:45;;;;;;66802:21;;;;;-1:-1:-1;66802:21:0;;66844:30;;:45;;;;;;;;;;66802:21;66844:45;;;5:2:-1;;;;30:1;27;20:12;5:2;66844:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66844:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66844:45:0;;-1:-1:-1;66904:12:0;66900:51;;66931:8;;66900:51;66961:136;67007:10;67030:36;67055:10;67030:20;:7;67042;67030:20;:11;:20;:::i;:::-;:24;:36;:24;:36;:::i;:::-;66961:33;;;;:136;;:33;:136;:::i;:::-;66771:3;;66720:387;;;;67117:26;67123:10;67135:7;67117:5;:26::i;:::-;21001:1;;;21037:13;;21021:12;:29;21013:73;;;;;-1:-1:-1;;;21013:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;66532:617;;:::o;61677:541::-;61729:14;61757:24;61783:13;61800:24;:22;:24::i;:::-;61754:70;;-1:-1:-1;61754:70:0;-1:-1:-1;61833:15:0;;-1:-1:-1;61833:15:0;;61880:333;61904:18;:25;61900:29;;61880:333;;;61951:7;61959:1;61951:10;;;;;;;;;;;;;;61965:1;61951:15;61947:54;;;61981:8;;61947:54;62038:16;:39;62055:18;62074:1;62055:21;;;;;;;;;;;;;;;;;;;;;;;;62038:39;;;;;;;;;;;;;;;;;62021:66;;;;;;;62038:39;;;62021:64;;:66;;;;;62055:21;62021:66;;;;;;62038:39;62021:66;;;5:2:-1;;;;30:1;27;20:12;5:2;62021:66:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62021:66:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62021:66:0;62107:10;;62021:66;;-1:-1:-1;62107:33:0;;62134:5;;62107:22;;62122:6;;62107:7;;62115:1;;62107:10;;;;;;;;;;;;:14;;:22;;;;:::i;:33::-;62098:42;-1:-1:-1;62160:43:0;62171:31;62195:6;62171:19;:7;62098:42;62171:19;:11;:19;:::i;:31::-;62160:6;;:43;:10;:43;:::i;:::-;62151:52;;61880:333;61931:3;;61880:333;;;;61677:541;;;;;:::o;62330:348::-;62419:4;62432:36;62442:6;62450:9;62461:6;62432:9;:36::i;:::-;62475:115;62484:6;62492:10;62504:85;62538:6;62504:85;;;;;;;;;;;;;;;;;:29;62514:6;62522:10;62504:9;:29::i;:::-;:33;:85;;:33;:85;:::i;:::-;62475:8;:115::i;:::-;62632:21;;;;;;;:13;:21;;;;;;62597:57;;62613:9;;62624:6;;62597:15;:57::i;:::-;-1:-1:-1;62668:4:0;62330:348;;;;;:::o;51302:84::-;51343:42;51302:84;:::o;19445:83::-;19511:9;;;;19445:83;:::o;60165:111::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60249:21;:10;60262:8;;60249:21;:::i;:::-;;60165:111;;:::o;54384:35::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54384:35:0;:::o;13473:210::-;13553:4;13570:83;13579:12;:10;:12::i;:::-;13593:7;13602:50;13641:10;13602:11;:25;13614:12;:10;:12::i;:::-;13602:25;;;;;;;;;;;;;;;;;;-1:-1:-1;13602:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;53646:28::-;;;;:::o;64088:222::-;20925:13;:18;;20942:1;20925:18;;;;;64220:20;;64199:4;64220:20;51528:9;64280:16;;;64294:1;64280:16;;;;;;;;;51503:34;;-1:-1:-1;64256:48:0;;64271:7;;64256:14;:48::i;:::-;64249:55;;51552:50;51586:9;51569:14;:26;51597:4;51552:16;:50::i;:::-;21001:1;;21037:13;;21021:12;:29;21013:73;;;;;-1:-1:-1;;;21013:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;64088:222;;;;;;:::o;27690:120::-;25066:22;25075:12;:10;:12::i;:::-;25066:8;:22::i;:::-;25058:83;;;;-1:-1:-1;;;25058:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27333:7;;;;27325:40;;;;;-1:-1:-1;;;27325:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;27749:7;:15;;;;;;27780:22;27789:12;:10;:12::i;:::-;27780:22;;;;;;;;;;;;;;;;;;27690:120::o;53192:21::-;;;;;;:::o;53482:25::-;;;;;;:::o;70047:179::-;70108:31;70141:24;70167:13;70196:24;:22;:24::i;:::-;70189:31;;;;;;70047:179;;;:::o;53066:51::-;;;;;;;;;;;;;;;:::o;25169:109::-;25225:4;25249:21;:8;25262:7;25249:21;:12;:21;:::i;26897:78::-;26960:7;;;;26897:78;:::o;57548:444::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57643:30;;;57635:52;;;;;-1:-1:-1;;;57635:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;57701:20;;;;;;;57700:21;;:123;;-1:-1:-1;57726:30:0;;;;;;;:12;:30;;;;;;:35;;;;:96;;-1:-1:-1;57771:30:0;;;;;;;:12;:30;;;;;;53872:16;57765:3;:36;;;;:57;57726:96;57696:246;;;57836:15;:34;;;;;;;;;;;;;-1:-1:-1;57881:30:0;;;:12;:30;;;;;:34;57926:7;;57696:246;57950:30;;;;;;;:12;:30;;;;;57983:3;57950:36;;22283:1;57548:444;:::o;69189:117::-;69260:4;69280:20;69291:1;69294:5;69280:10;:20::i;:::-;69273:27;69189:117;-1:-1:-1;;;;69189:117:0:o;59652:128::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53748:5;59723:4;:15;;59715:40;;;;;-1:-1:-1;;;59715:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59764:3;:10;59652:128::o;57236:163::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57321:25;;;57313:47;;;;;-1:-1:-1;;;57313:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;57369:10;:24;;;;;;;;;;;;;;;57236:163::o;25386:79::-;25430:27;25444:12;:10;:12::i;:::-;25430:13;:27::i;:::-;25386:79::o;11311:110::-;11395:18;;11368:7;11395:18;;;;;;;;;;;;11311:110::o;22825:140::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22908:6;;22887:40;;22924:1;;22887:40;22908:6;;22887:40;;22924:1;;22887:40;22938:6;:19;;;;;;22825:140::o;69535:85::-;69574:4;69594:20;69605:1;69608:5;69594:10;:20::i;:::-;69587:27;;69535:85;:::o;60402:482::-;60455:13;60479:42;60538:18;:25;;;;60524:40;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;60524:40:0;-1:-1:-1;60479:85:0;-1:-1:-1;60578:9:0;60573:147;60597:18;:25;60593:29;;60573:147;;;60671:16;:39;60688:18;60707:1;60688:21;;;;;;;;;;;;;;;;;;;;;;;;60671:39;;;;;;;;;;;;;;;;60640:28;;60671:39;;;60640:25;;60666:1;;60640:28;;;;;;:70;;;;:28;;;;;;;;;;;:70;60624:3;;60573:147;;;-1:-1:-1;60756:15:0;;;;60736:47;60794:13;:11;:13::i;:::-;60817:4;60824:18;60844:25;60736:142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;60736:142:0;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;60736:142:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60736:142:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60736:142:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60736:142:0;;60402:482;-1:-1:-1;;60402:482:0:o;58961:104::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59035:10;:24;;;;;;;;;;;;;58961:104::o;25286:92::-;25066:22;25075:12;:10;:12::i;25066:22::-;25058:83;;;;-1:-1:-1;;;25058:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25351:19;25362:7;25351:10;:19::i;27477:118::-;25066:22;25075:12;:10;:12::i;25066:22::-;25058:83;;;;-1:-1:-1;;;25058:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27134:7;;;;27133:8;27125:37;;;;;-1:-1:-1;;;27125:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;27537:7;:14;;;;27547:4;27537:14;;;27567:20;27574:12;:10;:12::i;59890:163::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59975:25;;;59967:47;;;;;-1:-1:-1;;;59967:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60023:10;:24;;;;;;;;;;;;;;;59890:163::o;53406:30::-;;;;;;:::o;22014:79::-;22079:6;;;;22014:79;:::o;22380:94::-;22460:6;;22420:4;;22460:6;;22444:12;:10;:12::i;:::-;:22;;;22437:29;;22380:94;:::o;18795:87::-;18867:7;18860:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18834:13;;18860:14;;18867:7;;18860:14;;18867:7;18860:14;;;;;;;;;;;;;;;;;;;;;;;;54117:22;;;;;;:::o;14186:261::-;14271:4;14288:129;14297:12;:10;:12::i;:::-;14311:7;14320:96;14359:15;14320:96;;;;;;;;;;;;;;;;;:11;:25;14332:12;:10;:12::i;:::-;14320:25;;;;;;;;;;;;;;;;;;-1:-1:-1;14320:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;62682:214::-;62751:4;62764:40;62774:10;62786:9;62797:6;62764:9;:40::i;:::-;62860:10;62846:25;;;;:13;:25;;;;;;62811:61;;62827:9;;62838:6;;62811:15;:61::i;54537:32::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54537:32:0;:::o;61080:480::-;61132:26;61160:21;61192:17;61244:18;:25;;;;61230:40;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;61230:40:0;-1:-1:-1;61300:18:0;:25;61286:40;;;;;;;;;;;;;;;;61218:52;;-1:-1:-1;61286:40:0;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;61286:40:0;-1:-1:-1;61279:47:0;-1:-1:-1;61340:9:0;61335:220;61359:18;:25;61355:29;;61335:220;;;61414:18;61433:1;61414:21;;;;;;;;;;;;;;;;;;;;;;;;;61402:33;;61461:9;61446;61456:1;61446:12;;;;;;;;:24;;;;:12;;;;;;;;;;:24;;;;61508:27;;;;;;;:16;:27;;;;;;;;61491:54;;;;;;;61508:27;;;61491:52;;:54;;;;;61446:12;;61491:54;;;;;;61508:27;61491:54;;;5:2:-1;;;;30:1;27;20:12;5:2;61491:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61491:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61491:54:0;61481:7;;:4;;61486:1;;61481:7;;;;;;;;;;;;;;;:64;61386:3;;61335:220;;;;61080:480;;;:::o;54301:32::-;;;;;;;;;:::o;63527:242::-;20925:13;:18;;20942:1;20925:18;;;;;63665:20;;63644:4;63665:20;51528:9;63725:16;;;63739:1;63725:16;;;;;;;;51503:34;;-1:-1:-1;63701:62:0;;63716:7;;63743:19;63701:14;:62::i;:::-;63694:69;;51552:50;51586:9;51569:14;:26;51597:4;51552:16;:50::i;:::-;21001:1;;21037:13;;21021:12;:29;21013:73;;;;;-1:-1:-1;;;21013:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;63527:242;;;;;:::o;65036:1188::-;20925:13;:18;;20942:1;20925:18;;;;;65160:22;;;;65217:557;65241:18;:25;65237:29;;65217:557;;;65301:18;65320:1;65301:21;;;;;;;;;;;;;;;;;;;65294:54;;;;;;65342:4;65294:54;;;;;;65301:21;;;;;65294:39;;:54;;;;;;;;;;65301:21;65294:54;;;5:2:-1;;;;30:1;27;20:12;5:2;65294:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65294:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65294:54:0;;-1:-1:-1;65363:12:0;65359:51;;65390:8;;65359:51;65437:327;65468:285;65504:16;:39;65521:18;65540:1;65521:21;;;;;;;;;;;;;;;;;;;;;;;;65504:39;;;;;;;;;;;;;;;;65558:18;:21;;65504:39;;;;;65558:18;65577:1;;65558:21;;;;;;;;;;;;;;;;;;65653:39;65678:13;:11;:13::i;:::-;65653:20;:7;65665;65653:20;:11;:20;:::i;:39::-;65735:4;65468:21;:285::i;:::-;65437:14;;:327;:18;:327;:::i;:::-;65420:344;;65217:557;65268:3;;65217:557;;;;65784:26;65790:10;65802:7;65784:5;:26::i;:::-;65829:1;65823:3;;:7;:35;;;;-1:-1:-1;65834:10:0;;:24;:10;:24;;65823:35;65819:111;;;65888:32;65896:7;65905:14;65888:7;:32::i;:::-;65871:49;;65819:111;65995:5;;65988:54;;65995:5;;66015:10;66027:14;65988:54;:26;:54;:::i;:::-;66057:4;:11;;;:13;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66057:13:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66057:13:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66057:13:0;;:69;;;66111:15;;66088:6;;;;;;;;;;;66074:32;;;:34;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66074:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66074:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66074:34:0;:52;66057:69;:87;;;;66130:14;66057:87;66053:135;;;-1:-1:-1;66157:21:0;;66053:135;66198:20;66209:1;66212:5;66198:10;:20::i;:::-;;21001:1;;21037:13;;21021:12;:29;21013:73;;;;;-1:-1:-1;;;21013:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;65036:1188;;;;;;;:::o;54213:26::-;;;;;;;;;:::o;59174:120::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59256:14;:32;;;;;;;;;;;;;;;;;59174:120::o;67768:653::-;27134:7;;67917:4;;;;27134:7;;27133:8;27125:37;;;;;-1:-1:-1;;;27125:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56676:6;;56662:34;;;;;;;;56640:19;;56676:6;;;56662:32;;:34;;;;;;;;;;;;;;56676:6;56662:34;;;5:2:-1;;;;30:1;27;20:12;5:2;56662:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56662:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56662:34:0;56734:15;;56662:34;;-1:-1:-1;56719:30:0;;;;:44;;-1:-1:-1;56753:10:0;;;;56719:44;56703:108;;;;;-1:-1:-1;;;56703:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56976:5;;;;;;;;;;;56971:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56971:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56971:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56971:29:0;:34;;:48;;-1:-1:-1;57009:10:0;;;;56971:48;56955:109;;;;;-1:-1:-1;;;56955:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;67957:14;;;;;;;67956:15;67948:59;;;;;-1:-1:-1;;;67948:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68016:18;68037:11;:9;:11::i;:::-;68127:10;;68110:80;;;;;;;;;;;;;;;;;;68016:32;;-1:-1:-1;68127:10:0;;;;;68110:43;;68154:15;;;;68171:18;;68110:80;;;;;;;;68154:15;68110:80;;;;68154:15;68110:80;1:33:-1;99:1;81:16;;;74:27;137:4;117:14;133:9;113:30;157:16;;;68110:80:0;;;;;;;;;;;;;;;-1:-1:-1;68110:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;68110:80:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;68110:80:0;;;;68199:18;68220:20;68231:1;68234:5;68220:10;:20::i;:::-;68199:41;;68249:28;68280:11;:9;:11::i;:::-;68249:42;;68331:10;68308:20;:33;68300:62;;;;;-1:-1:-1;;;68300:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68379:13;;-1:-1:-1;68394:20:0;-1:-1:-1;;56848:15:0;;56834:11;:29;56830:81;;;56874:15;:29;;;56830:81;27173:1;67768:653;;;;;:::o;54907:47::-;;;;;;;;;;;;;:::o;68749:132::-;68833:4;68807:10;51503:22;51528:9;51503:34;;68855:20;68866:1;68869:5;68855:10;:20::i;:::-;68848:27;;51552:50;51586:9;51569:14;:26;51597:4;51552:16;:50::i;:::-;68749:132;;;:::o;11855:134::-;11954:18;;;;11927:7;11954:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;11855:134::o;53951:18::-;;;;:::o;58185:604::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58288:20;;;;;;;:46;;-1:-1:-1;58312:22:0;;;;;58288:46;58280:73;;;;;-1:-1:-1;;;58280:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;58369:20;;;;;;;58368:21;;:107;;-1:-1:-1;58394:22:0;;;;;;;:12;:22;;;;;;:27;;;;:80;;-1:-1:-1;58431:22:0;;;;;;;:12;:22;;;;;;53872:16;58425:3;:28;;;;:49;58394:80;58364:381;;;58540:38;:24;;;58576:1;58540:24;;;:16;:24;;;;;;;58536:100;;58593:18;27:10:-1;;39:1;23:18;;45:23;;-1:-1;58593:31:0;;;;;;;;;;;;;;;;58536:100;58646:24;;;;;;;;:16;:24;;;;;;;;:35;;;;;;;;;;;;58692:22;;;:12;:22;;;;;:26;58729:7;;58364:381;58755:22;;;;;;:12;:22;;;;;58780:3;58755:28;;-1:-1:-1;58185:604:0:o;53590:30::-;;;;:::o;23120:109::-;22226:9;:7;:9::i;:::-;22218:54;;;;;-1:-1:-1;;;22218:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23193:28;23212:8;23193:18;:28::i;53144:20::-;;;;;;:::o;3738:98::-;3818:10;3738:98;:::o;17118:338::-;17212:19;;;17204:68;;;;-1:-1:-1;;;17204:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17291:21;;;17283:68;;;;-1:-1:-1;;;17283:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17364:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;17416:32;;;;;;;;;;;;;;;;;17118:338;;;:::o;6361:471::-;6419:7;6664:6;6660:47;;-1:-1:-1;6694:1:0;6687:8;;6660:47;6731:5;;;6735:1;6731;:5;:1;6755:5;;;;;:10;6747:56;;;;-1:-1:-1;;;6747:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6823:1;6361:471;-1:-1:-1;;;6361:471:0:o;7300:132::-;7358:7;7385:39;7389:1;7392;7385:39;;;;;;;;;;;;;;;;;:3;:39::i;31607:176::-;31716:58;;;31739:14;31716:58;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;31716:58:0;;;;;;;;25:18:-1;;61:17;;31716:58:0;182:15:-1;31739:23:0;179:29:-1;160:49;;31690:85:0;;31709:5;;31690:18;:85::i;16330:348::-;16406:21;;;16398:67;;;;-1:-1:-1;;;16398:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16499:68;16522:6;16499:68;;;;;;;;;;;;;;;;;:18;;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;16478:18;;;:9;:18;;;;;;;;;;:89;16593:12;;:24;;16610:6;16593:24;:16;:24;:::i;:::-;16578:12;:39;16633:37;;;;;;;;16659:1;;16633:37;;;;;;;;;;;;;16330:348;;:::o;80430:918::-;80492:31;80525:24;80551:13;80658:18;:25;;;;80644:40;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;80644:40:0;-1:-1:-1;80717:18:0;:25;80703:40;;;;;;;;;;;;;;;;80627:57;;-1:-1:-1;80703:40:0;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;80703:40:0;-1:-1:-1;80693:50:0;-1:-1:-1;80754:20:0;;;80816:413;80840:18;:25;80836:29;;80816:413;;;80898:18;80917:1;80898:21;;;;;;;;;;;;;;;;;;;;;;;;;80883:36;;80950:12;80930:14;80945:1;80930:17;;;;;;;;:32;;;;:17;;;;;;;;;;:32;;;;81007:30;;;;;;;:16;:30;;;;;;;;80990:66;;;;;;;81007:30;;;80990:64;;:66;;;;;80930:17;;80990:66;;;;;;81007:30;80990:66;;;5:2:-1;;;;30:1;27;20:12;5:2;80990:66:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;80990:66:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;80990:66:0;81111:45;;;;;;81150:4;81111:45;;;;;;80990:66;;-1:-1:-1;81080:99:0;;81172:6;;81080:87;;81111:30;;;;;;:45;;;;;80990:66;;81111:45;;;;;;;:30;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;81111:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81111:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81111:45:0;81080:14;;:87;:18;:87;:::i;:99::-;81067:7;81075:1;81067:10;;;;;;;;;;;;;:112;;;;;81198:21;81208:7;81216:1;81208:10;;;;;;;;;;;;;;81198:5;:9;;:21;;;;:::i;:::-;81190:29;-1:-1:-1;80867:3:0;;80816:413;;;-1:-1:-1;;;80430:918:0;;;:::o;4989:181::-;5047:7;5079:5;;;5103:6;;;;5095:46;;;;;-1:-1:-1;;;5095:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;14937:471;15035:20;;;15027:70;;;;-1:-1:-1;;;15027:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15116:23;;;15108:71;;;;-1:-1:-1;;;15108:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15212;15234:6;15212:71;;;;;;;;;;;;;;;;;:17;;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;15192:17;;;;:9;:17;;;;;;;;;;;:91;;;;15317:20;;;;;;;:32;;15342:6;15317:32;:24;:32;:::i;:::-;15294:20;;;;:9;:20;;;;;;;;;;;;:55;;;;15365:35;;;;;;;15294:20;;15365:35;;;;;;;;;;;;;14937:471;;;:::o;5918:192::-;6004:7;6040:12;6032:6;;;;6024:29;;;;-1:-1:-1;;;6024:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6024:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6076:5:0;;;5918:192::o;74969:447::-;75055:3;;75051:92;;75094:17;;;;;;;:12;:17;;;;;;:26;;75116:3;75094:26;:21;:26;:::i;:::-;75074:17;;;;;;;:12;:17;;;;;:46;75129:7;;75051:92;75191:17;;;75151:18;75191:17;;;:12;:17;;;;;;75172:37;;:14;75204:3;75172:9;:14::i;:::-;:18;:37;:18;:37;:::i;:::-;75238:18;;;75216:19;75238:18;;;:13;:18;;;;;;75151:58;;-1:-1:-1;75284:19:0;75151:58;75299:3;75284:19;:14;:19;:::i;:::-;75263:40;-1:-1:-1;75331:79:0;75379:30;75398:10;75379:14;:5;75389:3;75379:14;:9;:14;:::i;:30::-;75331:43;75363:10;75331:27;:11;75347:10;75331:27;:15;:27;:::i;:43::-;:47;:79;:47;:79;:::i;:::-;75310:18;;;;;;;:13;:18;;;;;:100;-1:-1:-1;;;74969:447:0;;;:::o;70840:684::-;27134:7;;71015:20;;27134:7;;27133:8;27125:37;;;;;-1:-1:-1;;;27125:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56676:6;;56662:34;;;;;;;;56640:19;;56676:6;;;56662:32;;:34;;;;;;;;;;;;;;56676:6;56662:34;;;5:2:-1;;;;30:1;27;20:12;5:2;56662:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56662:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56662:34:0;56734:15;;56662:34;;-1:-1:-1;56719:30:0;;;;:44;;-1:-1:-1;56753:10:0;;;;56719:44;56703:108;;;;;-1:-1:-1;;;56703:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56976:5;;;;;;;;;;;56971:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56971:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56971:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56971:29:0;:34;;:48;;-1:-1:-1;57009:10:0;;;;56971:48;56955:109;;;;;-1:-1:-1;;;56955:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;71084:17;71104:12;:10;:12::i;:::-;71175:5;;71084:32;;-1:-1:-1;71168:66:0;;71175:5;;71199:10;71219:4;71226:7;71168:66;:30;:66;:::i;:::-;71321:34;71332:1;71335:19;71321:10;:34::i;:::-;-1:-1:-1;71381:34:0;71405:9;71381:19;:7;71393:6;71381:19;:11;:19;:::i;:34::-;71366:49;;71424:31;71430:10;71442:12;71424:5;:31::i;:::-;71466:52;71482:10;71494:12;71508:9;71466:15;:52::i;:::-;57073:1;56848:15;;56834:11;:29;56830:81;;;56874:15;:29;70840:684;;-1:-1:-1;;;70840:684:0:o;51614:809::-;51846:14;51892:10;51903:1;51892:13;;;;;;;;;;;;;;;;51875:10;51886:1;51875:13;;;;;;;;;;;;;;;;51864:8;:24;51863:42;;;;;;51846:59;;51912:21;51940:11;51954:9;51940:23;;52091:10;52102:1;52091:13;;;;;;;;;;;;;;;;52084:3;:20;52080:96;;52155:10;52166:1;52155:13;;;;;;;;;;;;;;;;52138:10;52149:1;52138:13;;;;;;;;;;;;;;;;52132:3;:19;52131:37;;;;;;52115:53;;52080:96;52197:13;52188:6;:22;52184:67;;;52230:13;52221:22;;52184:67;52263:10;;52259:159;;52288:21;;;52304:4;52288:21;52284:127;;;51343:42;52322:13;;;52336:6;52322:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52322:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;52322:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;52284:127:0;;-1:-1:-1;52284:127:0;;52370:31;;;;;;:17;:31;;;;;;;;;;;;;;51343:42;;52370:17;;:31;;;;;;;;;;;;;;-1:-1:-1;51343:42:0;52370:31;;;5:2:-1;;;;30:1;27;20:12;5:2;52370:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;52370:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;52284:127:0;51614:809;;;;;:::o;24434:203::-;24506:4;24531:21;;;24523:68;;;;-1:-1:-1;;;24523:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24609:20:0;;:11;:20;;;;;;;;;;;;;;;24434:203::o;71745:2960::-;27134:7;;71890:4;;27134:7;;27133:8;27125:37;;;;;-1:-1:-1;;;27125:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56676:6;;56662:34;;;;;;;;56640:19;;56676:6;;;56662:32;;:34;;;;;;;;;;;;;;56676:6;56662:34;;;5:2:-1;;;;30:1;27;20:12;5:2;56662:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56662:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56662:34:0;56734:15;;56662:34;;-1:-1:-1;56719:30:0;;;;:44;;-1:-1:-1;56753:10:0;;;;56719:44;56703:108;;;;;-1:-1:-1;;;56703:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56976:5;;;;;;;;;;;56971:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56971:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56971:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56971:29:0;:34;;:48;;-1:-1:-1;57009:10:0;;;;56971:48;56955:109;;;;;-1:-1:-1;;;56955:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72060:10;;72043:45;;;;;;;;71998:42;;72060:10;;;72043:43;;:45;;;;;72060:10;;72043:45;;;;;;;72060:10;72043:45;;;5:2:-1;;;;30:1;27;20:12;5:2;72043:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;72043:45:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;72043:45:0;80:15:-1;;;97:9;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;72043:45:0;;;;;;;;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;72043:45:0;;421:4:-1;412:14;;;;72043:45:0;;;;;412:14:-1;72043:45:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72043:45:0;;;;;;;;;;;71998:90;;72097:24;72160:15;:22;;;;72124:25;:32;:58;72097:85;;72195:19;72191:278;;;72232:9;72227:233;72251:15;:22;72247:26;;;:50;;;72278:19;72277:20;72247:50;72227:233;;;72343:25;72369:1;72343:28;;;;;;;;;;;;;;72321:15;72337:1;72321:18;;;;;;;;;;;;;;;;:50;72317:132;;72410:5;72388:27;;72430:5;;72317:132;72299:3;;72227:233;;;;72191:278;72502:5;;72495:38;;;;;;72527:4;72495:38;;;;;;72477:15;;72502:5;;;72495:23;;:38;;;;;;;;;;;;;;72502:5;72495:38;;;5:2:-1;;;;30:1;27;20:12;5:2;72495:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;72495:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72495:38:0;;-1:-1:-1;72546:19:0;:35;;;;-1:-1:-1;72569:12:0;;72546:35;72542:74;;;72601:5;72594:12;;;;;;;72542:74;72630:11;;72626:298;;72658:15;:22;:27;:50;;;;;72689:19;72658:50;72654:153;;;72752:43;;;;:15;;:43;;;;;:::i;:::-;;72654:153;72817:97;72834:18;72817:97;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72854:59;72878:25;72905:7;72854:23;:59::i;:::-;72817:16;:97::i;:::-;72938:19;:42;;;;72961:19;72938:42;72934:81;;;73000:5;72993:12;;;;;;;72934:81;73196:31;73229:24;73255:25;73284:24;:22;:24::i;:::-;73195:113;;;;;;73369:27;73399:69;73423:25;73450:17;73399:23;:69::i;:::-;73369:99;;73478:34;73514:19;73535:17;73556:53;73573:14;73589:7;73598:10;73556:16;:53::i;:::-;73477:132;;;;;;73769:12;73764:182;;73860:22;73867:15;;73860:22;:::i;:::-;73893:43;;;;:15;;:43;;;;;:::i;:::-;;73764:182;73984:5;;73977:38;;;;;;74009:4;73977:38;;;;;;73954:20;;73984:5;;;73977:23;;:38;;;;;;;;;;;;;;73984:5;73977:38;;;5:2:-1;;;;30:1;27;20:12;5:2;73977:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;73977:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;73977:38:0;;-1:-1:-1;74043:1:0;74028:16;;:35;;;;;74062:1;74048:11;:15;74028:35;74024:637;;;74157:32;74206:17;:24;74192:39;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;74192:39:0;-1:-1:-1;74157:74:0;-1:-1:-1;74247:9:0;74242:246;74266:17;:24;74262:1;:28;74242:246;;;74427:49;74464:11;74427:32;74452:6;74427:17;74445:1;74427:20;;;;;;;:49;74406:15;74422:1;74406:18;;;;;;;;;;;;;;;;;:70;74292:3;;74242:246;;;;74500:31;74534:54;74558:15;74575:12;74534:23;:54::i;:::-;74500:88;;74599:52;74616:18;74599:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74636:14;74599:16;:52::i;:::-;74024:637;;;74678:4;74671:11;;;;;;;;;;;;;57073:1;56848:15;;56834:11;:29;56830:81;;;56874:15;:29;71745:2960;;-1:-1:-1;;71745:2960:0:o;25603:130::-;25663:24;:8;25679:7;25663:24;:15;:24;:::i;:::-;25703:22;;;;;;;;;;;25603:130;:::o;25473:122::-;25530:21;:8;25543:7;25530:21;:12;:21;:::i;:::-;25567:20;;;;;;;;;;;25473:122;:::o;82339:410::-;82471:14;82500:12;82496:52;;82525:13;;82496:52;82628:50;:27;;;82656:12;82670:7;82628:50;:27;:50;:::i;:::-;82713:12;82696:37;;;82734:8;82696:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82696:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82696:47:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82696:47:0;;82339:410;-1:-1:-1;;;;;82339:410:0:o;75604:754::-;75721:10;75673:7;75708:24;;;:12;:24;;;;;;75673:7;75759:12;:10;:12::i;:::-;75739:32;;75793:1;75782:8;:12;:33;;;;;75809:6;75798:8;:17;75782:33;75778:73;;;75837:6;75826:17;;75778:73;75949:10;75859:20;75935:25;;;:13;:25;;;;;;75882:92;;75967:6;;75882:80;;75910:51;;:20;:6;75921:8;75910:20;:10;:20;:::i;:::-;:24;:51;:24;:51;:::i;:::-;75882:23;:8;75895:9;75882:23;:12;:23;:::i;:92::-;75859:115;-1:-1:-1;75981:15:0;75999:33;76025:6;75999:21;:6;76010:9;75999:21;:10;:21;:::i;:33::-;75981:51;;76053:12;76043:7;:22;76039:60;;;76083:8;76076:15;;;;;;;;76039:60;76105:12;76120:25;:7;76132:12;76120:25;:11;:25;:::i;:::-;76105:40;;76152:14;76169:25;76187:6;76169:13;76178:3;;76169:4;:8;;:13;;;;:::i;:25::-;76228:10;;76208:5;;76152:42;;-1:-1:-1;76201:46:0;;76228:10;76208:5;;;;76228:10;76152:42;76201:46;:26;:46;:::i;:::-;76294:10;76281:24;;;;:12;:24;;;;;;:38;;76310:8;76281:38;:28;:38;:::i;:::-;76267:10;76254:24;;;;:12;:24;;;;;:65;76333:19;:7;76345:6;76333:19;:11;:19;:::i;:::-;76326:26;75604:754;-1:-1:-1;;;;;;;;;75604:754:0:o;23335:229::-;23409:22;;;23401:73;;;;-1:-1:-1;;;23401:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23511:6;;23490:38;;;;;;;23511:6;;23490:38;;23511:6;;23490:38;23539:6;:17;;;;;;;;;;;;;;;23335:229::o;7962:345::-;8048:7;8150:12;8143:5;8135:28;;;;-1:-1:-1;;;8135:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;8135:28:0;;8174:9;8190:1;8186;:5;;;;;;;7962:345;-1:-1:-1;;;;;7962:345:0:o;33646:1114::-;34250:27;34258:5;34250:25;;;:27::i;:::-;34242:71;;;;;-1:-1:-1;;;34242:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;34387:12;34401:23;34436:5;34428:19;;34448:4;34428:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;139:12;;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;34428:25:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;34386:67:0;;;;34472:7;34464:52;;;;;-1:-1:-1;;;34464:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34533:17;;:21;34529:224;;34675:10;34664:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34664:30:0;34656:85;;;;-1:-1:-1;;;34656:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33646:1114;;;;:::o;5445:136::-;5503:7;5530:43;5534:1;5537;5530:43;;;;;;;;;;;;;;;;;:3;:43::i;31791:204::-;31918:68;;;31941:18;31918:68;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;31918:68:0;;;;;;;;25:18:-1;;61:17;;31918:68:0;182:15:-1;31941:27:0;179:29:-1;160:49;;31892:95:0;;31911:5;;31892:18;:95::i;15689:308::-;15765:21;;;15757:65;;;;;-1:-1:-1;;;15757:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15850:12;;:24;;15867:6;15850:24;:16;:24;:::i;:::-;15835:12;:39;15906:18;;;:9;:18;;;;;;;;;;;:30;;15929:6;15906:30;:22;:30;:::i;:::-;15885:18;;;:9;:18;;;;;;;;;;;:51;;;;15952:37;;;;;;;15885:18;;:9;;15952:37;;;;;;;;;;15689:308;;:::o;77368:638::-;77474:16;77499:27;77543:11;:18;77529:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;77529:33:0;-1:-1:-1;77499:63:0;-1:-1:-1;77569:19:0;;;77636:341;77660:11;:18;77656:1;:22;77636:341;;;77724:1;77703:11;:18;:22;77698:1;:27;77694:276;;;77754:27;:5;77764:16;77754:27;:9;:27;:::i;:::-;77738:10;77749:1;77738:13;;;;;;;;;;;;;:43;;;;;77694:276;;;77822:37;77852:6;77822:25;77832:11;77844:1;77832:14;;;;;;;;;;;;;;77822:5;:9;;:25;;;;:::i;:37::-;77808:51;-1:-1:-1;77889:33:0;:16;77808:51;77889:33;:20;:33;:::i;:::-;77870:52;;77949:11;77933:10;77944:1;77933:13;;;;;;;;;;;;;:27;;;;;77694:276;77680:3;;77636:341;;;-1:-1:-1;77990:10:0;;77368:638;-1:-1:-1;;;;;77368:638:0:o;76588:545::-;76790:15;:22;76765:14;:21;:47;76757:99;;;;-1:-1:-1;;;76757:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76865:18;;76892:236;76916:15;:22;76912:1;:26;76892:236;;;76967:15;76983:1;76967:18;;;;;;;;;;;;;;76954:31;;76998:10;77012:1;76998:15;76994:50;;;77026:8;;76994:50;77052:68;77072:16;:35;77089:14;77104:1;77089:17;;;;;;;;;;;;;;;;;;;77072:35;;;;;;;;;;;;;;;-1:-1:-1;77072:35:0;;;77109:10;77052:19;:68::i;:::-;;76892:236;76940:3;;76892:236;;78417:1586;78579:34;78622:19;78650:17;78708:10;:17;78690:7;:14;:35;78682:65;;;;;-1:-1:-1;;;78682:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;78788:7;:14;78774:29;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;78774:29:0;-1:-1:-1;78754:49:0;-1:-1:-1;78810:25:0;;;;;78975:1023;78999:7;:14;78995:1;:18;78975:1023;;;79041:14;79056:1;79041:17;;;;;;;;;;;;;;79029:29;;79079:10;79090:1;79079:13;;;;;;;;;;;;;;79067:25;;79114:7;79122:1;79114:10;;;;;;;;;;;;;;;;;;;79161:27;;;;;;;;:16;:27;;;;;;;;;;;;-1:-1:-1;79114:10:0;-1:-1:-1;79202:22:0;;;79198:793;;;79260:1;79237:17;79255:1;79237:20;;;;;;;;;;;;;;;;;:24;79272:16;79291:25;:10;79306:9;79291:25;:14;:25;:::i;:::-;79272:44;;79327:26;79356:8;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79356:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79356:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;79356:29:0;;-1:-1:-1;79400:29:0;;;79396:121;;;79459:4;79444:19;;79487:18;79476:29;;79396:121;79561:283;79595:16;:27;79612:9;79595:27;;;;;;;;;;;;;;;;;;;;;;;;;79635:9;79720:52;79745:8;:24;;;:26;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79745:26:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79745:26:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;79745:26:0;79720:20;:8;79733:6;79720:20;:12;:20;:::i;79561:283::-;;79198:793;;;;;79894:25;:9;79908:10;79894:25;:13;:25;:::i;:::-;79871:17;79889:1;79871:20;;;;;;;;;;;;;:48;;;;;79944:37;79960:17;79978:1;79960:20;;;;;;;;;;;;;;79944:11;:15;;:37;;;;:::i;:::-;79930:51;;79198:793;79015:3;;78975:1023;;;;78417:1586;;;;;;;;;;;:::o;24156:183::-;24236:18;24240:4;24246:7;24236:3;:18::i;:::-;24228:64;;;;-1:-1:-1;;;24228:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24303:20;;24326:5;24303:20;;;;;;;;;;;:28;;;;;;24156:183::o;23898:178::-;23976:18;23980:4;23986:7;23976:3;:18::i;:::-;23975:19;23967:63;;;;;-1:-1:-1;;;23967:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;24041:20;;:11;:20;;;;;;;;;;;:27;;;;24064:4;24041:27;;;23898:178::o;28445:810::-;28505:4;29164:20;;29007:66;29204:15;;;;;:42;;-1:-1:-1;29223:23:0;;;29196:51;-1:-1:-1;;28445:810:0:o;81610:361::-;81706:14;81735:12;81731:52;;81760:13;;81731:52;81868:5;;81861:49;;81868:5;;81888:12;81902:7;81861:49;:26;:49;:::i;:::-;81945:12;81928:35;;;:37;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81928:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81928:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81928:37:0;;81610:361;-1:-1:-1;;;81610:361:0:o;52837:29915::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52837:29915:0;;;-1:-1:-1;52837:29915:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Swarm Source

bzzr://51c4fdcd9f1bbf5db6b87ac9afb84770f1f76dfe1400ee5ff128ff170945c929
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.